Asp.net mvc 从另一个模型派生模型

Asp.net mvc 从另一个模型派生模型,asp.net-mvc,oop,models,Asp.net Mvc,Oop,Models,在我的ASP.NETMVC3项目中,我希望有一个基类模型对象,该对象具有某些属性,然后我将在我的应用程序中的所有其他模型(或至少大多数模型)中使用这些属性。这样,使用这些派生模型的视图也将具有基类模型属性 基类模型属性可以在中设置,比如基类控制器,然后我需要用相同的数据填充派生模型。有没有关于如何最好地完成“er”的建议 或者我应该考虑以某种方式创建自己的DefaultModelBinder吗?我对这里的选择有点困惑。好像你说不出来似的。:) 示例代码 基本模型 导出模型 所以在基本控制器中 在

在我的ASP.NETMVC3项目中,我希望有一个基类模型对象,该对象具有某些属性,然后我将在我的应用程序中的所有其他模型(或至少大多数模型)中使用这些属性。这样,使用这些派生模型的视图也将具有基类模型属性

基类模型属性可以在中设置,比如基类控制器,然后我需要用相同的数据填充派生模型。有没有关于如何最好地完成“er”的建议

或者我应该考虑以某种方式创建自己的DefaultModelBinder吗?我对这里的选择有点困惑。好像你说不出来似的。:)

示例代码

基本模型

导出模型

所以在基本控制器中

在导出的控制器动作方法中


这稍微取决于您谈论的是传入模型还是传出模型(即提供的viewmodel或通过表单发布的模型参数)

在前一种情况下,按照你的建议做很容易;通过一个基本控制器,在操作执行之前或之后(覆盖OnActionExecuting或OnActionExecuted)填充带有公共信息的模型。您还可以使用ActionFilter,它可能更灵活,因为它不需要您为所有控制器遵循一个继承链。出于这个原因,我倾向于推荐后一种方法


在表单发布端,您可能需要创建自己的模型活页夹,但前提是您有理由希望在多个类型的模型中执行单个操作,坦率地说,这可能会有问题。在这种情况下,您必须将实际的类型名放入一个隐藏的elemetn或其他形式中,以便您的模型绑定器能够确定要实例化的模型。除非你有令人信服的理由,否则我建议你不要使用这种方法。

如果你在所有视图中都需要这种“公共数据”,我不会将继承加入其中。 我会选择一种扩展方法

大致如下:

public static CommonData GetCommonData(this HtmlHelper htmlhelper)
        {
            // do your magic here
        }
在您看来,您可以简单地调用:

@Html.GetCommonData()...
这样你的模型就更干净了

继承可能是一种有效的方法,如果这个公共数据真的“适合”您的模型类

如果您提供一些示例,将会有所帮助;-)

**编辑**

我会将您的“BaseModel”作为属性保留在控制器中,并按照您的建议在OnActionExecuting上填充它

但是我会在控制器和Html助手上使用ExtensionMethods来访问数据。 如果您使用继承,您将不必要地使事情复杂化

如果您需要扩展方法的示例,请告诉我

这种方法是枯燥的。您没有复制代码

**编辑2**

下面是您的扩展方法应该是什么样子:(我不知道,所以它可能无法编译)

确保控制器派生自添加BaseModel属性的控制器类。我在上面称它为“你的控制器”

那你就可以走了;-)

编辑3

提醒您,如果要在视图中使用扩展方法,则需要知道名称空间。 实现这一点的最佳方法是在视图文件夹的Web.Config中包含名称空间

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="Yournamespace" /> <- LOOK HERE
      </namespaces>
    </pages>
  </system.web.webPages.razor>


嗨,保罗,谢谢你的快速回复。我认为我们这里只讨论输入模型/视图模型。我将使用基本模型属性触发页面上的某些显示(例如model.IsAdministrator)。好的,所以我理解如何在基本控制器中使用重写的(这是一个词吗?)OnActionExecuting方法。我将有一个模型类作为这个控制器的私有成员,并相应地填充它的属性。如何将基础模型属性放入从它派生的模型中。请参阅上面原始问题中我更新的代码示例。对于这一点,我认为最简单的方法是使用OnActionExecuted,因为这样您就可以从作为filterContext参数一部分的ActionResult中提取模型。这样,如果它不是ViewResult,您可以保存自己查找不需要的数据。至于获取数据,您可以像获取其他数据一样获取数据,让您的基本控制器(通过注入或构造函数参数)对您的数据访问层进行一些引用,并且它可以查询信息。或者如果信息是派生出来的,就派生出来。我知道,我知道。。。当时我想不出任何有用的例子。我想我已经很好地解决了这个问题,虽然在我最近的更新上面。底线是,我需要在我的大多数模型上访问强类型属性,但本着DRY的精神,我希望将填充这些属性的代码保存在一个地方(我认为是一个基本控制器)。在我最初的帖子中添加了更多细节(我希望如此)。感谢您的温和提醒。如果我使用您(最初)推荐的方法,点击数据库来提取这些公共属性,那么如果我在一个视图中调用同一属性(比如10次),会发生什么?然后我会点击数据库10次,对吗?不!如果实现正确,您将只访问数据库一次。您将在OnActionExecuting中填充控件属性中的数据。无论调用PropertyInteresting方法多少次,数据库都不会再次被命中。我会调查的。谢谢当我得到一个有效的解决方案时,我会回复。
public ActionResult Index()
{
    // Derives from the base model in the base controller
    UserModel model = new UserModel();

    // model.IsAdministrator where IsAdministrator is a property of the base Model not UserModel

    return View(model);
}
public static CommonData GetCommonData(this HtmlHelper htmlhelper)
        {
            // do your magic here
        }
@Html.GetCommonData()...
public static class ExtensionHelpers
{
    public static BaseModel GetCommonData(this HtmlHelper htmlhelper)
    {
        YourController HtmlHelper = htmlhelper.ViewContext.Controller as YourController;
        if (controller != null)
        {
            return HtmlHelper.BaseModel;
        }
        return null;
}
  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="Yournamespace" /> <- LOOK HERE
      </namespaces>
    </pages>
  </system.web.webPages.razor>