我有一类属性,这些属性是从我在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
的值,因为这不使用依赖注入,并且将难以进行单元测试。
如何将值foo
和bar
的设置移至BaseController
?
当然我可以在HomeController
中设置值,但我宁愿从控制器中抽象出来,因为逻辑总是相同的,并且会使我的所有控制器都膨胀。
答案 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);
<强>替代强>
上述方法的主要优点是您可以访问操作代码中的foo
和bar
属性。但是,如果您不关心这一点并且只需要在“查看”页面中访问这些值,那么您可以覆盖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);