0
votes

I am currently using model binding and ASP.NET MVC 3 and .NET 4.0.

  1. View Model Class:

    public class BasicViewModel 
    {
        [Display(Name = @"Names")]
        [Required(ErrorMessage = @"Names is required")]
        [DisplayFormat(ConvertEmptyStringToNull = true)]
        List<string> Names { get; set; }
    
        [Display(Name = @"Email")]
        [Required(ErrorMessage = @"Email is required")]
        string Email { get; set; }
    
    }
    
  2. Controller

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult NameEmail( BasicViewModel basicModel)
    {
          // some manipulation of data
    }
    
  3. View in cshtml file (razor view engine)

     // model declared here using @model BasivViewModel
     // only required part shown labels part of code removed
     @Html.TextBoxFor(model => model.Names)
     ...
     @Html.TextBoxFor(model => model.Email)
     ...
    

The model binding provided by ASP.NET MVC binds the string Email to null if it is empty but binds the List Names to empty string (""). I want it to be null. I made the binding work using JavaScript by parsing the values of form fields on click of submit button. But i want the asp.net model binding to do this. Furthermore, it would be great if there is some field in Data Annotations class like Required for this functionality. I tried this Null Display Text Property and refer to the remarks section. Is there a solution or is this how it is implemented?. I am not sure whether i have understood this part of model binding correctly.

1
with lots of duplicate : consider stackoverflow.com/questions/12487188/… - Vishal Sharma
@vishalsharma may i know how the above link solves the problem? I know how to model bind to the list. It would be great if you could provide some explanation on how the link solves the problem. - Sudarsan GP
hanselman.com/blog/… read this one.. if you don't understand tell me i'll surely help - Vishal Sharma
@vishalsharma from the article it is clear that the index for the list needs to be continuous. But i guess i am missing the link between that article and how the List Names binds to empty string instead of null which is not the case in string email. - Sudarsan GP
can you please tell me what values are available in request.form during posting .. - Vishal Sharma

1 Answers

0
votes

By default, if the field, representing an array, is in the html, the controller will receive an array of length 0. However, to make the array null, you can define a custom ModelBinder.

public class MyModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(List<string>))
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;
            // Check to see if any of the elements the array is not empty and
            // returns null if they all are.
            return request.Form.GetValues("Names").Any(x => !string.IsNullOrWhiteSpace(x)) ?
                base.BindModel(controllerContext, bindingContext) :
                null;
            //You can also remove empty element from the array as well, by using
            // a where clause
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

Alternatively, you can also implement IModelBinder instead of DefaultModelBinder.

The next step is to register the custom binder in your Application_Start function in the Global.asax.cs file.

ModelBinders.Binders.Add(typeof(List<string>), new MyModelBinder());

This basically tells the mvc engine to use the MyModelBinder whenever the field is List<string>

To know more about modelbinder, goolge "MVC custom model binding". Let me know you go :)