During this session, we discuss Exception Handling in ASP.NET Core in detail, also we will show you how to implement the changes on your web app to display your customized message when some exceptions happen. In session 56 we discussed exception handling a little bit, but in this session, we talk about it in depth.
404 Error Handling in ASP.NET Core
When we request a page on a website or a web app that does not exist within that area, HTTP code 404 will be returned to the browser. In some cases, browsers handle this type of error, but we can control the 404 error and display our desired message to the user.
In This session, we introduce three middleware that can handle 404 error to stop the browser to display its designed page. Also, as we explained earlier in session 7, we can use the middleware inside Configure in the Startup class.
The first method is UseStatusCodePages middleware, for implementing this method we just need to add this middleware in HTTP pipeline. It is easy to implement but it doesn’t meet our requirement and it just display another predefined message to the user.
The second method needs more implementation, for this method we need to use UseStatusCodePagesWithRedirects middleware, then we should create a respective Controller and Action Method to handle the error page. finally, we need to create a View in the Views/Shared folder to be accessible by all the controllers. This method works for us and we can see our customized page to handle 404 error. But when we use this method, the web app does not return 404 HTTP code to the browser which could be a little bit problematic. Also, when the requested page is redirected to the error page, the URL is changed to the Error page path which is not acceptable in some circumstances.
To solve the above-mentioned issues, we can implement the third method, all the implementation is the same as the above method, just we need to use UseStatusCodePagesWithReExecute middleware instead of the UseStatusCodePagesWithRedirects middleware.
As explained above, first we need to add the required middleware in the Configure method of the Startup Class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(new DeveloperExceptionPageOptions { SourceCodeLineCount = 10 }); } else { app.UseStatusCodePagesWithReExecute("/Error/{0}"); } app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); } |
Then, we need to create the respective controller and action method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class ErrorController : Controller { [Route("Error/{statusCode}")] public IActionResult NotFound(int statusCode) { switch (statusCode) { case 404: ViewBag.ErrorTitle = "The Requested Page is not Exist"; break; default: ViewBag.ErrorTitle = "Unexpected Error"; break; } return View("Error"); } } |
Lastly, we need to create a View in the Views/Shared folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@{ ViewBag.Title = "Error Page"; } <h1 class="alert alert-danger my-5"> @ViewBag.ErrorTitle </h1> <h4 class="alert alert-danger my1"> @ViewBag.ErrorMessage </h4> |
Now, our web app can handle 404 error and display the customized message to the user.
Exception Handling in ASP.NET Core
Almost we can say always there is a possibility of unexpected exceptions in all the applications. If such an exception occurs in an application, it would stop working, and may the browser display a generic message regarding the exception. To control such a behavior, we can place our code in the Try / Catch block which can handle this situation.
Moreover, to display the proper message to the user, we can use UseExceptionHandler middleware and then add the respective action method in the defined controller.
Implementation of this part is very similar to the above code; and first, we need to add the middleware.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(new DeveloperExceptionPageOptions { SourceCodeLineCount = 10 }); } else { app.UseExceptionHandler("/Error"); app.UseStatusCodePagesWithReExecute("/Error/{0}"); } app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); } |
Next, we need to add the action method.
1 2 3 4 5 6 7 8 9 10 11 |
[Route("Error")] public IActionResult ExceptionError() { ViewBag.ErrorTitle = "Unexpected Error Occured"; ViewBag.ErrorMessage = "Please report this error to the website administrator"; return View("Error"); } |
Now we can use the designed View in the previous part to display the exception error message.
Display Specific Message to the Specific Exception
In some circumstances, we are aware of some exceptions which can not be controlled due to the nature of the application. In this situation, we can show the user a more specific message and lead them to solve it. For instance, when we try to delete some Categories that have some children (cost records that include those categories), The EF Core throws an exception while it tries to save the changes in the database.
Thus, as we know the reason for the exception, we can handle it more accurately and display a more detailed message to the user.
For solving the above-mentioned issue, we need to modify the Repository and Controller to handle the situation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public IEnumerable<Category> Delete(IEnumerable<int> DeleteList) { try { var DeleteCatList = webAppDBContext.Categories.Where(z => DeleteList.Contains(z.ID)).ToList(); webAppDBContext.Categories.RemoveRange(DeleteCatList); webAppDBContext.SaveChanges(); return DeleteCatList; } catch (DbUpdateException ex) { return null; } } |
Now, the controller understands if the method returns a null value it means a DB update exception occurs and the error page with the desired message should be displayed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[HttpPost] public IActionResult Delete(IEnumerable<int> SelectedCatDelete) { var delList = categoryRepository.Delete(SelectedCatDelete); if(delList == null) { ViewBag.DelError = "Yes"; ViewBag.DelTitle = "Delete operation has not been completed"; ViewBag.DelMessage = "This record can not be deleted, beacuse one or more cost record use this category."; return View("Error"); } return RedirectToAction("Index"); } |
Also, we need to modify the View as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
@{ ViewBag.Title = "Error Page"; } @if (ViewBag.DelError == "Yes") { <h1 class="alert alert-danger my-5"> @ViewBag.DelTitle </h1> <h4 class="alert alert-danger my1"> @ViewBag.DelMessage </h4> } else { <h1 class="alert alert-danger my-5"> @ViewBag.ErrorTitle </h1> <h4 class="alert alert-danger my1"> @ViewBag.ErrorMessage </h4> } |
If you need more details, watch this session video. Also, to be updated about our coming sessions, follow us on Instagram, Facebook, Telegram, or YouTube. Moreover, you can have access to the list of all sessions HERE and you can download this session source code from our GitHub.
You can download this Session Slides form HERE.