2014-03-28 641 views
2

我有一個n層應用程序,而核心Web服務是使用Web API構建的。許多Web服務的方法都設置爲HTTPGET並接受DTO對象作爲參數。我使用MVC 5構建的客戶端應用程序使用HttpClient調用此API。如何將複雜類型參數(DTO對象)傳遞給GET請求?

所以它似乎通過使用client.PostAsJsonAsync()我可以傳遞一個對象,而client.GetAsync()不允許我這樣做。這迫使我在URL中顯式指定DTO的屬性,該屬性起作用,但似乎有點多餘。

有人可以解釋爲什麼這不可能通過GET調用,並建議更好的做法?

+0

您可以提供關於您的API的更多詳細信息 - 第一個用於GET請求的對象是什麼?通常,查詢字符串用於過濾GET請求以檢索與特定查詢匹配的數據。 –

回答

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); 
    } 
+0

我的問題不在於HTTP的工作方式,而在於HttpClient類更多。向client.GetAsync()添加一個封裝器方法是否有意義,它將接受一個對象併爲你處理它到URL的轉換? – kob490

+0

如果你使用像RestSharp這樣的庫,那麼它有一個幫助器方法,它可以讓你獲取一個參數對象並將其序列化到你的查詢字符串中(IRestRequest.AddObject(object)) –

+0

@DavidKeaveny RestSharp方法做的不僅僅是擴展我建議的方法? –

相關問題