如果未提供模型,则 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 动态模型未被识别

[转] ASP.NET MVC 模型绑定的功能和问题

ASP.NET MVC 核心 POST 请求未将 JSON 数据转换为模型

ASP.NET MVC 网站视图模型在发布后未更新,但在发布中运行良好

无法更改 ASP.NET MVC 3 中文本框的值