如果未提供模型,则 ASP.NET MVC 自动模型实例化
Posted
技术标签:
【中文标题】如果未提供模型,则 ASP.NET MVC 自动模型实例化【英文标题】:ASP.NET MVC Automatic Model Instantiation if Model is not provided 【发布时间】:2013-07-23 07:17:03 【问题描述】:我正在尝试在未给出视图模型时(当它们为空时)实现视图模型的自动实例化。
控制器动作
public ActionResult SomeAction()
return View("~/.../SomeView.cshtml"); //No model is given
SomeView.cshtml
@model Models.SomeModel //According to this type...
<h2>@Model.Title</h2>
//...auto instantiate @Model when it is null
我试图覆盖 RazorViewEngine,但在 ViewEngine 时似乎(我可能错了)我无法访问模型类型,它始终为空,即使提供了它也是如此。而且我应该能够学习空模型的类型,因为我们正在尝试实例化它,所以应该有另一个元数据供我们获取视图的模型类型。
我尝试过扩展 DefaultModelBinder,但它似乎仅用于从 Http 请求绑定模型,它不会在手动创建视图时触发。
我没有想法。我希望这是可行的。
【问题讨论】:
为什么?这似乎是为了避免使用几次击键而付出的巨大努力。 你假设这是我的朋友的几次击键,可能有数百个原因有人需要它。如果我们会问“为什么要这样做而不是几次击键?”我们今天永远不会有 ASP.NET MVC。但是,如果你真的想知道:我有很多部分视图,所有的 HTML 都在项目中划分。我不想通过 Html.Partial('x.cshtml', new Model()) 实例化视图文件中的几十个视图模型。我不想将它们混合在模型中,因为它们在很多地方都使用过。我还将通过 Html.Partial 添加自动视图包含,并且我想摆脱模型实例化。 您在问题中没有提及偏音。部分的工作方式与视图的工作方式非常不同。任何适用于视图的解决方案都不适用于局部。无论如何,您究竟如何期望一些代码神奇地知道实例化您的视图模型所必需的?您当然可以编写一个解析视图的函数,并查找 @model 语句,然后动态实例化它,但这仅适用于不需要额外设置的简单模型。对于只适用于 10% 代码的东西,几乎不值得付出努力 此外,您通常不需要实例化默认模型,因为 Html 辅助函数在大多数情况下会为您处理空模型,而在它们不需要的情况下,您必须无论如何都要使用无法自动实例化的自定义配置。 我不喜欢你“它不起作用/不值得/需要”的人。我们解决了,请看下面的答案。 【参考方案1】:在 BorysG 的帮助下,我们解决了这个问题,我还改进了它以与 Partials 一起使用。
讨论:http://forums.asp.net/t/1924332.aspx/1?ASP+NET+MVC+Automatic+Model+Instantiation+if+Model+is+not+provided
这里也复制代码:
public class CustomViewEngine : RazorViewEngine
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
var view = base.CreatePartialView(controllerContext, partialPath);
return new ViewWrapper(view);
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
var view = base.CreateView(controllerContext, viewPath, masterPath);
return new ViewWrapper(view);
public class ViewWrapper : IView
protected IView View;
public ViewWrapper(IView view)
View = view;
public void Render(ViewContext viewContext, TextWriter writer)
//Type modelType = BuildManager.GetCompiledType(razorView.ViewPath);
var razorView = View as RazorView;
if (razorView != null)
//if we could not get the model object - try to get it from what is declared in view
var compiledViewType = BuildManager.GetCompiledType(razorView.ViewPath);
var model = viewContext.ViewData.Model;
Type baseType = compiledViewType.BaseType;
//model is passed as generic parameter, like this MyView1 : WebViewPage<MyModel1>
if (baseType != null && baseType.IsGenericType)
//and here the trick begins - extract type of model from generic arguments
var modelType = baseType.GetGenericArguments()[0]; //the same as typeof(MyModel1)
// ReSharper disable UseMethodIsInstanceOfType
//If model is null, or model is not type of the given model (for partials)
if (model == null || !modelType.IsAssignableFrom(model.GetType()))
// ReSharper restore UseMethodIsInstanceOfType
//Set @model and render the view
viewContext.ViewData.Model = Activator.CreateInstance(modelType);
View.Render(viewContext, writer);
并且在 Application_Start() 中也进入 Global.asax.cs。
//remove default Razor and WebForm view engines
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());
【讨论】:
以上是关于如果未提供模型,则 ASP.NET MVC 自动模型实例化的主要内容,如果未能解决你的问题,请参考以下文章
当表单处于空闲状态时,ASP.NET MVC 操作参数未绑定
ASP.NET MVC 核心 POST 请求未将 JSON 数据转换为模型