我尝试创建自定义操作过滤器,执行验证并根据结果创建自定义视图。执行操作过滤器时,它仅显示文本:<h2>My View</h2>
(不使用布局)。我还试图覆盖 OnResultExecuting 方法并在那里设置主名称(filterContext.Result as ViewResult).MasterName =&#34; Layout&#34; ,但是结果仍然相同。那么可以设置布局吗?
public class MyValidationFilterAttribute : ActionFilterAttribute
{
public string Layout { get; set; }
public MyValidationFilterAttribute(string layout = "_Layout")
{
Layout = layout;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var result = TodoValidate();
if (!result)
filterContext.Result = new ViewResult() { View = new MyView(), MasterName = Layout};
base.OnActionExecuting(filterContext);
}
}
public class MyView : IView
{
public void Render(ViewContext viewContext, TextWriter writer)
{
writer.Write("<h2>My View</h2>");
}
}
//更新1:
基于ASP.NET MVC源代码,当 View!= null 时,忽略 MasterName 。所以我认为如果我想使用 IVIew 我不能重复使用Layout,但我必须手动渲染整个html页面。
// ----------------
//ViewResult.cs
// ----------------
// FindView is called from ViewResultBase class only when the View == null
protected override ViewEngineResult FindView(ControllerContext context)
{
ViewEngineResult view = this.ViewEngineCollection.FindView(context, this.ViewName, this.MasterName);
if (view.View != null)
return view;
// rest of the code
}
// ----------------
// ViewResultBase.cs
// ----------------
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
if (string.IsNullOrEmpty(this.ViewName))
this.ViewName = context.RouteData.GetRequiredString("action");
ViewEngineResult viewEngineResult = (ViewEngineResult) null;
if (this.View == null)
{
viewEngineResult = this.FindView(context);
this.View = viewEngineResult.View;
}
TextWriter output = context.HttpContext.Response.Output;
this.View.Render(new ViewContext(context, this.View, this.ViewData, this.TempData, output), output);
if (viewEngineResult == null)
return;
viewEngineResult.ViewEngine.ReleaseView(context, this.View);
}