使用接口作为部分视图+数据注释的模型类型

时间:2012-03-27 20:29:43

标签: asp.net-mvc-3 interface data-annotations partial-views

我有一种情况,复杂的局部视图需要根据部分视图的使用位置进行不同的字段验证。

我认为我可以通过使局部视图将接口作为模型类型并基于接口实现两个不同的ViewModel来解决这个问题。两个ViewModel中的数据注释会有所不同。然后,我将向部分视图提供正确的ViewModel的实例。

但我发现,唯一被识别的注释是界面本身的注释。实现ViewModel类的接口上的DA被忽略,即使这些是作为模型传递的对象。所以我的计划不起作用。

有解决方法吗?更好的方法?如果可以避免,我宁愿不将局部视图拆分为单独的视图。

ETA:这是部分视图的缩写版本,如要求:

@model IPerson
@Html.ValidationSummary(false)
<fieldset>
    <table class="editForm">
        <tr>
            <td class="editor-label">
                @Html.LabelFor(model => model.FirstName)
            </td>
            <td class="editor-field">
                @Html.EditorFor(model => model.FirstName)
                @Html.ValidationMessageFor(model => model.FirstName)
            </td>
            <td class="editor-label">
                @Html.LabelFor(model => model.LastName)
            </td>
            <td class="editor-field">
                @Html.EditorFor(model => model.LastName)
                @Html.ValidationMessageFor(model => model.LastName)
            </td>
        </tr>
     </table>
  <fieldset>

真实的局部视图很长,并且有很多@if语句管理可选部分的渲染(或不渲染),但它没有做任何棘手的事情。

3 个答案:

答案 0 :(得分:3)

我的想法不起作用:this thread提醒我,课程不会从其界面继承属性。 (正如答案所指出的,如果两个接口指定具有不同属性的相同属性,并且两者都由一个类实现,会发生什么?)

它可能适用于公共基类。我明天会试试。

谢谢大家。

答案 1 :(得分:2)

安,你是对的。我删除了我的评论。您无法通过视图发布界面。但是,我不知道你到底想要做什么,因为我看不到你的代码。也许是这样的?我正在将一个接口传递给视图,但是将它作为我期望的类传回去。同样,我不确定应用程序是否在这里。

假设你有这样的课程

[MetadataType(typeof(PersonMetaData))]
public class Customer : IPerson {
    public int ID { get; set; }
    public string Name { get; set; }
     [Display(Name = "Customer Name")]
    public string CustomerName { get; set; }
}

public class Agent : IPerson {
    public int ID { get; set; }
    public string Name { get; set; }
}

public partial class PersonMetaData : IPerson {
    [Required]
    public int ID { get; set; }

    [Required]
    [Display(Name="Full Name")]
    public string Name { get; set; }
}

public interface IPerson {
    int ID { get; set; }
    string Name { get; set; }
}

public interface IAgent {
    int AgentType { get; set; }
}

public interface ICustomer {
    int CustomerType { get; set; }
}

您的控制器看起来像

    public ActionResult InterfaceView() {
        IPerson person = new Customer {
            ID = 1
        };
        return View(person);
    }

    [HttpPost]
    public ActionResult InterfaceView(Customer person) {
        if (ModelState.IsValid) {
            TempData["message"] = string.Format("You posted back Customer Name {0} with an ID of {1} for the name: {2}", person.CustomerName, person.ID, person.Name);
        }
        return View();
    }

您的视图看起来像这样

@model DataTablesExample.Controllers.Customer

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@if (@TempData["message"] != null) {
    <p>@TempData["message"]</p>
}

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>IPerson</legend>

        @Html.HiddenFor(model => model.ID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.CustomerName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.CustomerName)
            @Html.ValidationMessageFor(model => model.CustomerName)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

答案 2 :(得分:1)

嗯,实际上你有一个非常合理的想法!如果您使用HtmlHelper方法的非泛型版本(例如“@ Html.Editor”而不是“@ Html.EditorFor”),则可以归档,因为通用版本会重新创建ModelMetadata(我不知道为什么!)基于泛型参数类型,不要使用视图的ModelMetadata。吓坏了,不是吗?

希望得到这个帮助。