using System; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.Extensions.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Common.Filters; using Umbraco.Web.Models; using Umbraco.Web.Routing; namespace Umbraco.Web.Mvc { /// /// Represents the default front-end rendering controller. /// [PreRenderViewActionFilter] [TypeFilter(typeof(ModelBindingExceptionFilter))] public class RenderMvcController : UmbracoController, IRenderMvcController { private IPublishedRequest _publishedRequest; private readonly ILogger _logger; private readonly ICompositeViewEngine _compositeViewEngine; public RenderMvcController(ILogger logger, ICompositeViewEngine compositeViewEngine) { _logger = logger; _compositeViewEngine = compositeViewEngine; } /// /// Gets the current content item. /// protected IPublishedContent CurrentPage => PublishedRequest.PublishedContent; /// /// Gets the current published content request. /// protected internal virtual IPublishedRequest PublishedRequest { get { if (_publishedRequest != null) return _publishedRequest; if (RouteData.DataTokens.ContainsKey(Core.Constants.Web.PublishedDocumentRequestDataToken) == false) { throw new InvalidOperationException("DataTokens must contain an 'umbraco-doc-request' key with a PublishedRequest object"); } _publishedRequest = (IPublishedRequest)RouteData.DataTokens[Core.Constants.Web.PublishedDocumentRequestDataToken]; return _publishedRequest; } } /// /// Ensures that a physical view file exists on disk. /// /// The view name. protected bool EnsurePhsyicalViewExists(string template) { var result = _compositeViewEngine.FindView(ControllerContext, template, false); if (result.View != null) return true; _logger.LogWarning("No physical template file was found for template {Template}", template); return false; } /// /// Gets an action result based on the template name found in the route values and a model. /// /// The type of the model. /// The model. /// The action result. /// If the template found in the route values doesn't physically exist, then an empty ContentResult will be returned. protected IActionResult CurrentTemplate(T model) { var template = ControllerContext.RouteData.Values["action"].ToString(); if (EnsurePhsyicalViewExists(template) == false) throw new InvalidOperationException("No physical template file was found for template " + template); return View(template, model); } /// /// The default action to render the front-end view. /// /// /// [RenderIndexActionSelector] public virtual IActionResult Index(ContentModel model) { return CurrentTemplate(model); } } }