ASP.NET Core FromBody模型绑定:使用Interafece字段绑定类

时间:2018-05-30 09:29:43

标签: c# asp.net asp.net-mvc asp.net-core .net-core

我一直在苦苦挣扎,我发现了一些问题,但没有人能满足我的需求。我会尝试发布一个更好的问题以及我尝试过的一些事情。

情况如下: 我有一个APIGateway和一个WebApp。到目前为止,WebApp向APIGateway发送了POST请求。我使用FromBody属性发送更大的对象,这也很好,直到我介绍接口:))

以下是一些代码:

Web应用程序:

public interface ICommand
{
    Guid CorrelationId { get; set; }

    Guid SocketId { get; set; }
}

public class Command : ICommand
{       
    public Command(Guid CorrelationId, Guid SocketId)
    {
        this.CorrelationId = CorrelationId;
        this.SocketId = SocketId;
    }

    public Guid CorrelationId { get; set; } = new Guid();

    public Guid SocketId { get; set; } = new Guid();
}    

public interface IDocument
{
    Guid Id { get; set; }

    ulong Number { get; set; }
}

public class Document : IDocument
{
    public Guid Id { get; set; } = new Guid();

    public ulong Number { get; set; } = 0;
}

public interface ICreateDocumentCommand : ICommand
{
    IDocument Document { get; set; }
}

public class  CreateDocumentCommand : Command, ICreateDocumentCommand
{
    public CreateDocumentCommand(IDocument Document, ICommand Command) : base(Command.CorrelationId, Command.SocketId)
    {
        this.Document = Document;
    }

    public IDocument Document { get; set; }
}

APIGateway:

[HttpPost]
public async Task<IActionResult> Create([FromBody]CreateDocumentCommand documentCommand)
{
    if (documentCommand == null)
    {
       return StatusCode(403);
    }
    return Json(documentCommand.Document.Id);
}

使用案例

public class InventoryList : Document
{
    public Guid WarehouseId { get; set; } = new Guid();
}

// Example document class
////////////////////////////////////////
// Example POST Request

ICommand command = new Command(messageId, socketId);
switch (item.GetType().Name)
{
    case "InventoryList":
    command = new CreateDocumentCommand((InventoryList)item, command);
    break;
}
string result = await PostAsync($"{apiGatewayAddress}{item.GetType().BaseType.Name}/Create", command, accessToken);

我的POST发送功能:

public async Task<string> PostAsync<T>(string uri, T item, string authorizationToken = null, string authorizationMethod = "Bearer")
{
    JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };

    HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, uri);
    requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

    requestMessage.Content = new StringContent(JsonConvert.SerializeObject(item, typeof(T), jsonSerializerSettings), System.Text.Encoding.UTF8, "application/json");
    return await _client.SendAsync(requestMessage).Result.Content.ReadAsStringAsync();
}

如您所见,我在JSON序列化设置中包含 TypeNameHandling.All ,将发送请求并调用APIGateway中的Create。但是参数documentCommand为NULL。

我读过这个: Asp.Net Core Post FromBody Always Null

这: ASP.NET Core MVC - Model Binding : Bind an interface model using the attribute [FromBody] (BodyModelBinder)

这: Casting interfaces for deserialization in JSON.NET

尝试了各种魔术技巧,创建了新的构造函数,用[JSONConstructor]标记它们,仍然没有成功。此外,我尝试将APIGateway Cerate方法参数类型更改为ICreateDocumentCommand,并再次获得null。我一直在网上搜索一些模型绑定技巧但是我找不到任何与FromBody绑定的东西。我也找到了一些解决方案,包括DI,但我正在寻找一个简单的解决方案。我希望我们能够找到一个:)

1 个答案:

答案 0 :(得分:1)

事实证明,将接口或类作为JSON传递给内部并不容易。我添加了一个自定义的JSONConverter,现在可以使用了!