Razor中的嵌入式代码_Layout.cshtml
我正在研究一个MVC3 Razor Web应用程序,它从Java内容管理系统获取它的页面装饰。由于这装潢是由每个页面共享,我已经把在_Layout.cshtml文件中的CMS内容的检索,但我不是,我实现的代码完全满意...Razor中的嵌入式代码_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的某个辅助类中调用单个静态方法。这将允许我将代码移出视图,并感觉像是最好的解决方案,但我仍然不是特别满意。
有没有人有任何其他的建议/意见?
您可以使用全球行动滤波器所需的数据添加到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());
}
一种解决方案:
- 创建基础控制器,每个控制器,从继承。
- 覆盖OnActionExecuted或类似的概述
- 添加数据到ViewBog或ViewData的在你重写代码
的OnActionExecuted代码会被执行每一个动作被调用的时候,所以你可能要进行一些检查以确保该动作将返回一个视图,等等。可能有更好的重写OnActionExecuting,OnResultExecuting等等,但这是我头脑中最重要的一个。
另一种解决方案:
创建你可以用它来装点你的控制器的过滤器属性。
这可能是一个更好的解决办法,如果你不希望有一个基本的控制器。
*“由于_layout文件没有控制器”。* 问题是,您的假设不完全正确!事实上,在控制器的帮助下填充_Layout页面是很常见的。让我们想想例如很多网站的登录/注销矩形......它通常放在_Layout中并通过控制器进行处理。 没有控制器将ViewModel传递给布局...仅仅是因为布局...只是...布局而不是传达信息的东西...它可以成为其他内容的“容器”反过来可能有一个ViewModel。 实际上,您可以使用Html.Action或Html.RenderAction从_Layout调用Child控制器...这是登录在大多数asp.net Mvc网站中处理的方式......我建议您执行同样适用于您的内容...通过调用专门的子控制器来填充您的内容,其中一个用于布局页面的每个不同“区域”。
我这样做可以看到的唯一问题是我需要将数据传递给所有不同的控制器操作,因为我只想调用一次LoadContent方法。我是否误解了您建议的解决方案中的某些内容?是否可以在不同的控制器动作之间传递状态数据(不使用viewbag)? – DoctorMick 2012-03-27 14:08:07
可能你误解了我的建议。 Probaby你只需要1-2个控制器。 1-2之间的选择......仅取决于模块性问题......这取决于您的选择。只需在你的_layout中放入一个Html.Action或一个只调用一个控制器的Html.RenderAction。这样,您将始终使用相同的控制器填充您的_layout的一部分...这意味着相同的控制器会为使用该_layout页面的所有视图执行相应的工作。 如果您希望有多个控制器分别填充_layout的不同部分,您可以选择使用多个Html.Action。这取决于您。 – 2012-03-27 14:16:57
这看起来像一个很好的解决方案,但我是否认为这会发生在每一个行动?我不希望代码执行任何部分视图或json操作。 – DoctorMick 2012-03-27 14:09:26
我更新了代码,因此它只能在正常操作中执行。 – 2012-03-27 15:02:53