MVC Model Binding子类对象属性,用字符串数组填充

时间:2013-04-08 18:54:43

标签: asp.net-mvc model-binding

我有一个基本视图模型,其Id属性类型为object(所以我可以将它设置为int或Guid),如下所示:

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

因此,视图模型来源于此

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

然后我的HTML呈现为:

<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" /> 

当提交给MVC行动时:

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

模型属性的值为:

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

我的问题是,为什么我会将一项字符串数组作为 Id 的值,而不仅仅是一个字符串?有没有办法改变这种行为?当我尝试将其解析为期望的类型时,它会导致问题。

2 个答案:

答案 0 :(得分: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);
            }

        }

    }

}

答案 1 :(得分:1)

问题在于将您的id属性键入为object - 不确定默认绑定应该如何在这里工作,但由于对象可能是任何东西 - 比如具有多个属性本身的复杂对象 - 也许它试图将它找到的所有属性转储到数组中?

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

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