Как проверить, имеет ли возвращаемый вид тип PartialViewResult или ViewUserControl - PullRequest
0 голосов
/ 21 марта 2010

В методе CreateView () (проверьте мой View Engine ниже) или в моем фильтре настраиваемых действий (также ниже) я должен каким-то образом проверить, является ли View, который мы запрашиваем, ViewUserControl.Потому что в противном случае я получаю сообщение об ошибке:

"Имя мастера не может быть указано, когда представление является ViewUserControl."

, когда у меня есть "modal = true" в QueryStringи запрос 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, потому что вы не можете отправитьНаправьте значения в RenderPartial так, как вы можете использовать RenderAction.Насколько мне известно, нет способа предоставить RouteValueDictionary RenderPartial () так же, как вы можете RenderAction ().

Ответы [ 2 ]

4 голосов
/ 13 апреля 2010

Вы можете достичь описанного поведения, вызвав PartialView вместо view:

Создайте view , как вы бы сейчас:

  <% Html.RenderAction("PartialIndex", new { test = "input" }); %>

Как вы можете видеть тамв этом нет ничего особенного.

Тогда в вашем действии контроллера просто вызовите PartialView вместо View:

public ActionResult PartialIndex(string test)
{
    var viewResult = PartialView("PartialIndex", (object)test);
    return viewResult;
}

И также переопределите View метод для отмены основного имени, когда модальный параметр передается в строку запроса.

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 может быть установлено.

0 голосов
/ 21 марта 2010

Попробуйте это (не проверено).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);
} 

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...