Как передать параметр сложного типа (объект DTO) в запросы GET?

У меня есть n-уровневое приложение, в то время как основной веб-сервис построен с использованием веб-API. многие из методов веб-службы установлены как HTTPGET и принимают объект DTO в качестве параметра. мое клиентское приложение, созданное с использованием MVC 5, использует HttpClient для вызова этого API.

поэтому кажется, что с помощью client.PostAsJsonAsync() я могу передать объект, тогда как client.GetAsync() не позволяет мне это делать. это заставляет меня явно указывать свойства DTO в URL-адресе, который работает, но кажется излишним.

Может кто-нибудь объяснить, почему это невозможно с помощью вызова GET, и предложить лучшую практику?

1 ответ

Решение

Почему передача данных в URI кажется избыточной? Спецификация HTTP говорит, что методы GET не должны использовать содержимое, отправленное в теле. Это в первую очередь облегчает кэшированию возможность кэшировать ответы на основе только URI, метода и заголовков. Требование кешировать синтаксический анализ тела сообщения для идентификации ресурса было бы очень неэффективным.

Вот основной метод расширения, который сделает всю работу за вас,

 public static class UriExtensions
    {
        public static Uri AddToQuery<T>(this Uri requestUri,T dto)
        {
            Type t = typeof (T);
            var properties = t.GetProperties();
            var dictionary = properties.ToDictionary(info => info.Name, 
                                                     info => info.GetValue(dto, null).ToString());
            var formContent = new FormUrlEncodedContent(dictionary);

            var uriBuilder = new UriBuilder(requestUri) {Query = formContent.ReadAsStringAsync().Result};

            return uriBuilder.Uri;
        }
    }

и при условии, что у вас есть DTO, как это,

 public class Foo
    {
        public string Bar { get; set; }
        public int Baz { get; set; }
    }

Вы можете использовать это так.

    [Fact]
    public void Foo()
    {
        var foo = new Foo()
        {
            Bar = "hello world",
            Baz = 10
        };

        var uri = new Uri("http://example.org/blah");
        var uri2 = uri.AddToQuery(foo);

        Assert.Equal("http://example.org/blah?Bar=hello+world&Baz=10", uri2.AbsoluteUri);
    }
Другие вопросы по тегам