ASP.NET MVC - 模型的元数据,用于从模型对象类型而不是视图的声明模型

时间:2013-04-09 04:23:41

标签: asp.net asp.net-mvc asp.net-mvc-4 modelmetadata modelmetadataprovider

我声明了一个模型的接口,实现了它的类:

public interface IMyModel
{
    [Range(1, 1000)]
    [Display(Name = "ModelProp From Interface")]
    int MyIntProperty { get; set; }
    IMySubModel SubModel { get; }
}

public interface IMySubModel
{
    [Range(1,1000)]
    [Display(Name = "SubModelProp From Interface")]
    int MyIntSubProperty { get; set; }
}

我还有模型实现,具有不同的元数据:

public class MyModelImplementation:IMyModel
{
    [Display(Name = "ModelProp From Class")]
    [Range(1, 15)]
    public int MyIntProperty
    {
        get;
        set;
    }
    public IMySubModel SubModel { get; set; }
    public MyModelImplementation()
    {
        SubModel = new MySubModelImplementation();
    }
}

public class MySubModelImplementation: IMySubModel
{
    [Display(Name = "SubModelProp From Class")]
    [Range(1, 15)]
    public int MyIntSubProperty
    {
        get;
        set;
    }
}

我有View,我使用这个模型界面:

@model MvcApplicationModelInterface.Models.IMyModel
@using (Html.BeginForm())
{
    <p>Using Lambda Expression:</p>

    @Html.DisplayNameFor(m=>m.MyIntProperty)
    @Html.EditorFor(m=>m.MyIntProperty)
    @Html.ValidationMessageFor(m=>m.MyIntProperty)
    <br/>
    @Html.DisplayNameFor(m=>m.SubModel.MyIntSubProperty)
    @Html.EditorFor(m=>m.SubModel.MyIntSubProperty)
    @Html.ValidationMessageFor(m=>m.SubModel.MyIntSubProperty)
    <br/>

    <p>Using String Expression:</p>

    @Html.DisplayName("MyIntProperty")
    @Html.Editor("MyIntProperty")
    @Html.ValidationMessage("MyIntProperty")
    <br/>
    @Html.DisplayName("SubModel.MyIntSubProperty")
    @Html.Editor("SubModel.MyIntSubProperty")
    @Html.ValidationMessage("SubModel.MyIntSubProperty")
    <br/>
    @Html.ValidationSummary(true)
    <br/>
    <input type="submit" name="btnSubmit" value="btnSubmit" />
}

我有控制器正确绑定和初始化模型:

    [HttpGet]
    public ActionResult Index()
    {
        ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
        var model = new MyModelImplementation();
        model.MyIntProperty = 111;
        model.SubModel.MyIntSubProperty = 222;
        return View(model);
    }

    [ActionName("Index"), HttpPost]
    public ActionResult Save([ModelBinder(typeof(MyModelBinder))]IMyModel model)
    {
        return View(model);
    }

    public class MyModelBinder : DefaultModelBinder
    {
        protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
        {
            return new MyModelImplementation();
        }
    }

问题:

如果在控制器的操作中返回带有NOT NULL模型的视图(返回View(新的MyModelImplementation(){...}); ),我在屏幕上看到的结果是:

enter image description here

但是,如果控制器的操作返回带有null模型的结果(返回View(null); ),则结果为:

enter image description here

正如您所看到的,Lambda html帮助程序和字符串表达式帮助程序的行为是不同的,并且这些行为都不是一致的,并且某些行为看起来像一个错误:

  • (预期)对于Lambda助手,DisplayName取自IMyModel
  • (意外)对于String表达式,所有元数据都来自MyModelImplementation类 (换句话说,如果使用Html.DisplayNameFor(M =&GT; m.MyIntProperty) - 它示出了从接口鉴于声明(型号类型)元数据,但是如果使用Html.DisplayName(“MyIntProperty”)它使用模型的元数据.GetType())。
  • (意外)所有验证规则和字符串始终从MyModelImplementation(model.GetType())的元数据取,代替声明的模型类型(IMyModel)。
  • (预期)对于字符串表达式helper Model的属性仅在传递给视图的模型为NULL时从Interface获取
  • (意外)对于字符串表达式,如果传递给view的模型为NULL,则根本不会检索/遵守SubModel的属性元数据

问题:

此ASP.NET MVC错误/功能的最佳解决方法是什么?如何强制Html扩展始终使用模型类型中的元数据默认情况下在视图中声明?我尝试使用MetadataTypeAttribute,但在这种情况下,实现模型的人将获得覆盖接口中指定的原始元数据的自由,我不想允许。所以我宁愿寻找一些自定义的ModelMetadataProvider实现。在MetadataType的情况下,也不遵守某些元数据属性,例如RequiredAttribute。

1 个答案:

答案 0 :(得分:0)

我不相信Editor()EditorFor()之间的区别是一个错误。我认为这是因为EditorFor()可以访问强类型模型的类型信息,而编辑器必须使用反射来获取类型,它返回实际类型而不是使用的接口类型。

我认为您所看到的是强类型版本具有更多上下文并且可以获取界面信息而不必简单地调用GetType()

验证工作正常,因为您告诉模型绑定器绑定到绑定到MyModelImplementation的MyModelBinder。验证基于您要发布的方法及其所需的参数。