jazza1000
jazza1000

Reputation: 4247

How to populate ViewDataDictionary inside an ExceptionFilter

How to retrieve the ViewModel from within an exception filter?

I have an ExceptionFilter, which I am using for a global error handler in an asp .net core 3.1 MVC application. I am trying to get the exception filter to redirect back to the View when there is an error and show validation errors, ie the equivalent of saying:

return View(viewModel)

in the controller

I can redirect to the View, but am a little stuck on how to populate the Model in the ViewResult

ExceptionFilter code

public void OnException(ExceptionContext context)
    {
        string controller = context.RouteData.Values["controller"].ToString();
        string action = context.RouteData.Values["action"].ToString();       

        if (context.Exception is WebServiceException && context.Exception.IsUnauthorized())
        {
            context.Result =  new  RedirectToActionResult("fetchtoken", "Home", new { path = $"/{controller}/{action}" });
        }
        //other type of exception, return the view displaying errors
        else
        {
            context.ModelState.Clear();
            context.ModelState.AddModelError(action, $"error in {action}");
            m_Logger.LogError(context.Exception, $"error in {action}");
            context.ExceptionHandled = true;
            context.ModelState
            context.Result = new ViewResult{
                ViewName = action,
                ViewData = // ??????????????
            };
            
        }
        
    }

In the controller:

  [Authorize]
    [HttpPost]
    public async Task<IActionResult> AuthoriseApiUser(AuthoriseApiViewModel viewModel)
    {
        await m_ApiUserService.AuthoriseUser(viewModel.TenantId, viewModel.UserId); //error thrown here
        return View(viewModel);
    }

Upvotes: 0

Views: 597

Answers (1)

Karney.
Karney.

Reputation: 5031

Through obtaining the value of each key in the form data, the value is compared with the property of the model. Then, assign value to model. For example.

public void OnException(ExceptionContext context)
    {
        string controller = context.RouteData.Values["controller"].ToString();
        string action = context.RouteData.Values["action"].ToString();
        
        //start
        var viewModel = new ViewModel();
        var list = context.HttpContext.Request.Form.AsEnumerable();
        foreach (var meta in list)
        {
            if (meta.Key == "addr")
            {
                viewModel.addr = meta.Value;
            }
        }
        //end
        if (context.Exception is WebServiceException && context.Exception.IsUnauthorized())
        {
            context.Result = new RedirectToActionResult("fetchtoken", "Home", new { path = $"/{controller}/{action}" });
        }
        //other type of exception, return the view displaying errors
        else
        {
            //...
            var modelMetadata = new EmptyModelMetadataProvider();
            context.Result = new ViewResult
            {
                ViewName = action,
                ViewData = ViewData = new ViewDataDictionary(modelMetadata, context.ModelState)
                {
                    Model = viewModel
                }
            };

        }

    }

Model

public class ViewModel
{
    public int id { get; set; }
    [MinLength(2)]
    public string addr { get; set; }
}

Upvotes: 1

Related Questions