C# 在JSON类型不匹配的ASP.NET内核上引发自定义异常

C# 在JSON类型不匹配的ASP.NET内核上引发自定义异常,c#,asp.net-core,C#,Asp.net Core,我试图做的是在JsonTokenType和我要转换到的对象/结构之间存在类型不匹配时抛出我自己的异常 例如,我的对象是LoginRequest: public class LoginRequest { [Required] public string Username { get; set; } [Required] public string Password { get; set; } } 和我的控制器: [HttpPost] public async Ta

我试图做的是在
JsonTokenType
和我要转换到的
对象/结构之间存在类型不匹配时抛出我自己的异常

例如,我的对象是LoginRequest:

public class LoginRequest
{
    [Required]
    public string Username { get; set; }
    [Required]
    public string Password { get; set; }
}
和我的控制器:

[HttpPost]
public async Task<IActionResult> CreateCredentialsAsync([FromBody] LoginRequest request)
{
    // Do Stuff
}
现在,从一个
iasyncationfilter
中,我可以读取
ModelState
并看到它是无效的,但我看不到区分错误原因和抛出不同异常的方法

我想做的是抛出一个
CustomBadRequestException(错误代码:3,消息:“真的,你认为那应该是一个数字而不是一个字符串”)
,但是如果他们根本无法提供用户名,我想抛出
DifferenticCustomBadRequestException(错误代码:2,消息:“不错,试试黑客”)

我是否需要一个定制的模型绑定器来实现这一点(或者甚至扩展现有的模型绑定器),或者我是否需要某种反序列化设置和/或转换器来根据出错的地方提供更具体的异常,或者两者都需要


附加问题:是否可以在调用操作筛选器之前收集模型状态中的所有错误(这听起来似乎绝对需要自定义模型绑定器,但我想我会问)?

我不确定我是否完全理解您的问题陈述,但假设您希望对模型反序列化进行更多控制,可以对MVC json serialiser选项进行一些调整:

public void配置服务(IServiceCollection服务)
{
services.AddMvc(o=>{})
.AddJsonOptions(s=>
{
s、 SerializerSettings.Converters.Add(new Converter());//获得更多控制的一种方法是对您的类型使用自定义转换器,请参见下面的实现
//如果您想要的是更简单一点的东西,那么设置行为和处理一般错误事件也可能有效
s、 SerializerSettings.MissingMemberHandling=MissingMemberHandling.Error;//您可能希望这样做,以便丢失
s、 SerializerSettings.Error=委托(对象发送方,ErrorEventArgs args args)
{
//在这里抛出自定义异常
var message=args.ErrorContext.Error.message;
args.ErrorContext.Handled=false;
};
});
}
实现转换器相当容易:

类转换器:JsonConverter
{
公共覆盖boolcanwrite=>false;
公共重写void WriteJson(JsonWriter writer、LoginRequest值、JsonSerializer序列化程序)
{
抛出新的NotImplementedException();
}
公共重写LoginRequest ReadJson(JsonReader阅读器,类型objectType,LoginRequest existingValue,bool hasExistingValue,JsonSerializer序列化程序)
{
//你的逻辑在这里
}
}

UPD在更好地了解了您的特定需求之后,重新处理基本类型似乎试图摆弄MVC serialiser有点太麻烦了。原因是,您所追求的控制级别(特别是检查基元类型)似乎在
JsonTextReader
级别上可用,但它似乎是覆盖的,这意味着重新实现大量库代码:

services.AddMvc(o=>
{
o、 InputFormatters.RemoveType();
o、 Add(新的MyJsonInputFormatter(logger、serializerSettings、charPool、objectPoolProvider));//在实例化格式化程序之前,有很多参数需要从某处获取。
})
....
类MyJsonInputFormatter:JsonInputFormatter{
公共重写异步任务ReadRequestBodyAsync(
InputFormatterContext上下文,
编码
{
…您在这里的整个实现。。。
}
}

因此,我认为最可行的方法是在MVC之前注入自定义中间件,并按照原始json的方式进行操作。由于MVC将需要再次重新读取json(用于模型绑定等),因此您需要查看我的另一个用于请求蒸汽倒带的转换器。

我同意此特定类型的转换器将很容易,但问题是这需要对我系统中的所有类型进行通用检查。任何时候,当一个用户发布一个带有int的JSON正文时,当它应该是一个字符串时,应该抛出相同的错误,或者任何时候一个用户发布一个带有bool而不是int的JSON正文时,等等。好的,我想我现在更理解你的问题陈述了。重复检查-是否要检查反序列化类型是否与目标成员类型匹配?是,以确保反序列化类型与目标成员类型匹配。