Razor _Layout.cshtml中嵌入的代码

时间:2012-03-16 15:43:07

标签: asp.net-mvc razor

我正在开发一个MVC3 Razor Web应用程序,它从Java内容管理系统获取它的页面装饰。由于这个装饰是由每个页面共享的,我将CMS内容的检索放在_Layout.cshtml文件中,但我对我实现的代码并不完全满意......

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    @{
        -- The first two lines are temporary and will be removed soon.
        var identity = new GenericIdentity("", "", true);
        var principal = new GenericPrincipal(identity, new string[] { });
        var cmsInterface = MvcApplication.WindsorContainer.Resolve<ICMSInterface>();
        cmsInterface.LoadContent(principal, 2);
     }
     @Html.Raw(cmsInterface.GetHeadSection())
 </head>

<body>
    @Html.Raw(cmsInterface.GetBodySection(0))
    @RenderBody()
    @Html.Raw(cmsInterface.GetBodySection(1))
</body>
</html>

由于_layout文件没有控制器,我无法看到我可以将代码放在哪里进行检索。以下是我考虑过的一些事情:

  • 以单独的部分检索CMS内容,因此我不需要LoadContent调用。不幸的是,由于我必须用来检索CMS内容的组件,这是不可能的,它是全有或全无。
  • 使用局部视图,以便我可以使用控制器。因为我需要将整个页面放入部分选项中,这看起来有点荒谬。
  • 在某个帮助程序类上调用单个静态方法,该类检索数据并将这三个部分添加到ViewBag。这将允许我将代码移出视图并感觉是最好的解决方案,但我仍然不是特别满意。

有没有人有任何其他建议/意见?

4 个答案:

答案 0 :(得分:5)

您可以使用全局操作过滤器将所需数据添加到所有控制器中的ViewBag:

public class LoadCmsAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if (!filterContext.IsChildAction &&
            !filterContext.HttpContext.Request.IsAjaxRequest() &&
            filterContext.Result is ViewResult)
        {
            var identity = new GenericIdentity("", "", true);
            var principal = new GenericPrincipal(identity, new string[] { });
            var cmsInterface = MvcApp.WindsorContainer.Resolve<ICMSInterface>();
            cmsInterface.LoadContent(principal, 2);

            var viewBag = filterContext.Controller.ViewBag;
            viewBag.HeadSection = cmsInterface.GetHeadSection();
            viewBag.FirstBodySection = cmsInterface.BodySection(0);
            viewBag.SecondBodySection = cmsInterface.BodySection(1);
        }
    }
}

的Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    ...
    filters.Add(new LoadCmsAttribute());
}

答案 1 :(得分:1)

一个解决方案:

  1. 创建每个控制器继承的基本控制器。
  2. 覆盖OnActionExecuted或类似概述
  3. 将数据添加到已覆盖代码中的ViewBog或ViewData
  4. 每次调用一个动作时都会运行OnActionExecuted代码,因此你可能想要执行一些检查以确保动作将返回一个视图等。可能有更好的覆盖OnActionExecuting,OnResultExecuting等等但是这是一个在我脑海中浮现的。

    另一种解决方案:

    创建一个可用于装饰控制器的过滤器属性。

    http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

    如果您不需要基本控制器,这可能是更好的解决方案。

答案 2 :(得分:1)

*&#34;由于_layout文件没有控制器&#34;。* 关键是你的假设并不完全正确!事实上,在控制器的帮助下填充_Layout页面是很常见的。让我们考虑一下很多网站的登录/登出矩形......它通常放在_Layout中并用控制器处理。 没有控制器将ViewModel传递给布局...只是因为布局......只是......布局而不是传达信息的东西......但是它可以是一个&#34;容器&#34;对于其他内容,反过来可能有一个ViewModel。 在实践中,您可以使用Html.Action或Html.RenderAction从_Layout调用子控制器...这是在大多数asp.net Mvc网站上处理Login的方式......我建议你这样做对于您的内容...通过调用专门的子控制器来填充您的内容,每个不同的&#34;区域&#34;布局页面。

答案 3 :(得分:0)

好像你的回答可能在这里:child action that obviates need for base controller.