Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Are you using any packages like BVN.NotFound handler. I remember of having it one of the CMS 11 projects where it will show 200 in network tab in case of 404 errors. Also any reason why you want to have 200 network tab for 404 errors.
I don't want a 200 error, I want to make sure the 404/500 error status code is passed along. Currently, since the error page I want to use exists in CMS. The web.config points to these pages, and at least the 404 error is sending a statusCode of 404, but the site is obviously not passing that status along to the browser.
Let me make sure I understand correctly. If you need error code passed on to browser, In that case I believe, you can remove any not found handlers (in your project like BVN etc).
public class ErrorPage : SitePage public virtual int StatusCode { get; set; } |
public class ErrorPageController : PageControllerBase<ErrorPage> if (currentPage != null) var code = (int)(HttpStatusCode)currentPage.StatusCode; return View(model); |
<httpErrors errorMode="Custom" existingResponse="Auto"> <remove statusCode="404" /> <error statusCode="404" path="/404-error" responseMode="ExecuteURL" /> </httpErrors> |
I have most of that code in and it is an improvement. However, when I actually type in an invalid URL it still just goes to the default browser 404 page, instead of routing to the NotFound page (/notfound). It also doesn't let me even view the page from the CMS admin view either.
public class ErrorPageController : PageControllerBase<ErrorPage>
{
public ActionResult Index(ErrorPage currentPage)
{
PageViewModel<ErrorPage> model = null;
if (currentPage != null)
{
model = PageViewModel.Create(currentPage);
PageViewModel.Create(currentPage);
}
// Validate that currentPage.StatusCode is a valid enum value before casting
// if (Enum.IsDefined(typeof(HttpStatusCode), currentPage.StatusCode))
// {
// Response.StatusCode = currentPage.StatusCode;
// }
// else
// {
// // Handle the case where currentPage.StatusCode is not a valid status code
// // You might log this issue and set a default status code
// Response.StatusCode = (int) HttpStatusCode.InternalServerError;
// }
var code = (int) (HttpStatusCode) currentPage.StatusCode;
Response.StatusCode = code;
return View(model);
}
}
[ContentType(
DisplayName = "Error Page",
GUID = "1286779b-d4cb-4053-96ba-68622cc796c1",
Description = "Used for various error messages")
]
public class ErrorPage : SitePageData
{
// Define properties here that you want to include on your error pages
// For example, a property for a custom error message
[CultureSpecific] public virtual ContentArea ErrorContentArea { get; set; }
public virtual int StatusCode { get; set; }
}
@using ErrorPage = Page.ErrorPage
@using EPiServer.Web.Mvc.Html
@model CMS.Ellsworth.ViewModels.PageViewModel<ErrorPage>
@if (Model.CurrentPage.DisplayPageTitle)
{
<div class="row header">
<div class="col-xs-12">
<h1>@Model.CurrentPage.PageTitle</h1>
</div>
</div>
}
@Html.PropertyFor(x => x.CurrentPage.ErrorContentArea)
<httpErrors errorMode="Custom" existingResponse="Auto">
<remove statusCode="404" />
<error statusCode="404" path="/not-found" responseMode="ExecuteURL" />
</httpErrors>
At this point I am assuming there is package like BVN which is handling your 404's , you might want to check and remove them to validate this. Also I assume you had created a page in CMS which is accessible at /not-found path.
Make a basic NotFoundController which can that serve up your 404Page
e.g.
public class NotFoundController : Controller
{
#region Fields
//private readonly ILanguagePreferenceResolver languagePreferenceResolver;
private readonly ISiteSettingsProvider settingsProvider;
#endregion
#region Constructors and Destructors
public NotFoundController()
{
// User service locator pattern as this class will be instantiated from BVNetwork library not from StructureMap
//languagePreferenceResolver = ServiceLocator.Current.GetInstance<ILanguagePreferenceResolver>();
settingsProvider = ServiceLocator.Current.GetInstance<ISiteSettingsProvider>();
}
#endregion
#region Public Methods
public ActionResult Index()
{
// set the response headers
Response.Headers["Server"] = string.Empty;
Response.StatusCode = 404;
if (Path.HasExtension(Request.RawUrl))
{
return new EmptyResult();
}
var loader = ServiceLocator.Current.GetInstance<IContentLoader>();
var urlRewriteContext = new UrlRewriteContext(new UrlBuilder(Request.RawUrl));
var currentCulture = urlRewriteContext.Language ?? ContentLanguage.PreferredCulture;
/*
if (!languagePreferenceResolver.IsValidLanguage(currentCulture.Name))
{
var browserLanguages = Request.UserLanguages?.ToList() ?? new List<string>();
var preferredLanguage = languagePreferenceResolver.PreferredLanguageBranch(browserLanguages);
currentCulture = new CultureInfo(preferredLanguage.LanguageID);
}
*/
ContentLanguage.PreferredCulture = currentCulture;
var error404Page = settingsProvider.Current?.Error404Page;
if (!ContentReference.IsNullOrEmpty(error404Page))
{
// Load 404 page content and pass to view
var notFoundPage = loader.Get<NotFoundPage>(
error404Page,
LanguageSelector.Fallback(ContentLanguage.PreferredCulture.Name, true));
Request.RequestContext.SetContentLink(error404Page);
if (notFoundPage != null)
{
return View(Constants.ViewPath.NotFoundPage, new NotFoundPageViewModel(notFoundPage));
}
}
return new EmptyResult();
}
#endregion
}
Your web.config should than look like
<httpErrors errorMode="Custom">
<remove statusCode="404" />
<error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
<remove statusCode="410" />
<error statusCode="410" path="/NotFound" responseMode="ExecuteURL" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" path="/500.aspx" responseMode="ExecuteURL" />
</httpErrors>
Just for absolute completeness my Not Found Page (Your 404 Page) Controller than looks like
/// <summary>
/// Not Found Page Controller
/// </summary>
/// <seealso cref="NotFoundPage" />
public class NotFoundPageController : PageControllerBase<NotFoundPage>
{
#region Public Methods
/// <summary>
/// Indexes the specified current page.
/// </summary>
/// <param name="currentPage">The current page.</param>
/// <returns></returns>
public ActionResult Index(NotFoundPage currentPage)
{
var urlRewriteContext = new UrlRewriteContext(new UrlBuilder(Request.RawUrl));
var currentCulture = urlRewriteContext.Language;
ContentLanguage.PreferredCulture = currentCulture;
var currentculture = ContentLanguage.PreferredCulture;
var page = ServiceLocator.Current.GetInstance<IContentLoader>()
.Get<NotFoundPage>(currentPage.PageLink, currentculture);
// This removes the server from the response, it isn't handled by the URL rewriter.
Response.Headers["Server"] = string.Empty;
var viewModel = new NotFoundPageViewModel(page);
return View(viewModel);
}
#endregion
}
There are some issues with the code you provided, in the ErrorController.cs. I'm not sure what .Error404Page variable should be, since that specific one doesn't exist and I'm not sure where that is set.
I have a Optimizely CMS 11 + Commerce 13 website on .NET Framework 4.7.2. Currently there is a "NotFound" (404) and "Error" (500) pages created in the CMS that display a user-friendly 404 page, except due to this and the pre-existing configuration, anything that actually results in reaching that page like an invalid URL like http://localhost:5000/productproduct will still return a 200 status code in the Network dev tools. I have tried all documentation I've found so far but no luck, and I prefer to accomplish it as close to this method as possible.
Here is the web.config configuration - I have tried PassThrough, Replace, Auto - in the existingReponse.
NotFound.aspx - I know this displays when "Replace" is set as existingResponse, but this is the code there is - the onLoad was the logic for handling applying 404 error. (also tried
<%-- <%@ Page Language="c#" AutoEventWireup="false" Inherits="BVNetwork.NotFound.Core.NotFoundPage.NotFoundBase" %> --%> <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NotFound.aspx.cs" Inherits="BVNetwork.NotFound.Core.NotFoundPage.NotFoundBase" %> <%@ Import Namespace="System.Diagnostics" %> <%-- Note! This file has no code-behind. It inherits from the NotFoundBase class. You can make a copy of this file into your own project, change the design and keep the inheritance WITHOUT having to reference the BVNetwork.EPi404.dll assembly. If you want to use your own Master Page, inherit from SimplePageNotFoundBase instead of NotFoundBase, as that will bring in what is needed by EPiServer. Note! you do not need to create a page type for this 404 page. If you use the EPiServer API, and inherit from SimplePageNotFoundBase, this page will run in the context of the site start page. Be very careful with the code you write here. If you reference resources that cannot be found you could end up in an infinite loop. The code behind file might do a redirect to a new page based on the redirect configuration if it matches the url not found. The Error event (where the rest of the redirection is done) might not run for .aspx files that are not found, instead it redirects here with the url it could not find in the query string. Available properties: Content (BVNetwork.FileNotFound.Content.PageContent) // Labels you can use - fetched from the language file Content.BottomText Content.CameFrom Content.LookingFor Content.TopText Content.Title UrlNotFound (string) The url that cannot be found Referer (string) The url that brought the user here It no referer, the string is empty (not null) If you are using a master page, you should add this: <meta content="noindex, nofollow" name="ROBOTS"> to your head tag for this page (NOT all pages) --%> <script runat="server" type="text/C#"> protected override void OnLoad(EventArgs e) { // Calls the base class OnLoad method. // base.OnLoad(e) Response.StatusCode = 404; // Set the status code to 404. // Preserve the original behavior where the server returns the content of the NotFound page. Response.TrySkipIisCustomErrors = true; Response.End(); } </script> <%@ Register TagPrefix="EPiServer" Namespace="EPiServer.WebControls" Assembly="EPiServer" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > <html> <head> <title><%= Content.Title %></title> <meta content="noindex, nofollow" name="ROBOTS" /> </head> <body> <h1>Andrew!!!!!</h1> <form id="FileNotFoundForm" method="post" runat="server"> <div class="logo"> Company Logo Here </div> <h1> <%= Content.Title %></h1> <div style="width: 760px"> <div style="padding-left: 10px; float: left; width: 550px"> <%= Content.TopText %> <%= Content.LookingFor %> <div class="notfoundbox"> <%= HttpUtility.HtmlEncode(UrlNotFound.ToString()) %> <%= Referer.Length > 0 ? Content.CameFrom : "" %> <%= Referer.Length > 0 ? HttpUtility.HtmlEncode(Referer) : "" %> </div> <%= Content.BottomText %> </div> <div style="padding-right: 10px; padding-left: 10px; float: right; width: 200px"> </div> </div> <div class="floater"> 404 </div> </form> </body> </html>
I turned on Error handling, but still the same issues.
