Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASP.NET MVC自动模型实例化(如果未提供模型)_C#_Asp.net_Asp.net Mvc_View_Model - Fatal编程技术网

C# ASP.NET MVC自动模型实例化(如果未提供模型)

C# ASP.NET MVC自动模型实例化(如果未提供模型),c#,asp.net,asp.net-mvc,view,model,C#,Asp.net,Asp.net Mvc,View,Model,我试图在视图模型未给定时(当它们为空时)实现视图模型的自动实例化 控制器动作 SomeView.cshtml @model Models.SomeModel//根据此类型。。。 @模型名称 //…当@Model为空时自动实例化它 我试图覆盖RazorViewEngine,但在ViewEngine时,我似乎(可能是错的)无法访问模型类型,它始终为null,即使提供了它。我应该能够了解空模型的类型,因为我们正在尝试实例化它,所以应该有另一个元数据,让我们获得视图的模型类型 我尝试过扩展Defaul

我试图在视图模型未给定时(当它们为空时)实现视图模型的自动实例化

控制器动作

SomeView.cshtml

@model Models.SomeModel//根据此类型。。。
@模型名称
//…当@Model为空时自动实例化它
我试图覆盖RazorViewEngine,但在ViewEngine时,我似乎(可能是错的)无法访问模型类型,它始终为null,即使提供了它。我应该能够了解空模型的类型,因为我们正在尝试实例化它,所以应该有另一个元数据,让我们获得视图的模型类型

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


我没有主意了。我希望这是可行的。

在BorysG的帮助下,我们已经解决了这个问题,我还改进了它,使之能够与Partials一起工作

讨论:

在此处复制代码:

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

为什么?这似乎是为了避免使用几次击键而付出的巨大努力。你假设这是几次击键,我的朋友,可能有数百个理由说明为什么有人需要这样做。如果我们问“为什么不敲几下键盘呢?”我们今天就不会有ASP.NET MVC了。然而,如果你真的想知道:我有很多局部视图,所有的HTML都被划分在项目中。我不想通过Html.Partial('x.cshtml',new Model())在视图文件中实例化几十个视图模型。我不想在模型中混用它们,因为它们在很多地方都有使用。我还将通过Html.Partial添加自动视图包含,并且我希望摆脱模型实例化。您在问题中没有提到任何关于Partials的内容。分部的工作方式与视图的工作方式非常不同。任何适用于视图的解决方案都不适用于局部视图。在任何情况下,您如何期望某些代码神奇地知道实例化视图模型所需的内容?您当然可以编写一个函数来解析视图,并查找@model语句,然后动态实例化它,但这只适用于不需要额外设置的简单模型。几乎不值得为只使用10%代码的东西付出努力。此外,您通常不需要实例化默认模型,因为Html助手函数在大多数情况下为您处理空模型,而在它们不处理空模型的情况下,你必须使用无法自动实例化的自定义配置。我不喜欢你“它不工作/不值得/需要”的人。我们解决了它,请参见下面的答案。
@model Models.SomeModel //According to this type...
<h2>@Model.Title</h2>
//...auto instantiate @Model when it is null
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);
    }
}
//remove default Razor and WebForm view engines
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());