在方法CreateView()(检查下面的View Engine)或我的自定义操作过滤器(也在下面)中,我必须以某种方式检查我们请求的View是否是ViewUserControl。因为否则我会收到错误
“当视图是ViewUserControl时,无法指定主名称。”
当我在QueryString中有“modal = true”并且View请求是ViewUsercontrol时,因为你无法在ViewUserControls上设置母版页(显然)。
这是我现在的自定义视图引擎代码:
public class PendingViewEngine : VirtualPathProviderViewEngine
{
public PendingViewEngine()
{
// This is where we tell MVC where to look for our files.
/* {0} = view name or master page name
* {1} = controller name */
MasterLocationFormats = new[] {"~/Views/Shared/{0}.master", "~/Views/{0}.master"};
ViewLocationFormats = new[]
{
"~/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx", "~/Views/Shared/{0}.ascx",
"~/Views/{1}/{0}.ascx"
};
PartialViewLocationFormats = new[] {"~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.ascx"};
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
return new WebFormView(partialPath, "");
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
return new WebFormView(viewPath, masterPath);
}
}
我的动作过滤器:
public class CanReturnModalView : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// setup the request, view and data
HttpRequestBase request = filterContext.RequestContext.HttpContext.Request;
bool modal = false;
if (request.QueryString["modal"] != null)
modal = bool.Parse(request.QueryString["modal"]);
if (filterContext.Result is ViewResult)
{
ViewResult view = (ViewResult) (filterContext.Result);
// replace the view Master page file with Modal Masterpage
if (modal)
view.MasterName = "AdministrationModal";
filterContext.Result = view;
}
else if (filterContext.Result is RedirectToRouteResult)
{
RedirectToRouteResult redirect = (RedirectToRouteResult) filterContext.Result;
// append modal route value to the redirect result if modal was requested
if (modal)
redirect.RouteValues.Add("modal", true);
filterContext.Result = redirect;
}
}
}
上面的ViewEngine在这样的调用上失败了:
<% Html.RenderAction("Display", "MyController", new { zoneslug = "some-zone-slug" });%>
我在这里呈现的动作是:
public ActionResult Display(string zoneslug)
{
WidgetZone zone;
if (!_repository.IsUniqueSlug(zoneslug))
zone = (WidgetZone) _repository.GetInstance(zoneslug);
else
{
// do something here
}
// WidgetZone used here is WidgetZone.ascx, so a partial
return View("WidgetZone", zone);
}
我无法使用RenderPartial,因为您无法以RenderAction的方式将路线值发送到RenderPartial。据我所知,没有办法像RenderAction()那样为RenderPartial()提供RouteValueDictionary。
答案 0 :(得分:4)
您可以通过调用PartialView而不是view来实现所描述的行为:
像现在一样创建视图:
<% Html.RenderAction("PartialIndex", new { test = "input" }); %>
正如你所看到的,没有什么特别之处。
然后在您的控制器操作中,只需调用 PartialView 而不是View:
public ActionResult PartialIndex(string test)
{
var viewResult = PartialView("PartialIndex", (object)test);
return viewResult;
}
当modal参数传递给查询字符串时,还会覆盖视图方法来否决mastername。
public bool IsModal
{
get
{
var modalParameter = Request.QueryString["modal"];
if (string.IsNullOrEmpty(modalParameter))
return false;
bool modalValue;
var success = bool.TryParse(modalParameter, out modalValue);
return success && modalValue;
}
}
protected override ViewResult View(string viewName, string masterName, object model)
{
if (IsModal)
masterName = "Alternate";
return base.View(viewName, masterName, model);
}
只有在渲染实际视图(而不是部分视图)时才会触发View方法覆盖,因此可以安全地假设可以设置masterName。
答案 1 :(得分:0)
试试这个(未经测试)。 FindView返回一个ViewEngineResults,它有一个名为IView View的属性,可以是PartialViewResult。如果不存在,只需检查并返回并使用空母版。
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if( base.FindView(controllerContext, viewName, "", useCache).View is PartialViewResult )
return base.FindView(controllerContext, viewName, "", useCache);
if (controllerContext.HttpContext.Request.IsAjaxRequest())
return base.FindView(controllerContext, viewName, "Modal", useCache);
return base.FindView(controllerContext, viewName, "Site", useCache);
}
}