c# - 如果未提供模型,则 ASP.NET MVC 自动模型实例化

标签 c# asp.net asp.net-mvc view model

我正在尝试在未给定 View 模型时(当它们为空时)实现 View 模型的自动实例化。

Controller Action

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 时间我无法访问模型类型,它始终为 null,即使它已提供。而且我应该能够了解 null 模型的类型,因为我们正在尝试实例化它,所以应该有另一个元数据供我们获取 View 的模型类型。

我试过扩展 DefaultModelBinder,但它似乎只用于绑定(bind)来自 Http 请求的模型,它不会在手动创建 View 时触发。

我没主意了。希望可行。

最佳答案

在 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());

关于c# - 如果未提供模型,则 ASP.NET MVC 自动模型实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17803709/

相关文章:

c# - 如何将 Unity3d Mesh 保存到文件?

c# - 带有 MySQL 的 ASP.NET MVC EF 需要 .dll 及其用法?

asp.net - asp.net core 中事件内存 session 的访问列表

c# - 复杂对象的自动映射器映射

asp.net-mvc - 如何从 Forms Authentication 迁移到 ASP .NET Identity

c# - 如何从 ASP.NET 标记中获取资源字符串?

c# - InternalsVisibleTo 不起作用

c# - 在 .NET 的子类中扩展枚举定义

jquery - 为整个 Visual Studio 解决方案安装旧版 NuGet 包

c# - ReportViewer 控件不显示报告