spaasis
spaasis

Reputation: 469

ASP.NET Core: global handling for showing exception message in current page

In my application I have a set of errors that are "expected" and thus they shouldn't redirect the user to a full error page when they occur. For example, I would like to show the error message in a red box above the current page.

I can easily catch an error on a model action and show the message on the current view, but I was wondering how to do it globally.

I tried a custom middleware with TempData and a filter with ModelState, but can't wrap my head around how to actually pass the error data back to the current page.

This works for a single model (setting the error data in TempData):

public async Task<IActionResult> OnPost() {
            try {
                 // methodThatThrows
            }
            catch (ApplicationError e) {
                TempData["Error"] = e.Message;
                return RedirectToPage("Current_Page");
            }
            return RedirectToPage("Other_Page");
        }

For some reason, this doesn't work (in a global middleware), as TempData is empty when the redirect completes. Also setting the middleware doesn't really work with showing the other, more critical errors in the normal error page:

public class ApplicationErrorMiddleware {
        private readonly RequestDelegate _next;
        private readonly ITempDataDictionaryFactory _tempFactory;

        public ApplicationErrorMiddleware(RequestDelegate next, ITempDataDictionaryFactory tempFactory) {
            _next = next;
            _tempFactory = tempFactory;
        }

        public async Task InvokeAsync(HttpContext httpContext) {
            try {
                await _next(httpContext);
            }
            catch (ApplicationError ex) {
                HandleError(httpContext, ex);
            }
        }

        private void HandleError(HttpContext context, ApplicationError error) {
            var tempData = _tempFactory.GetTempData(context);
            tempData.Add("Error", error.Message);

            context.Response.Redirect(context.Request.Path);
        }
    }

Upvotes: 0

Views: 386

Answers (1)

spaasis
spaasis

Reputation: 469

By the tip of @hiiru, I went through a wild goose chase through the configuration options to find a working solution.

My issue was a missing call from the middleware HandleError-method:

        private void HandleError(HttpContext context, ApplicationError error) {
            var tempData = _tempFactory.GetTempData(context);
            tempData.Add("Error", error.Message);
            tempData.Save(); // this call was missing

            context.Response.Redirect(context.Request.Path);
        }

After popping that in there, the tempdata is sent with the redirection back to the original page. Note that this is using the default cookie-based temp data, so no specific configuration is needed.

Now, this works, but it might not be the best way to do this.

Upvotes: 1

Related Questions