很抱歉,是否已经有人回答了这一问题,但我似乎无法在Google或SO上找到解决方案。
在ASP.NET Core中,是否可以编写自定义模型绑定程序或诸如此类,从而使我可以在Web API中获得某些继承支持?
基本上我有一个像这样的课:
public class Order {
public Guid Id { get; set; }
public PaymentContainer PaymentParameters { get; set; }
}
还有像这样的容器类
public class PaymentContainer
{
public string Type { get; set; }
public IPaymentParameters Value { get; set; }
}
以及一些实现IPaymentParameters
接口的类和控制器方法,例如:
[HttpPost]
public IActionResult CreateOrder([FromBody]Order order)
{
}
我非常希望客户端能够发送json,例如:
{
"id" : "1234-..-1234",
"paymentParameters" : {
"type": "SpecialParameters1",
"value" : { /* instance of specialparameters1 here */ }
}
}
然后将“ value”属性设置为“ SpecialParameters1”的实例,使其到达控制器方法中。
我认为有可能写一个Modelbinder,但是我不太了解如何完成。
注意:我知道可以更改Json.Net TypeNameHandling的方法,但我宁愿不要搞乱依赖于json序列化程序的所有其他内容,而只需对其进行设置设置为“自动”或“全部”将为远程执行代码打开一些途径。
说明:第一个答案后的一个小更新 目标是拥有多个参数实例,以便以下输入也“有效”
{
"id" : "1234-..-1234",
"paymentParameters" : {
"type": "SpecialParameters2",
"value" : { /* instance of specialparameters2 here */ }
}
}
当然我会上课
public class SpecialParameters1 : IPaymentParameters{}
public class SpecialParameters2 : IPaymentParameters{}
答案 0 :(得分:0)
是的,它的ASP.NET Core在模型绑定方面非常擅长,我将为您设置示例(只是重构了一些类-不确定要做什么,但作为原理的证明我认为它会很合适)
在“视图”中,您可以设置以下内容:
<h2>orders with ajax</h2>
<dl>
<dt>Order Id:</dt>
<dd id="order-id">D3BCDEEE-AE26-4B20-9170-D1CA01B52CD4</dd>
<dt>Payment container - Type</dt>
<dd id="order-paymentcontainer-type">Card payment</dd>
<dt>Payment Parameters - Name</dt>
<dd id="order-paymentcontainer-paymentParameters-name">Card payment nr. 1</dd>
<dt>Payment Parameters - Provider</dt>
<dd id="order-paymentcontainer-paymentParameters-provider">Big Bank</dd>
</dl>
<a id="submit-button">Process order</a>
@section Scripts {
<script src="~/js/paymentTest.js"></script>
}
然后您设置课程:
public class Order
{
public Guid Id { get; set; }
public PaymentContainer PaymentContainer { get; set; }
}
public class PaymentContainer
{
public string Type { get; set; }
public PaymentParameters PaymentParameters { get; set; }
}
public class PaymentParameters
{
public string Name { get; set; }
public string Provider { get; set; }
}
然后在您的paymentTest.cs中写
var order = {
Id: "",
PaymentContainer: {
Type: "",
PaymentParameters: {
Name: "",
Provider: ""
}
}
};
order.Id = document.getElementById("order-id").innerHTML;
order.PaymentContainer.Type = document.getElementById("order-paymentcontainer-type").innerHTML;
order.PaymentContainer.PaymentParameters.Name = document.getElementById("order-paymentcontainer-paymentParameters-name").innerHTML;
order.PaymentContainer.PaymentParameters.Provider = document.getElementById("order-paymentcontainer-paymentParameters-provider").innerHTML;
$("#submit-button").click(function () {
$.ajax({
url: 'api/orders',
type: 'POST',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(order),
success: function (data) {
location.reload();
}
});
});
最后是用于绑定的控制器设置方法
[Route("api/orders")]
[HttpPost]
public async Task ProcessOrder([FromBody] Order order)
{
var orders = new List<Order>();
orders.Add(order);
// and some other code ...
}
答案 1 :(得分:0)
请纠正我,如果我错了-这里的主要问题是您无法将View绑定的数据绑定到控制器吗?
您无法绑定,因为您的Order类包含接口(间接),并且MVC无法绑定接口。 没关系。因为接口是抽象行为而不是数据。
此问题的可能解决方法是在CreateOrder方法中使用OrderViewModel而不是Order类型。 即:
public IActionResult CreateOrder([FromBody]OrderViewModel order)
然后OrderViewModel将具有PaymentContainerViewModel而不是PaymentContainer, 它将具有具体的PaymentParameters值 而不是接口IPaymentParameters Value,并且绑定是个不错的选择。