Ric*_*nia 7 c# asp.net-mvc asp.net-core-mvc
我正在使用.Net 4.5.1创建一个使用MVC 6的ASP.Net 5应用程序.我有一个POST方法,它使用FromBody参数自动获取对象.
[HttpPost]
public IActionResult Insert([FromBody]Agent agent)
{
try
{
var id = service.Insert(agent);
return Ok(id);
}
catch (Exception ex)
{
return HttpBadRequest(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
这只是一个概念的证明,我不会只返回成功的id或错误的完整异常.
当发送有效的JSON时,一切正常.但是,当发送无效的JSON时,我在调试期间收到异常:
抛出异常:Newtonsoft.Json.dll中的'Newtonsoft.Json.JsonReaderException'
附加信息:解析值后,遇到意外字符:l.路径'名称',第2行,第20位.
问题是在此错误之后,该方法被正常调用,但是使用null参数,并且异常不会传播.
我可以检查null并返回一个通用消息,但这并不像原始消息那样有用,它包含重要信息,例如标记名称和无效字符的位置.
所以我想捕获此异常并将其返回给HTTP调用者.我怎么做?像这样的东西:
{"error": "After parsing a value an unexpected character was encountered: l. Path 'Name', line 2, position 20"}
Run Code Online (Sandbox Code Playgroud)
我知道我可以在try/catch块中手动捕获和反序列化JSON,但这对我来说是不可接受的.我想这样做并继续使用FromBody,我发现它很有效率.
小智 12
JsonInputFormatter实际上,默认情况下会在遇到错误时返回空模型 - 但它会填充ModelState所有异常.
因此,您可以通过挖掘来访问所有遇到的错误ModelState:
[HttpPost]
public IActionResult Insert([FromBody]Agent agent)
{
if (!ModelState.IsValid)
{
var errors = ModelState
.SelectMany(x => x.Value.Errors, (y, z) => z.Exception.Message);
return BadRequest(errors);
}
// Model is valid, do stuff.
}
Run Code Online (Sandbox Code Playgroud)
上面的输出是所有异常消息的数组,例如:
[
"After parsing a value an unexpected character was encountered: l. Path 'Name', line 2, position 20",
"Another exception message..."
]
Run Code Online (Sandbox Code Playgroud)
我发现自己遇到了完全相同的问题,但能够找到不同的解决方案。我将在这里分享我的解决方案,以替代@ ypsilo0n的答案。
不用签入每个控制器,if (!ModelState.IsValid)我们可以使用以下中间件过滤器:
public class FooFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var modelState = context.ModelState;
if (modelState != null && modelState.IsValid == false)
{
// this class takes the model state and parses
// it into a dictionary with all the errors
var errorModel = new SerializableError(modelState);
context.Result = new BadRequestObjectResult(errorModel);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,控制器永远不会被调用,因为该中间件在请求之前和结束之前运行。(有关详细信息,请阅读文档)。
当我们设置非null时,context.Result它表示“在此处结束HTTP请求”(文档)-如果您问我,不是很友好/直观,但是可以(请期待返回值)。
使用.net core 1.1
| 归档时间: |
|
| 查看次数: |
2553 次 |
| 最近记录: |