从ExceptionFilter#OnException

时间:2018-08-02 14:05:12

标签: asp.net-core

我编写了一个自定义ExceptionFilter,目的是捕获所有抛出的CustomException,并将它们作为错误添加到ModelState中。这样,我可以让服务抛出异常,这些异常将在表单上显示为验证错误。

public class CustomExceptionFilter : IExceptionFilter
{
    private readonly IModelMetadataProvider _modelMetadataProvider;
    private readonly GeneralSettings _generalSettings;

    public CustomExceptionFilter(
        IModelMetadataProvider modelMetadataProvider,
        IOptions<GeneralSettings> generalSettings)
    {
        _modelMetadataProvider = modelMetadataProvider;
        _generalSettings = generalSettings.Value;
    }

    public void OnException(ExceptionContext context)
    {
        var isJsonRequest = IsJsonRequest(context.HttpContext.Request);
        var isFormRequest = context.HttpContext.Request.HasFormContentType;

        if (isJsonRequest)
        {
            HandleJsonRequest(context);
        }
        else if (isFormRequest)
        {
            HandleFormRequest(context);
        }
    }

    private void HandleJsonRequest(ExceptionContext context)
    {
        JsonResult result = null;
        switch (context.Exception)
        {
            case CustomException ce:
                var errors = ce.Messages;
                result = new JsonResult(new { errors });
                break;
            default:
                if (_generalSettings.ShowDebugErrors)
                {
                    result = new JsonResult(new
                    {
                        errors = new List<CustomExceptionMessage>
                        {
                            new CustomExceptionMessage
                            {
                                Key = "",
                                Message = context.Exception.Message
                            }
                        }
                    });
                }
                break;
        }

        if (result != null)
        {
            result.StatusCode = (int)HttpStatusCode.BadRequest;
            context.Result = result;
        }
    }

    private void HandleFormRequest(
        ExceptionContext context)
    {
        switch (context.Exception)
        {
            case CustomException ce:
                var result = new ViewResult
                {
                    ViewName = context.ActionDescriptor.RouteValues["action"],
                    ViewData = new ViewDataDictionary(
                        _modelMetadataProvider,
                        context.ModelState)
                };
                result.ViewData.ModelState.AddModelErrors(ce);
                context.Result = result;
                break;
        }
    }

    private bool IsJsonRequest(HttpRequest request)
    {
        var typedHeaders = request.GetTypedHeaders();
        return typedHeaders.Accept?
                .Any(a => a.MediaType == "application/json")
            ?? false;
    }
}

这很好用,除了我刚刚注意到,当抛出CustomException并且异常过滤器让HandleFormRequest处理时,在内部继续运行回到视图时,POST的模型似乎丢失了,导致网页崩溃(因为它需要模型)。我怀疑这是因为我创建了一个新的ViewResult并将其设置为context.Result(在HandleFormRequest内部)。但是,此ViewResult不包含我的模型。

我的问题是,是否可以通过任何方式从ExceptionContext context检索我的模型并将其添加回ViewResult?几年前,我在.net mvc中找到了this answer,但我正努力将其转换为与.net core兼容。

0 个答案:

没有答案