我编写了一个自定义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兼容。