Объедините данные URL с телом HTTP-запроса POST в ServiceStack - PullRequest
2 голосов
/ 20 мая 2019

Я хотел бы иметь возможность отправлять данные в REST API следующим образом:

POST /foo/b HTTP/1.1
Accept: application/json
Content-Type: application/json

{ "Qux": 42, "Corge": "c" }

Сегмент URL после foo (т. Е. b) также содержит данные, которые мне нужно записать в переменную на стороне сервера. Я пытался реализовать эту функцию в ServiceStack (см. Код ниже), но тело ответа: null.

Вот первый тип запроса:

[Route("/foo/{Bar}", "POST")]
public class PostFooRequest : IReturn<PostFooResponse>
{
    public string Bar { get; set; }

    [ApiMember(ParameterType = "body")]
    public Foo Body { get; set; }
}

Как видите, Bar является переменной URL. Класс Foo определяется следующим образом:

public class Foo
{
    public int Qux { get; set; }
    public string Corge { get; set; }
}

Кроме того, ответ выглядит так:

public class PostFooResponse
{
    public string Bar { get; set; }
    public Foo Foo { get; set; }
}

Наконец, сама служба определяется следующим образом:

public class ReproService : Service
{
    public object Post(PostFooRequest request)
    {
        return new PostFooResponse { Bar = request.Bar, Foo = request.Body };
    }
}

Обратите внимание, что этот метод просто повторяет значения request в ответе.

Когда я выполняю вышеуказанный запрос, я получаю только значение Bar:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"bar":"b"}

Установка точки останова в методе Post показывает, что request.Body равно null.

Как мне написать код, чтобы у API был нужный контракт?

FWIW, я знаю этот вопрос , но ответ только объясняет, в чем проблема; не как решить.

1 Ответ

2 голосов
/ 20 мая 2019

Если вы хотите перевести текущий запрос в следующее DTO, сериализатор должен иметь возможность заполнить свойства:

[Route("/foo/{Bar}", "POST")]
public class PostFooRequest : IReturn<PostFooResponse>
{
    public string Bar { get; set; }

    public int Qux { get; set; }
    public string Corge { get; set; }
}

Сериализатор не может знать, как десериализовать отправляемый вами объект.

Глядя на ваше DTO и запрос, я ожидал бы другой запрос.

POST /foo/b HTTP/1.1
Accept: application/json
Content-Type: application/json

{
    "Foo": {  "Qux": 42, "Corge": "c" }
}

Другой способ получения FormData будет использовать следующее свойство в вашей службе ServicestackRequest.FormData.Убедитесь, что вы звоните не в DTO, а в столицу Request.

...