2013-04-08 106 views
3

我有类型的对象的ID属性基本视图模型MVC模型绑定子类对象属性(所以我可以有它是int或GUID),如下所示:填充有字符串数组

public abstract class BaseViewModel 
{ 
    public virtual object Id { get; set; } 
} 

<input id="Id" name="Id" type="hidden" value="240" /> 
<input id="FirstName" name="FirstName" type="text" value="John" /> 
<input id="LastName " name="LastName " type="text" value="Smith" /> 

当submi:和视图模型因此,从这

public class UserViewModel : BaseViewModel 
{ 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
} 

我的HTML则呈现为派生tted到MVC行动:

[HttpPost] 
    public ActionResult EditUser(UserViewModel model) 
    { 
     ...code omitted... 
    } 

值的模特属性是:

Id: string[0] = "240" 
FirstName: string = "John" 
LastName: string = "Smith" 

我的问题是,为什么我得到一个一个项目字符串数组作为价值标识 ,而不只是一个字符串?有没有办法改变这种行为?当我尝试将其解析为预期类型时,会导致问题。

+0

尝试检查,如果你有两个项目具有相同的名称。当发生这种情况时,值作为数组发送到服务器 – pollirrata 2013-04-08 19:07:52

+0

这个问题是类似的:http://stackoverflow.com/questions/6809159/ms-mvc3-model-binding-an-object,虽然它没有答案,OP发现相同的问题:获取数组映射到属性定义为'object' – Faust 2013-04-08 19:24:28

回答

1

问题在于输入你的id属性为object - 不知道默认绑定应该如何在这里工作,但由于对象可能是任何东西 - 就像一个复杂的对象本身具有多个属性 - 可能会尝试将所有找到的属性转储到数组中?

如果Id并不总是将是一个整数,我建议你输入这个字符串,因为该模型绑定机制应该没有问题映射几乎任何通过HTTP发送的字符串,那么:

public abstract class BaseViewModel 
{ 
    public virtual string Id { get; set; } 
} 
+0

我认为这是一个好主意,但我不能使用它,因为我使用表达式树将视图模型绑定到entitymodel,它不会允许int字符串绑定。否则我相信这会很好。 – CodeGrue 2013-04-08 19:49:06

2

我结束了与处理“ID”对象属性作为一个特殊的情况下,自定义模型粘合剂解决这个:

public class CustomModelBinder : DefaultModelBinder 
{ 
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     // apply the default model binding first to leverage the build in mapping logic 
     base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 

     // since "Id" is a special property on BaseViewModel of type object, 
     // we need to figure out what it should be and parse it appropriately 
     if (propertyDescriptor.Name == "Id" && propertyDescriptor.PropertyType == typeof(object)) 
     { 
      // get the value that the default binder applied 
      var defaultValue = propertyDescriptor.GetValue(bindingContext.Model); 

      // this should be a one element string array 
      if (defaultValue is string[]) 
      { 
       var defaultArray = defaultValue as string[]; 

       // extract the first element of the array (the actual value of "Id") 
       var propertyString = defaultArray[0]; 
       object value = propertyString; 

       // try to convert the ID value to an integer (the most common scenario) 
       int intResult; 
       if (int.TryParse(propertyString, out intResult)) 
       { 
        value = intResult; 
       } 
       else 
       { 
        // try to convert the ID value to an Guid 
        Guid guidResult; 
        if (Guid.TryParse(propertyString, out guidResult)) value = guidResult; 
       } 

       // set the model value 
       propertyDescriptor.SetValue(bindingContext.Model, value); 
      } 

     } 

    } 

}