从另一个模型导出模型

时间:2011-01-25 15:35:12

标签: asp.net-mvc oop models

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

可以在基类控制器中设置基类模型属性,然后以某种方式我需要使用相同的数据填充派生模型。关于如何最好地完成任何建议?

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

示例代码

基本模型

public class ElkModel
{
    public bool IsAdministrator { get; set; }
}

派生模型

public class UserModel : ElkModel
{
    [HiddenInput]
    public int User_ID { get; set; }

    // Other properties specific to this model
}

所以在基本控制器中

private BaseModel baseModel;

protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    baseModel = new baseModel();
    baseModel.MyProperty = "test";

    base.OnActionExecuting(filterContext);
}

并在派生控制器操作方法

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);
}

2 个答案:

答案 0 :(得分:2)

如果你需要在所有视图中使用这个“公共数据”,我不会在混合中抛出继承。 我会选择一种扩展方法。

有些事情:

public static CommonData GetCommonData(this HtmlHelper htmlhelper)
        {
            // do your magic here
        }

在您的视图中,您只需致电:

@Html.GetCommonData()...

这样可以保持模特的清洁。

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

如果你提供了一些例子,它会有所帮助; - )

**编辑**

我会将你的'BaseModel'保存为Controller中的属性,并按照你的建议在OnActionExecuting上填充它。

但我会在Controller和Html帮助器上使用ExtensionMethods来访问数据。 如果你使用继承,你将不必要地复杂化。

如果您需要扩展方法的样本,请告诉我。

这种方法很糟糕。你没有复制代码。

**编辑2 **

以下是您的扩展方法的外观:(在我的头顶,因此可能无法编译)

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;
}

确保Controller派生自您添加BaseModel属性的Controller类。我在上面称它为'YourController'。

然后你应该好好去; - )

编辑3

提醒您,如果要在View中使用扩展方法,则需要知道命名空间。 实现此目的的最佳方法是在Views文件夹的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>

答案 1 :(得分:1)

如果您正在谈论传入的模型或传出的模型(即提供的视图模型或由表单发布的模型参数),则取决于一点。

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

在表单发布方面,您可能需要创建自己的模型绑定器,但只有在您有某种原因需要单个操作时才能使用多种类型的模型,并且坦率地说这可能会变得毛茸茸。在这种情况下,您必须将实际的类型名称放入隐藏的表单elemetn或其他东西,以便您的模型绑定器可以确定要实例化的模型。除非你有令人信服的理由,否则我建议不要这样做。