C# 枚举属性、Web API、JSON反序列化和键入

C# 枚举属性、Web API、JSON反序列化和键入,c#,asp.net,enums,C#,Asp.net,Enums,假设我们有一个这样的课程: public class Person { [JsonConstructor] public Person(string name, DayOfWeek bornOnDay) => (Name, BornOnDay) = (name, bornOnDay); public string Name { get; protected set; } public DayOfWeek BornOnDay { get; prot

假设我们有一个这样的课程:

public class Person
{
     [JsonConstructor]
     public Person(string name, DayOfWeek bornOnDay) => (Name, BornOnDay) = (name, bornOnDay);

     public string Name { get; protected set; }

     public DayOfWeek BornOnDay { get; protected set; }
}
还有这样一个端点:

[HttpPost]
[Route("api/people")]
public IHttpActionResult PostPerson([FromBody]List<Person> people)
{
     // whatever
}
Endpoint将收到一份名单,其中包含一名出生于周五的

我想让post操作要么完全发生,要么失败,而不仅仅是没有
enum
typos的对象。。有没有一种方法可以做到这一点,即不接收
字符串而不是
DayOfWeek
,然后使用
Enum.TryParse(…)
确定输入错误

编辑:


实际上,我希望错误发生并且可以检测到,这样我就可以将
400
代码返回给客户端

您可以这样做,您可以根据输入的字符串创建枚举值

public class Person
{
     private string day;
     [JsonConstructor]
     public Person(string name, string bornOnDay){
         this.Name = name;
         this.day = bornOnDay;
     }

     public string Name { get; protected set; }

     public DayOfWeek BornOnDay { 
     get {
          DayOfWeek  weekday;
          if(Enum.TryParse(day, true, out weekday))
            return weekday;  
          else
            return DayOfWeek.None;//add none if no able to parse
     }
 }
注意:
None
是根据避免与系统中的
null
值相关的问题而添加的。

这是怎么回事:

public class Person
{
     [JsonProperty]
     public string Name { get; protected set; }

     [JsonProperty]
     private string _BornOnDay { set {
       //try parse the string, if not successful, throw a nicely
       //formatted error with the original string and what you expect,
       //if parse is successful, set the value to BornOnDay;
     }}

     [JsonIgnore]
     public DayOfWeek BornOnDay { get; protected set; }
}

不确定JsonConstructor属性,从不需要使用它。如果你确实需要它,如果我理解正确,你可以有类似的东西。反序列化程序应该向构造函数中提供一个字符串,然后在其中,您自己为枚举执行解析逻辑。

由于您的枚举不可为空,如果您在枚举中添加一个默认值,如“None”,那么在构造函数中,您可以检查值是否为“None”,如果是,则可能是拼写错误或根本没有设置,您可以抛出一个错误。您可以尝试不起作用的解决方案,因为异常是在端点代码开始执行之前抛出的。谢谢你的时间!因为你不能把你的控制器主体放进try-catch块?您应该有一个全局异常处理程序来处理类似的事情,这样您就不会受到错误发生位置的限制。有一些内置功能,比如HttpResponseException,它在构造函数中接受状态代码。所以你可以从任何地方抛出它。这样你就有了一个对象,你可以把它放在任何方法中,还有一个全局异常处理程序,无论你在哪里使用它,它都会自行处理,而不需要对每个方法体进行检查并一次又一次地格式化错误。它不会被全局异常处理程序捕获。我试过了。这将产生与我在问题中提到的相同的结果,这是不可取的。在这种情况下,您无法检测到它。如果有可能检测到,请告诉我如何检测。我对您提出的解决方案做了一点小小的更改。我将枚举设置为可空,这样我就可以使用.NET内置的enum DayOfWeek了。@Shocky2-我建议不要这样做,遵循。。由于null会产生很多问题,因此我建议将
None
添加为枚举之一,这将在每次访问Bornanday时进行解析。也没有理由使用if语句。无论如何,解析将默认为0(等于无)。如果您对此没有意见,那么您首先就不需要自定义解析器。由于DayOfWeek不可为null,因此如果反序列化程序无法获取该值,它将默认为0。实际上不需要自定义逻辑。如果我使用的是无法更改的库中的枚举,该怎么办?在这种情况下,Nullable是一个令人满意的解决方案。
public class Person
{
     [JsonProperty]
     public string Name { get; protected set; }

     [JsonProperty]
     private string _BornOnDay { set {
       //try parse the string, if not successful, throw a nicely
       //formatted error with the original string and what you expect,
       //if parse is successful, set the value to BornOnDay;
     }}

     [JsonIgnore]
     public DayOfWeek BornOnDay { get; protected set; }
}