Чтение динамического объекта FromBody в WebAPI просто не работает - PullRequest
0 голосов
/ 24 января 2019

Я нашел много информации по этой теме, но ни один из этих сайтов и статей не мог решить мою проблему. У меня довольно простой метод:

[HttpPost, Route("Diagnosis/{lkNo}/Tree/{nodeID:int}/Answer")]
public List<TreeNode> AnswerTreeNode(string lkNo, int nodeID, 
[FromBody] dynamic data) {
    // So some stuff
}

Когда я вызываю этот метод, он заполняет первые два параметра, но данные всегда равны нулю. Вот мой тестовый запрос, полученный сервером:

POST /Diagnosis/LK-28084453/Tree/0/Answer HTTP/1.1
Cache-Control: no-cache
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate
Cookie: ASP.NET_SessionId=*****; __RequestVerificationToken=*****
Host: localhost:51124
User-Agent: PostmanRuntime/7.6.0
Postman-Token: *****
Content-Length: 5
Content-Type: application/x-www-form-urlencoded

=Test

Отправка параметра как json приводит к тому же результату:

...
Content-Length: 25
Content-Type: application/json

{ "value": "some value" }

Что бы я ни пытался, данные всегда нулевые. Вот мой конфиг маршрута:

// WebAPI
GlobalConfiguration.Configure(config => {
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DiagnosisApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    // Default return JSON
    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
    config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
        new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();

    config.MessageHandlers.Add(new MyHandler());
});

public class MyHandler : System.Net.Http.DelegatingHandler {
    protected override async System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage> SendAsync(
                                             System.Net.Http.HttpRequestMessage request,
                                                System.Threading.CancellationToken token) {
        System.Net.Http.HttpMessageContent requestContent = new System.Net.Http.HttpMessageContent(request);
        string requestMessage = requestContent.ReadAsStringAsync().Result; // This one contains the raw requests as posted abve

        return await base.SendAsync(request, token);
    }
}

У вас есть идея, что здесь не так?

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Я решил проблему, удалив временный обработчик сообщений.Кроме того, я изменил атрибут данных на тип JObject от Newtonsoft.Теперь я могу легко реализовать свою собственную процедуру интерпретации полученных данных.Например:

if (data["result"].Type == JTokenType.Boolean && data["result"].Value<bool>())

Вот мой код Javascript:

node.treat = function (result) {
    if (result !== undefined)
        $.ajax({
            url: 'Diagnosis/' + vm.data.lkNo() + '/Tree/' + node.id + '/Answer',
            data: JSON.stringify({ result: result }),
            type: 'POST',
            contentType: "application/json",
            success: function (response) { /* do something */ }
        };
}

Работает как шарм!

0 голосов
/ 24 января 2019

Мое предложение было бы не использовать динамический тип в сигнатуре вашего метода.

Измените его на string и убедитесь, что вы также сериализуете то, что отправляете в API.

Как только вы видите поступающие данные, вы можете использовать что-то вроде Newtonsoft Json для анализа строки в динамическом объекте, и вы можете взять ее оттуда.

Ваш метод станет:

public List<TreeNode> AnswerTreeNode(string lkNo, int nodeID, 
[FromBody] string data) {
    // parse data into dynamic here
}
...