This post explains how to respond with user friendly messages when http errors occur on your production website in ASP.NET Core. Custom http error messages does not reveal any information about your code or your configuration and custom error messages looks nicer.
Http errors can be client errors with status codes of 400 – 499 or server errors with status codes of 500 – 599. The most common client error is 404 “Not Found” and this error is encountered when a user browses to a page that does not exist.
It is important to respond with the correct status code even if your website displays a custom error message. A status code of 404 tells search engines that the page does not exist and that they not should index this page. If your custom error page responds with a status code of 200 on a page that does not exist you risk to get a lot of duplicates indexed by search engines.
You can inspect responses and status codes under the Network tab when using tools for developers in Google Chrome. Tools for developers in Google Chrome is very useful when you want to debug http status codes.
Services
We first need to register our error handling in the Configure method in the StartUp class. We will respond with a custom error page in environments that not is development, error information during development will be more detailed. The parameter {0} last in the relative url (/home/error/{0}) will contain the status code.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Use error handling
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseStatusCodePagesWithReExecute("/home/error/{0}");
}
// More code ...
} // End of the Configure method
Controller
We need to add an error method in our home controller to handle requests when http errors occurs on our website. We have created 3 different static pages to handle custom error messages, static pages is handled by our IStaticPageRepository. The default error page displays status 500 “Internal Server Error”.
public class homeController : Controller
{
#region Variables
private readonly IStaticPageRepository static_page_repository;
private readonly IGroupRepository group_repository;
private readonly IFinalRepository final_repository;
#endregion
#region Constructors
public homeController(IStaticPageRepository static_page_repository, IGroupRepository group_repository, IFinalRepository final_repository)
{
// Set values for instance variables
this.static_page_repository = static_page_repository;
this.group_repository = group_repository;
this.final_repository = final_repository;
} // End of the constructor
#endregion
#region View methods
// Get the error page
// GET: /home/error/404
[HttpGet]
public IActionResult error(string id = "")
{
// Set the connection id
byte connectionId = 2;
if (id == "404")
{
connectionId = 3;
}
else if(id == "401")
{
connectionId = 4;
}
else
{
connectionId = 2;
}
// Get the error page
StaticPage staticPage = this.static_page_repository.GetOneByConnectionId(connectionId);
staticPage = staticPage != null ? staticPage : new StaticPage();
// Create the bread crumb list
List<BreadCrumb> breadCrumbs = new List<BreadCrumb>(2);
breadCrumbs.Add(new BreadCrumb("Startsidan", "/"));
breadCrumbs.Add(new BreadCrumb(staticPage.link_name, "/home/error/" + id.ToString()));
// Set form values
ViewBag.BreadCrumbs = breadCrumbs;
ViewBag.StaticPage = staticPage;
// Return the view
return View();
} // End of the error method
#endregion
} // End of the class
View
Our error method in our home controller returns a view called error.cshtml in response to http errors. Our error view uses a layout view and displays a title and a description.
@using Annytab.Models
@{
// Get form values
StaticPage staticPage = ViewBag.StaticPage;
// Set meta data
ViewBag.Title = staticPage.title;
ViewBag.MetaTitle = staticPage.title;
ViewBag.MetaDescription = staticPage.meta_description;
ViewBag.MetaKeywords = staticPage.meta_keywords;
ViewBag.MetaCanonical = "http://www.mysite.nu/home/error";
ViewBag.MetaRobots = staticPage.meta_robots;
// Set the layout for the page
Layout = "/Views/shared_front/_standard_layout.cshtml";
}
@*Title*@
<h1>@ViewBag.Title</h1>
@*Description*@
<div class="annytab-basic-bread-text">@Html.Raw(staticPage.main_content)</div>
<div class="annytab-basic-space"></div>
@section scripts {
<script>$("#txtSearch").focus();</script>
}