Skip to main content

Breaking? Change In Asp.Net MVC2

In MVC1, by default an empty textbox was sent as string.Empty to the controller on POST. In MVC2, it now sends the value as NULL. See ModelMetadata.ConvertEmptyStringToNull. I think there are some valid reasons for why they made the change – see Brad Wilson’s comment for more. If your system relies on string.Empty, you’ve got a problem.

There are several options for handling this. The first is using the DisplayFormatAttribute on every property that needs it. Painful. Here’s an example:

[DisplayFormat(ConvertEmptyStringToNull=false)]
public string FirstName { get; set; }

You can also write a custom binder that sets this value to false. Like so:

public class CustomStringModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {

        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);   
        if (bindingContext.ModelType == typeof(string))
        {   
            bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
            if (value == null || string.IsNullOrEmpty(value.AttemptedValue))   
                return "";
        }
        return value.AttemptedValue;
    }
}

You’ll need to add the following to the Global.asax Application_Start method to use your custom model binder.

ModelBinders.Binders.Add(typeof(string), new CustomStringModelBinder());

One thing to note, if you use the RequiredAttribute, you don’t need to worry about the null because it will invalidate the model based on the NULL.

Which option is better? Neither. Simply pick the default for ConvertEmptyStringToNull and then use DisplayFormat to handle the exceptions. Not perfect but not bad.

I do wish that this was configurable in some way instead of creating a ModelBinder.

Comments

Thanks for this tip. I was able to use a more concise version of the above:

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{ bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;

return base.BindModel(controllerContext, bindingContext);
}

Popular posts from this blog

Migrating Legacy Apps to the New SimpleMembership Provider

Asp.Net MVC4 uses the new SimpleMembership provider, changes the table structure and adds a new hashing algorithm. The reasons for the changes can be found in this article by Jon Galloway. This article shows how to migrate your existing apps to the new provider.I’m assuming that you stored your passwords in the unrecoverable SHA-1 format. If you didn’t, then you’ll have to change a couple of things. All of my apps are done this way so… I’m also assuming that you have created the basic skeleton of the new app and ran it once so the correct tables will be created.First, we’ll look at the new tables. Previously, we had all of those aspnet_xxxxxx tables. Here’s the new ones.UserProfileContains all of the elements relevant to the user. This is a combination of the aspnet_Users table and the aspnet_Profiles table.webpages_MembershipStores the password info when not using OAuth, Live, Facebook, etc. This table is somewhat of a match to the aspnet_Membership table.webpages_OAuthMembershipStor…

JavaScript function to automatically add slashes to date

In converting an old Windows app to a browser app, the user wanted to be able to enter dates without the slashes. Here's a simple jscript: 1:// Function to convert short date string (MMddyy) 2:// or (MMddyyyy) to a date string (mm/dd/yyyy). 3:// txtBox is the actual textbox control 4:// with the value to be processed. 5:function FixShortDate(txtBox) { 6:if (txtBox == null) { 7:return'' } 8: 9:var re = new RegExp(/(\d{6})(\d{2})?/); 10: 11:if (re.test(txtBox.value)) 12: { 13:if (txtBox.value.length == 8) { 14: txtBox.value = txtBox.value.substring(0, 2) + '/' + txtBox.value.substring(2, 4) + '/' + txtBox.value.substring(4, 8) 15: } 16: 17:if (txtBox.value.length == 6) { 18:if (txtBox.value.substring(4, 6) < 20)