我一直在试图找到一种很好的方式来处理我们的Asp.net MVC网站的模型,当有所有页面的共同属性。这些属性将显示在布局(主页面)中。我使用一个“BaseModel”类来保存这些属性,我的Layout使用这个BaseModel作为它的模型。Asp.net MVC模型的视图和布局
每个其他模型都从该BaseModel继承,并且每个模型都具有相对于它所表示的视图的特定属性。正如你可能已经猜到的那样,我的模型实际上是视图模型,即使这在这里不太相关。
我曾尝试不同的方法来初始化BaseModel在每个视图
- 通过“手”(这样特定的控制器可以实现特定的对于为例共同的行为)
- 具有基础controlelr是覆盖OnActionExecuting调用初始化方法
- 使用一个辅助类做控制器之外
- 使用模型厂
但无那些真正吸引我:
- 似乎是显而易见的我,但干的理由一个足够的理由认为(其实我从来没有尝试过的解决方案可言,我只是把它放在最后一点能够循环)。
- 我不喜欢那个,因为这意味着无论何时添加一个新的Controller,都需要知道它必须从BaseController继承,并且需要调用Initialize方法,更不用说如果您的控制器已经覆盖了基本的一个,无论如何调用基地来维护这些值。
- 请参阅下一点
- 和3.是同一主题的变体,但对第二个解决方案的问题没有帮助。
- 到目前为止我的最爱,但现在我必须通过几个变量来设置这些值。我喜欢它的依赖性倒置。但是,如果我想提供会话中的值,我需要将它们明确地传递给例子,然后我回到原点,因为我必须手动提供它们(作为参考或通过任何类型的接口)
当然,(几乎)所有这些解决方案都有效,但我正在寻找一种更好的方法来实现。
在输入这个问题时,我发现可能有一个新的路径builder pattern,但实现也可能很快成为一个负担,因为我们可以有几十个视图和控制器。
我会很乐意接受任何严肃的建议/提示/建议/模式/建议!
更新
感谢@EBarr我想出了另一种解决方案,使用ActionFilterAttribute(不生产代码,这样做是在5分钟内):
public class ModelAttribute : ActionFilterAttribute
{
public Type ModelType { get; private set; }
public ModelAttribute(string typeName) : this(Type.GetType(typeName)) { }
public ModelAttribute(Type modelType)
{
if(modelType == null) { throw new ArgumentNullException("modelType"); }
ModelType = modelType;
if (!typeof(BaseModel).IsAssignableFrom(ModelType))
{
throw new ArgumentException("model type should inherit BaseModel");
}
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var model = ModelFactory.GetModel(ModelType);
var foo = filterContext.RequestContext.HttpContext.Session["foo"] as Foo;
model.Foo = foo;
model.Bar = somevalue;
filterContext.Controller.TempData["model"] = model;
}
}
称它是那么很简单:
[Model(typeof(HomeModel))]
public ActionResult Index()
{
var homeModel = TempData["model"] as HomeModel;
// Add View Specific stuff
return View(homeModel);
}
它给了我最好的每一个世界。唯一的缺点是要找到一种合适的方式将模型传递回动作。
这里使用TempData对象完成,但我也考虑更新可以在ActionParameters中找到的模型。
我仍然采取任何严重的建议/提示/建议/模式/建议,或以前的观点。
感谢您的反馈。虽然它不完全符合我的要求(您的解决方案是3的不同实现),但它实际上给了我一个想法。我只是尝试使用一个自定义的ActionFilterAttribute,似乎可以做到这一点。我仍然需要设计一种“干净”的方式来让模型回到动作中(现在我正在使用TempData)。我会更新这个问题来反映这一点。 – 2012-04-03 14:02:03
是的,它是#3的一个版本。我想过属性,但是需要装饰每个控制器/动作(取决于需要)。在OnActionExecuting和OnActionExecuted中保存我的代码保存在一个基本控制器中。在实践中,对于任何更大的MVC项目,您将拥有一个基本控制器,所以我不介意这么多。它还允许我基于模型类型运行逻辑,而不是绑定执行操作的逻辑。 – EBarr 2012-04-03 14:07:35
RE:抓取模型:在你的动作过滤器属性中,你将最终实现相同的事件(执行和执行),但是你可以从filterContext中取出模型,不需要把它交回,只需找到它并填写你需要的东西。 – EBarr 2012-04-03 14:29:23