public override void ExecuteResult(ActionContext context) { try { EmptyResult empty = new EmptyResult(); //check if the request has been already served (set in route constraint) object constraintCheck = context.HttpContext.Items["Agility.Web.RequestPreviouslyHandledInRouteConstraint"]; if (constraintCheck is bool && ((bool)constraintCheck)) { empty.ExecuteResult(context); return; } HttpRequest Request = context.HttpContext.Request; HttpResponse Response = context.HttpContext.Response; //initialize the offline processing... //HACK: OFFLINE: this should be started in the Startup //if (!OfflineProcessing.IsOfflineThreadRunning) //{ // OfflineProcessing.StartOfflineThread(); //} string url = UriHelper.GetEncodedUrl(Request); string rawUrl = Request.GetEncodedPathAndQuery(); //check if this is Robots.txt and a publishwithagility.com domain (used for staging only) if (( Request.Host.Value.IndexOf(".publishwithagility.com", StringComparison.CurrentCultureIgnoreCase) != -1 || Request.Host.Value.IndexOf(".azurewebsites.net", StringComparison.CurrentCultureIgnoreCase) != -1) && string.Equals(rawUrl, "/robots.txt", StringComparison.CurrentCultureIgnoreCase)) { Response.ContentType = "text/plain"; StringBuilder sb = new StringBuilder(); sb.AppendLine("User-agent: *"); sb.Append("Disallow: /"); var task = Response.WriteAsync(sb.ToString()); task.Wait(); empty.ExecuteResult(context); AgilityCache.TurnOffCacheInProgress(); return; } //don't allow ANY urls to end with / if (!Current.Settings.IgnoreTrailingSlash) { if (rawUrl != "/" && rawUrl.EndsWith("/")) { string newUrl = rawUrl.TrimEnd('/'); AgilityHttpModule.RedirectResponse(newUrl, 301); AgilityCache.TurnOffCacheInProgress(); return; } } if (AgilityContext.BuildAgilityContext()) { empty.ExecuteResult(context); AgilityCache.TurnOffCacheInProgress(); return; } //pre-process the request for any channel or redirections that we encounter... string pagePath = AgilityPagePath; if (!IgnorePrechecks) { if (AgilityHttpModule.HandleChannelsAndRedirects(ref pagePath, LanguageCode)) { empty.ExecuteResult(context); AgilityCache.TurnOffCacheInProgress(); return; } } //use the first page in the sitemap if there is no page passed in... if (string.IsNullOrEmpty(pagePath) || pagePath == "/" || pagePath == "~/") { pagePath = BaseCache.GetDefaultPagePath(AgilityContext.LanguageCode, AgilityContext.WebsiteName, string.Empty); } //check to see if the site should be in "preview mode" if (AgilityHttpModule.CheckPreviewMode(context.HttpContext)) { empty.ExecuteResult(context); AgilityCache.TurnOffCacheInProgress(); return; } AgilityPage page = null; if (!string.IsNullOrEmpty(pagePath)) { //add the ~ if neccessary if (!pagePath.StartsWith("~/")) { if (!pagePath.StartsWith("/")) { pagePath = string.Format("~/{0}", pagePath); } else { pagePath = string.Format("~{0}", pagePath); } } page = Agility.Web.Data.GetPage(pagePath, LanguageCode); //check if this page is a folder, kick out... if (page != null && string.IsNullOrEmpty(page.TemplatePath) && page.TemplateID < 1 && string.IsNullOrEmpty(page.RedirectURL)) { page = null; } } if (AgilityContext.IsResponseEnded) { //check if we've ended the response... empty.ExecuteResult(context); AgilityCache.TurnOffCacheInProgress(); return; } if (page == null) { //possibly route the page if it is a page template... string aspxPath = context.HttpContext.Request.PathBase; int previewIndex = aspxPath.IndexOf("TemplatePreview/", StringComparison.CurrentCultureIgnoreCase); if (previewIndex > -1) { aspxPath = aspxPath.Substring(previewIndex + "TemplatePreview/".Length); aspxPath = string.Format("~/{0}", aspxPath); if (!aspxPath.EndsWith(".aspx", StringComparison.CurrentCultureIgnoreCase)) { //assume we wanted to render a .cshtml file aspxPath = string.Format("{0}.cshtml", aspxPath); } //load the page def in Preview mode... int pageDefinitionID = 0; if (int.TryParse(Request.Query["agilityPageDefinitionID"], out pageDefinitionID) && pageDefinitionID > 0) { AgilityContext.IsTemplatePreview = true; string pageTitle = string.Empty; AgilityContentServer.AgilityPageDefinition _currentPageDefinition = BaseCache.GetPageDefinition(pageDefinitionID, AgilityContext.WebsiteName); if (_currentPageDefinition != null) { AgilityContext.CurrentPageTemplateInPreview = _currentPageDefinition; pageTitle = string.Format("Template Preview - {0}", _currentPageDefinition.Name); ViewData.Model = new AgilityTemplateModel() { Page = new AgilityPage() { Title = pageTitle } }; ViewResult templateView = new ViewResult() { //TODO: handle template preview with inline code... ViewName = _currentPageDefinition.TemplatePath, ViewData = ViewData }; return; } } } // //404 - we can't load the page, so we have to throw a 404 //TODO: figure out how to return a 404 context.HttpContext.Response.StatusCode = 404; return; } //if we get here and we don't have a page, throw a 404 if (page == null) { context.HttpContext.Response.StatusCode = 404; return; } //set the dynamic page formula items from the last ones that were loaded... AgilityContext.DynamicPageFormulaItem = AgilityContext.LastLoadedDynamicPageFormulaItem; //check if this page is a redirect if (!string.IsNullOrEmpty(page.RedirectURL)) { //redirect to the link specified on the page AgilityHttpModule.RedirectResponse(page.RedirectURL); AgilityCache.TurnOffCacheInProgress(); return; } //set the current language and culture based on the language code... AgilityHttpModule.SetLanguageAndCultureBasedOnPage(page); //set the page in context (Context.items) AgilityContext.Page = page; //setup ouput caching AgilityHttpModule.SetupOutputCaching(context.HttpContext.Request, context.HttpContext.Response, page); //assemble the model data ViewData.Model = new AgilityTemplateModel() { Page = page }; ViewData["Title"] = page.Title; string templatePath = string.Empty; DataView dv = Data.GetContentView(AgilityDynamicCodeFile.REFNAME_AgilityPageCodeTemplates, AgilityDynamicCodeFile.LANGUAGECODE_CODE); if (dv != null && dv.Count > 0) { string filter = string.Format("ReferenceName = '{0}' AND Visible = true", page.TemplateID); DataRow[] rows = dv.Table.Select(filter); if (rows.Length > 0) { templatePath = string.Format("~/Views/{0}/DynamicAgilityCode/{1}/{2}.cshtml", rows[0]["VersionID"], AgilityDynamicCodeFile.REFNAME_AgilityPageCodeTemplates, page.TemplateID); } else { } } if (string.IsNullOrEmpty(templatePath)) { //if it's not in code, check the regular template path templatePath = page.TemplatePath; } if (string.IsNullOrEmpty(templatePath)) { //still null? throw an error... throw new ApplicationException("The template for this page is not available."); } //get the view engine var tempdata = HtmlHelperViewExtensions.GetServiceOrFail <ITempDataDictionaryFactory>(context.HttpContext); var engine = HtmlHelperViewExtensions.GetServiceOrFail <IRazorViewEngine>(context.HttpContext); ViewEngineResult viewResult = engine.GetView(null, templatePath, true); var tempDataDict = tempdata.GetTempData(context.HttpContext); StringWriter sw = new StringWriter(); if (!viewResult.Success || viewResult?.View == null) { throw new ApplicationException("The template for this page is not available."); } var viewContext = new ViewContext(context, viewResult.View, ViewData, tempDataDict, sw, new HtmlHelperOptions()); //render the view... var t = viewResult.View.RenderAsync(viewContext); t.Wait(); string s = sw.GetStringBuilder().ToString(); //set the content type Response.ContentType = "text/html"; t = Response.WriteAsync(s); t.Wait(); //ViewResult view = new ViewResult() //{ // ViewName = templatePath, // ViewData = ViewData //}; //view.ExecuteResult(context); } //TODO: do we get an HttpException here? //catch (HttpException hex) //{ // if (hex.InnerException != null) // { // if (hex.InnerException.InnerException != null && hex.InnerException.InnerException is HttpException) // { // //http exceptions thrown from Partial Controllers are buried... // throw hex.InnerException.InnerException; // } // } // throw hex; //} catch (Exception ex) { StringBuilder sb = new StringBuilder(); sb.Append("ViewData: ").AppendLine(); foreach (string key in ViewData.Keys) { sb.AppendFormat("{0}: {1}", key, ViewData[key]).AppendLine(); } ApplicationException aex = new ApplicationException(sb.ToString(), ex); AgilityHttpModule.HandleIntializationException(aex); } }