Way to Avoid ASP.NET UpdateModel Magic Strings

Using the UpdateModel in an ASP.NET MVC or Web API controller allows for the specification of the fields of the model to bind data from the client to a model class in an application. The default is to try and bind all fields the of the model to a field in the client request. However, this can lead to problems.

UpdateModel Problem Discussion

TThe problem is that this opens up the opportunity for a client to post data that should not be changed by manipulating the data on the client by some method - which is not hard to do as all the browsers provide developer tools that allow for complete access to the data, scripts, and document interface on the client.

In order to help with controlling what is bound from the client, it is best to specify the list of items in the UpdateModel (or TyyUpdateModel) method of a controller. However, this can be tedious as normally, it is specified with a list of strings (“magic” strings) that correspond to the fields of the model class that are to be bound. These “magic” strings are an easy source for errors as they can be mistyped, a field may be forgotten, or a field name may changed/removed/added. This is not a safe way to program.

Compiled String Builder

In order to get around this problem, I began thinking of how I could have .Net give me the list of properties on a model so that I would not have to rely on these “magic” strings. I quickly settled on using reflection and lambda expressions to enable the program building of the list of strings. This way, I could have a compile time check of the strings to be included in the UpdateModel binding. Strings are still being passed to the UpdateModel as a string array, but these are generated from the actual properties on the model.

The basic definition and usage of the UpdateModel method is:

UpdateModel<TModel>(TModel, String[])

//where it is called using "magic" strings on a Movie model object
UpdateModel(movie, new string[] { "Name", "ReleaseDate" });

It would be preferable (if it were possible) to be able to refer to actual compile time properties when specifying what part of the model to update:

//if it were possible....
UpdateModel(movie, new string[] { Movie.Name, Movie.ReleaseDate });

Since we cannot do this, I came up with a way to specify field lists using lambda expressions that actually do not require the developer to enter any strings. The field lists can be built using the ModelBinderBuilder class. Once this is built, the ModelBinderBuilder will contain a field array that can be passed to the UpdateModel method.

Basic usage of the ModelBinderBuilder class:

var bindFields = ModelBinderBuilder<Movie>.Get()
    .Add(x => x.NumberAvailable)
    .Add(x => x.GenreId)
    .Add(x => x.Name)
    .Add(x => x.Id);

//will pass ["NumberAvailable", "GenreId", "Name", "Id"] for field list
UpdateModel(movie, bindFields.Fields); 

//ModelBinderBuilder also provides a Remove method and a All (adds all properties) method.
var bindFields = ModelBinderBuilder<Movie>.Get()
    .All()
    .Remove(x => x.Id);

//will pass ["NumberAvailable", "GenreId", "Name"] for field list
UpdateModel(movie, bindFields.Fields);

Of course, this need not be done with every call to a controller action. Instead the builder part of the above code can be placed in the static constructor of the controller and the fields object added as a static property of the controller. Now the list would be built once and then reused throughout the life of the application instance by referring to the static property. We can define field lists for various action such as create, update, delete, etc.

Hopefully you find this functionality useful in your development.

Source Code

    Tom Klopfstein avatar
    About Tom Klopfstein
    Tom is a software developer who enjoys learning new things and trying to fix what's broken.
    comments powered by Disqus