如何向 GET 请求传递复杂类型参数(DTO 对象)?

问题描述 投票:0回答:1

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

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

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

asp.net-web-api dto n-tier-architecture multi-tier
1个回答
5
投票

为什么在 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.