adamkdean

software engineering

Remove params from URL in JavaScript

By Adam K Dean on

Let us say the param we want to remove is session and our URL is http://www.example.com/?session=lasgfnasolgnasgn&id=500&other=100. We can remove it like so:

var oldUrl = "http://www.example.com/?session=lasgfnasolgnasgn&id=500&other=100";
var newUrl = oldUrl.replace(/&?session=([^&]$|[^&]*)/gi, "");
console.log(newUrl);

http://www.example.com/?id=500&other=100

Now let's say we also want to remove other from that URL, we can do that like this:

var oldUrl = "http://www.example.com/?session=lasgfnasolgnasgn&id=500&other=100";
var newUrl = oldUrl.replace(/&?((session)|(other))=([^&]$|[^&]*)/gi, "");
console.log(newUrl);

http://www.example.com/?id=500

Excellent.

Invoke callbacks with unknown arguments

By Adam K Dean on

Whilst working on some instrumentation code, I had need to pass a function and an unknown number of arguments to another function which would then time the execution of that function. This turned out to be quite easy using fn.prototype.apply.

Let's say that we want to call a function but execute some other code, we'd do that here:

function invokeCallback(callback) {
  var params = Array.prototype.slice.call(arguments, 1);
  return callback.apply(null, params);
}

And here are our three varied functions:

function action() {
    console.log('action');
}

function greet(msg) {
    console.log(msg);
}

function nameage(name, age) {
    var msg = 'My name is ' + name + ' and my age is ' + age;
    console.log(msg);
}

And here is how we can call them dynamically without invokeCallback having to know anything about them:

invokeCallback(action);
invokeCallback(greet, 'Hello!');
invokeCallback(nameage, 'Bob', '20');

Amazing.

Cloning objects in JavaScript

By Adam K Dean on

Just a quick snippet post today.

A great way to clone objects in JavaScript and break references is to serialize and deserialize the object. The process of converting it to a JSON string and back into an object severs any references. Unfortunately, it also breaks certain types such as Date and probably RegEx too.

var clone = JSON.parse(JSON.stringify(original));

A better way (I've found) to clone objects while retaining types is to use jQuery.extend.

// Shallow copy
var newObject = jQuery.extend({}, oldObject);

// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);

There are other, quicker ways, but when you can run 120,000 deep copies a second, is that extra microsecond really worth it?

No MediaTypeFormatter is available

By Adam K Dean on

You may have come across the error message No MediaTypeFormatter is available to read an object of type T from content with media type 'text/plain'. during your adventures in ASP.NET Web API. Tonight it was my turn to be faced with this bothersome little 'issue'.

I was attempting to post {Username:"testuser", Password:"testpass"} to an API controller which received a ViewModel like so:

public class UserViewModel
{
    public string Username { get; set; }
    public string Password { get; set; }
}

public HttpResponseMessage Post(UserViewModel value)
{
    // do something
}

The only problem was that it just wasn't finding the controller action. Spitting out error messages and generally being counter-productive.

After going through lots of StackOverflow posts and dismissing them, it turned out the first one was actually relevant. I was using a Chrome extension (Postman) to help with REST calls and even though I had selected JSON, it was still sending requests as plain/text, and not application/json.

I set the Content-type header to application/json and it started working.

Force JSON with WebAPI

By Adam K Dean on

Sometimes when you call a WebAPI through the browser, you'll be served XML. This may make it easier to read, but it's really not helping us when all we really want is JSON. Putting the following snippet into the end of Application_Start() in Global.asax.cs will force your WebAPI application to always send JSON.

GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());

As simple as that.