Embedded code in Razor _Layout.cshtml

I am working on a MVC3 Razor web application that gets page decoration from java content management system. Since this decoration is shared by every page, I put the extraction of the CMS content in the _Layout.cshtml file, but I'm not quite happy with the code I implemented ...

<!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> 

Since there is no controller for the _layout file, I do not see where else I could put the code to extract. Here are a few things I looked at:

  • Extract the contents of the CMS in separate parts, so I don’t need to call LoadContent. Unfortunately, due to the component that I have to use to extract the contents of the CMS, this is not possible, is it all or nothing.
  • Use a partial view so that I can use the controller. Since I would need to translate the entire page into a partial one, this option seems a bit ridiculous.
  • Calling one static method for some helper class that retrieves data and adds three sections to the ViewBag. This will allow me to get the code out of the view and feel like a better solution, but I'm still not very happy with it.

Does anyone have any other suggestions / comments?

+4
source share
4 answers

You can use the global action filter to add the necessary data to the ViewBag in all controllers:

 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()); } 
+5
source

One solution:

  • Create a base controller to which each of your controllers inherits.
  • Override OnActionExecuted or Similar Overview
  • Add data to ViewBog or ViewData in your redefined code

The OnActionExecuted code will run every time the action is called, so you can do some checking to ensure that the action will return the view, etc. It might be better to override OnActionExecuting, OnResultExecuting, etc., but the one that comes to my mind.

Another solution:

Create a filter attribute that you can use to decorate controllers.

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

This might be the best solution if you do not need a basic controller.

+1
source

* "As there is no controller for the _layout file." * The fact is that your assumption is not entirely true! In fact, it’s pretty common to populate the _Layout page with controllers. For example, think, for example, about the input / output rectangle, which is a lot of websites ... it is usually placed in _Layout and processed by the controller. There is no controller that passes the ViewModel to the layout ... simply because the layout ... is just ... the layout, and not something that conveys the information ... howeber it can be a “container” for other content that in turn may have a ViewModel. In practice, you can call child controllers from _Layout using Html.Action or Html.RenderAction ... This is the way Login is handled on most asp.net Mvc websites ... and I suggest you do the same for your content ... fill in your content by invoking specialized child controllers, one for each other "area" of the layout page.

+1
source
0
source

Source: https://habr.com/ru/post/1401846/


All Articles