如何在BaseController中初始化BaseModel

时间:2015-10-09 07:29:49

标签: c# asp.net-mvc inheritance dependency-injection model

我有一类属性,这些属性是从我在MVC应用程序的每个视图中都需要的服务中设置的。

因此,我创建了一个“基本视图模型”,我的视图模型将继承该模型。

public class BaseModel
{
    public BaseModel()
    {
        foo = "foo value";
        bar = "bar value";
    }

    public string foo { get; set; }

    public string bar { get; set; }
}

public class HomeIndexViewModel : BaseModel
{
}

然后我创建了一个“基本控制器”,我的所有控制器将继承自:

public class BaseController : Controller
{
    public BaseController()
    {
    }
}

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        HomeIndexViewModel model = new HomeIndexViewModel();
        return View(model);
    }
}

这是按预期工作的,我可以在我的视图中致电@Model.foo并获取foo value

但是我不相信我应该在它的构造函数中初始化BaseModel的值,因为这不使用依赖注入,并且将难以进行单元测试。

如何将值foobar的设置移至BaseController

当然我可以在HomeController中设置值,但我宁愿从控制器中抽象出来,因为逻辑总是相同的,并且会使我的所有控制器都膨胀。

1 个答案:

答案 0 :(得分:5)

我认为问题在于您是在 action 中创建模型的实例,因此基本控制器没有引用该对象来设置属性。

我个人可能会选择一些工厂类型的'在基本控制器中的功能,负责根据需要创建模型。

例如:

public class BaseController : Controller
{
    public T CreateBaseModel<T>() where T : BaseModel, new()
    {
        return new T
        {
            foo = "foo value",
            bar = "bar value"
        };
    }
}

然后,当您在动作中创建模型时,您可以这样做:

HomeIndexViewModel model = CreateBaseModel<HomeIndexViewModel>();

如果由于某种原因你需要将参数传递给模型构造函数,那么你可以像这样重载:

public T CreateBaseModel<T>(params object[] args) where T : BaseModel
{
    T model = (T)Activator.CreateInstance(typeof(T), args);
    model.foo = "foo";
    return model;
}

HomeIndexViewModel model = CreateBaseModel<HomeIndexViewModel>(param1, param2, etc);

<强>替代

上述方法的主要优点是您可以访问操作代码中的foobar属性。但是,如果您不关心这一点并且只需要在“查看”页面中访问这些值,那么您可以覆盖OnActionExecuted方法并在其中应用值。这种方法的好处是你不需要改变在动作中创建模型的方式......

protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
    BaseModel model = filterContext.Controller.ViewData.Model as BaseModel;
    if (model != null)
    {
        model.foo = "foo value";
        model.bar = "bar value";
    }

    base.OnActionExecuted(filterContext);
}

进行null检查意味着它只会尝试为从BaseModel继承的模型应用值,这意味着您仍然可以毫无顾虑地使用其他模型。

通过这种方法,您的操作代码可以追溯到最初的方式:

HomeIndexViewModel model = new HomeIndexViewModel();
return View(model);