【问题标题】:How to pass a complex type parameter (DTO object) to GET requests?如何将复杂类型参数(DTO 对象)传递给 GET 请求?
【发布时间】:2014-03-28 20:04:01
【问题描述】:

我有一个 n 层应用程序,而核心 Web 服务是使用 Web API 构建的。许多 Web 服务的方法设置为 HTTPGET 并接受 DTO 对象作为参数。我使用 MVC 5 构建的客户端应用程序正在使用 HttpClient 调用此 API。

所以似乎通过使用 client.PostAsJsonAsync() 我可以传递一个对象,而 client.GetAsync() 不允许我这样做。这迫使我在 URL 中明确指定 DTO 的属性,这可行,但似乎有点多余。

有人可以解释为什么这不可能通过 GET 调用并提出更好的做法吗?

【问题讨论】:

  • 您能否提供有关您的 API 的更多详细信息 - 首先用于 GET 请求的对象是什么?通常查询字符串用于过滤 GET 请求以检索与您的特定查询匹配的数据。

标签: asp.net-web-api dto n-tier-architecture multi-tier


【解决方案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);
    }

【讨论】:

  • 我的问题不在于 HTTP 的工作方式,而在于 HttpClient 类。向 client.GetAsync() 添加一个包装器方法是否有意义,它将接受一个对象并为您处理其到 URL 的转换?
  • 如果你使用像 RestSharp 这样的库,那么它有帮助方法,允许你获取一个参数对象并将其序列化到你的查询字符串中(IRestRequest.AddObject(object))
  • @DavidKeaveny RestSharp 方法是否比我建议的扩展方法做得更多?
  • 不是真的;但正如他们所说,您可以编写的最好的代码段是您不必编写的代码段 - 换句话说,如果您使用的库已经提供了功能,为什么要重新发明一个可能有错误的实现?
猜你喜欢
  • 2016-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-27
相关资源
最近更新 更多