【发布时间】:2019-05-10 20:59:19
【问题描述】:
我正在编写托管在 Service Fabric 上的 ASP.NET Core 2.2.0 应用程序。
我有一个代表请求的类,并且我声明了两个构造函数:我自己使用的公共和序列化程序的私有:
public class MyClass
{
private MyClass() // for serializer
{
}
public MyClass(string myProperty) // for myself
{
MyProperty = myProperty ?? throw new ArgumentNullException(nameof(myProperty));
}
[Required]
public string MyProperty { get; private set; }
}
然后,我创建了一个 API 控制器:
[ApiController]
public class MyController
{
[HttpPut]
public async Task<IActionResult> Save([FromBody] MyClass model)
{
throw new NotImplementedException("Doesn't matter in this example");
}
}
我通过使用 Fiddler 调用 null 值来测试它:
PUT /MyController (Content-Type: application/json)
{
"MyProperty": null
}
问题我遇到的问题是我的公共构造函数被调用,myProperty 等于null,这导致ArgumentNullException 被抛出并导致500 Internal Server Error。
我的预期是它将使用私有无参数构造函数和私有设置器。然后,由于控制器标有ApiController 属性,因此该模型将根据数据注释自动进行验证,并将导致 400 Bad Request,因为需要MyProperty。
有趣的是 - 如果我公开默认构造函数,那么它会按预期工作,但我不想这样做。
为什么它不使用私有构造函数,我怎样才能让它使用它而不将它标记为公共?
另一个问题是模型绑定器是否了解如何通过反射使用带有参数的构造函数?
【问题讨论】:
-
你为什么假设它首先使用私有构造函数?我的假设是,如果它存在,它会调用一个公共的,然后寻找一个私有的构造函数。但是,我建议您将此类用于太多事情。也许你需要一个不同的班级。
-
您没有告诉序列化程序 (JSON.NET) 您希望它使用默认构造函数,因此它使用与输入 JSON 最匹配的构造函数
-
其实为什么会有两个构造函数呢?您是否尝试将同一类用于不同目的,即既作为 REST 有效负载又作为模型类用于其他工作?这可能会导致很多问题,因为 REST API 的关注点和限制与域类、ORM DTO 或用于与之通信的类的关注点和限制非常不同其他服务。
-
@YeldarKurmangaliyev 你对我的评论是对的,由于一些无关的事情我心情不好,我道歉并删除了它。这个问题和答案实际上非常相关,因为我也不知道 JSON.NET 将使用参数化构造函数进行反序列化!所以我今天学到了一些东西,我很感谢你。
标签: c# asp.net-core data-annotations model-binding