3

我有一个基本视图模型,其 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的值,而不仅仅是一个字符串?有没有办法改变这种行为?当我尝试将其解析为预期的类型时,它会导致问题。

4

2 回答 2

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);
            }

        }

    }

}
于 2013-04-09T12:23:58.737 回答
1

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

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

public abstract class BaseViewModel
{
    public virtual string Id { get; set; }
}
于 2013-04-08T19:17:26.947 回答