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

时间:2014-03-28 20:04:01

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

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

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

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

1 个答案:

答案 0 :(得分:3)

为什么在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);
    }