ASP。如果没有提供模型,则NET MVC自动模型实例化

时间:2023-02-07 04:02:15

I'm trying to achieve auto instantiation of view models when they are not given (when they are null).

我正在尝试实现视图模型的自动实例化,当它们没有给出时(当它们为空时)。

Controller Action

控制器动作

public ActionResult SomeAction()
{
    return View("~/.../SomeView.cshtml"); //No model is given
}

SomeView.cshtml

SomeView.cshtml

@model Models.SomeModel //According to this type...
<h2>@Model.Title</h2>
//...auto instantiate @Model when it is null

I've tried to override RazorViewEngine, but it seems (I may be wrong) at the ViewEngine time I cannot access the model type, it is always null, even if it is provided. And I should be able to learn type of the null model since we are trying to instantiate it, so there should be another Metadata which for us to get the View's Model type.

我尝试过重写RazorViewEngine,但是在ViewEngine时,我无法访问模型类型,它总是为null,即使提供了它。我应该能够学习空模型的类型因为我们正在尝试实例化它,所以应该有另一个元数据让我们获得视图的模型类型。

I've tried extending DefaultModelBinder, but it seems it is only for binding models from an Http request, it didn't fire on manual view creation.

我尝试过扩展DefaultModelBinder,但它似乎只用于从Http请求绑定模型,它并没有在手动创建视图时启动。

I'm out of ideas. I hope it is feasible to do.

我的想法。我希望这是可行的。

1 个解决方案

#1


3  

With the help of BorysG we have solved it, I've also improved it to work with Partials.

在BorysG的帮助下,我们已经解决了这个问题,我还改进了它与部分的工作。

Discussion: http://forums.asp.net/t/1924332.aspx/1?ASP+NET+MVC+Automatic+Model+Instantiation+if+Model+is+not+provided

讨论:http://forums.asp.net/t/1924332.aspx/1?ASP MVC +自动+ +网络+模型+实例化+如果+ + +不+提供

Copying the code here also:

在这里复制代码:

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);
    }
}

And also into Global.asax.cs in the Application_Start().

也为Global.asax。cs的Application_Start()。

//remove default Razor and WebForm view engines
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());

#1


3  

With the help of BorysG we have solved it, I've also improved it to work with Partials.

在BorysG的帮助下,我们已经解决了这个问题,我还改进了它与部分的工作。

Discussion: http://forums.asp.net/t/1924332.aspx/1?ASP+NET+MVC+Automatic+Model+Instantiation+if+Model+is+not+provided

讨论:http://forums.asp.net/t/1924332.aspx/1?ASP MVC +自动+ +网络+模型+实例化+如果+ + +不+提供

Copying the code here also:

在这里复制代码:

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);
    }
}

And also into Global.asax.cs in the Application_Start().

也为Global.asax。cs的Application_Start()。

//remove default Razor and WebForm view engines
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());