3

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

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 模型的视图(return View(new MyModelImplementation(){...});),我在屏幕上看到的结果是:

在此处输入图像描述

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

在此处输入图像描述

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

  • (预期)对于 Lambda 助手,DisplayName 取自 IMyModel
  • (意外)对于字符串表达式,所有元数据都取自 MyModelImplementation 类(换句话说,如果您使用 Html.DisplayNameFor(m=>m.MyIntProperty) - 它显示来自接口的元数据(视图中声明的模型类型),但是如果您使用 Html .DisplayName("MyIntProperty") 它使用 model.GetType()) 的元数据。
  • (意外)所有验证规则和字符串总是取自 MyModelImplementation (model.GetType()) 元数据,而不是声明的模型类型 (IMyModel)。
  • (预期)对于字符串表达式帮助器模型的属性仅在传递给视图的模型为 NULL 的情况下取自接口
  • (意外)对于字符串表达式助手 SubModel 的属性元数据根本不被检索/尊重,以防传递给视图的模型为 NULL

问题:

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

4

1 回答 1

0

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

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

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

于 2013-04-12T22:45:11.470 回答