我正在尝试在没有给出视图模型时(当它们为空时)实现视图模型的自动实例化。
控制器操作
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,但它似乎只是用于绑定来自Http请求的模型,它不会触发创建手动视图。
我没有想法。我希望这样做是可行的。
答案 0 :(得分:3)
在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);
}
}
还有Application_Start()中的Global.asax.cs。
//remove default Razor and WebForm view engines
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());