【问题标题】:Using an interface as the model type of a partial view + data annotations使用接口作为局部视图的模型类型+数据注释
【发布时间】:2012-03-27 20:29:43
【问题描述】:

我有一个案例,复杂的局部视图需要不同的字段验证,具体取决于使用局部视图的位置。

我想我可以通过让局部视图将接口作为模型类型并基于该接口实现两个不同的 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 语句管理可选部分的呈现(或不呈现),但它并没有做任何棘手的事情。

【问题讨论】:

  • 你能发布部分视图吗?
  • @mattytommo 这页很长,但我会尝试提供一个缩写版本。

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


【解决方案1】:

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

它可能适用于通用基类。我明天试试。

谢谢大家。

【讨论】:

  • @chrfin 我想我没有。不幸的是,很久以前我不记得我最终是如何处理这个问题的,而且我不再可以访问源代码。抱歉,我无法提供更多帮助。
【解决方案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>
}

【讨论】:

  • 这与我试图做的很接近,除了我的观点将 IPerson 而不是 Customer 作为模型类型。这是因为我希望能够将两个不同的派生类(具有不同的元数据)传递给视图。但这不起作用:派生类的元数据被忽略了。在考虑了一夜之后,我认为我会将视图中的一些常见复杂内容分解为较小的局部视图,并拥有两个视图,而不是试图在模型之间共享一个视图。非常感谢您的 cmets 和您的回答!
  • You can't post an interface back through your view. 没有任何意义。您的意思是不能将值发布到采用接口的方法吗?您当然可以使用自定义模型绑定器。另外,仅仅因为你使用Model/Interface-A创建视图,绝对不代表控制器上的post方法必须使用Model/Interface-A作为参数。
【解决方案3】:

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

希望对您有所帮助。

【讨论】:

  • 确实,我可以确认使用非*For() 版本的方法可以正常工作。例如使用 Html.textBox("Name", Model.Name) 而不是 html.TextBoxFor(m => m.Name)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-26
  • 2021-06-24
  • 2020-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多