2015-04-14 22 views
0

稱爲在服務方面我有一個非常簡單的配置,通過URL參數傳遞時能正常工作:的Web API定製法[FromBody]參數,通過DataServiceContext.Execute

(段)

builder.EntitySet<MappedAuthorizationGroup>("MappedAuthorizationGroups"); 
var function = builder.Function("TestMethod"); 
//parameter removed here, because I want to POST it ([FromBody]) 
//function.Parameter<string>("id"); 
function.ReturnsCollectionFromEntitySet<MappedAuthorizationGroup>("MappedAuthorizationGroups"); 

控制器方法裝飾又是相當簡單:

[HttpPost] 
[ODataRoute("TestMethod")] //(id={id})")] // Again, parameter removed because i want to POST it 
public IQueryable<MappedAuthorizationGroup> TestMethod([FromBody]string id) 
{ 
    ... code ... 
} 

現在,有幾個答案就在這裏如何通過AJAX調用此方法,但我已經在使用微軟的OData客戶端(DAT aServiceContext)的所有「正常」Odata調用(CRUD操作)...所以我想用它來進行這些自定義調用(使用.Execute(),我假設?)

我非常簡單的客戶端代碼:

var client = new Default.Container(new Uri("thecorrectURI")); 

var methodURI = new Uri(client.BaseUri, "TestMethod"); 

var recs = client.Execute<MappedAuthorizationGroup>(methodURI, "POST", new BodyOperationParameter("id", "C26DFAF6-8F32-429B-9DB3-2F8CF0ABBD3A")); 

然而,這並不正確填充字符串「ID」參數,應該是[FromBody]當它到達服務器。調查後,這似乎是由於1或2個原因:

  1. 內容類型錯誤。但是,如果我將內容類型設置爲「application/x-www-form-urlencoded; charset = utf-8」,我在服務器上得到了一個不同的錯誤,因爲它期望json,我認爲這應該只適用於單一的原始參數。

  2. BodyOperationParameter()序列化爲JSON,但由於某種原因,這在服務器端不起作用。許多帖子都提到它只與簡單的「= myvalue」傳遞兼容。它是否正確?我如何從DataServiceContext對象執行此操作?我需要從更一般的東西上進行這個調用,比如一個HttpClient對象,它很容易設置正確的標題和正文內容?

我想這個移動到身體,而不是一個簡單的URL究其原因,是這個參數實際上將是的GUID的序列化清單,比應該在URL中設置很可能更多。

回答

0

好的,有很多事情可以解決這個問題。每個人都被記錄在網絡上的某個地方,但他們沒有一個真正在一個單一的解決方案中聚集在一起,我可以在這種情況下使用它(這看起來應該是非常常見的......嗯)。總之:

的方法裝飾是對的OData控制器側正確,如:

[HttpPost] 
[ODataRoute("TestMethod")] 
public IQueryable<YourEntity> TestMethod([FromBody]string id) 

(我一直參數名稱爲「ID」,以消除需要建立另一條路線)

在客戶端/消費者端,不得不改變我的原始代碼。首先,我不能使用odata客戶端上下文的東西,因爲它不能給你足夠的參數序​​列化控制權,這是一個問題。此外,它似乎只想發送JSON,並將內容類型設置爲其他內容(對於表單文章),導致了另一個錯誤。可能是因爲我們的OData服務通常適用於所有標準CRUD調用的JSON,並且似乎沒有一種簡潔的方式來表示「僅對某些自定義調用期望非JSON數據」)。同時,將主體內容參數序列化爲JSON不起作用。

因此,使用HttpClient進行更多的請求控制。然而,請求正文內容與格式非常特別。我發送它爲「= stringvalue」,UTF-8編碼。

獲取數據返回也是一個問題,因爲IEnumerable似乎回來包裝在一個「價值」對象...所以反序列化JSON到列表將失敗。用一個名爲「value」的List屬性創建一個類,然後反序列化到這個對象,FINALLY成功了。

最終客戶端代碼實際上得到這個工作(對我來說)看起來有點像:

using (var client = new HttpClient()) 
{ 
    client.BaseAddress = new Uri("http://localhost/mywebsite/odata"); 

    // Content string *MUST* start with = 
    var content = new StringContent("=C26DFAF6-8F32-429B-9DB3-2F8CF0ABBD3A", Encoding.UTF8, "application/x-www-form-urlencoded"); 

    HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/mywebsite/odata/TestMethod"); 
    message.Content = content; 

    // Send the request 
    HttpResponseMessage response = client.SendAsync(message).Result; 

    // Get the result 
    string retval = response.Content.ReadAsStringAsync().Result; 

    // Deserialize the response 
    var jsonSerializer = new JavaScriptSerializer(); 

    var groups = jsonSerializer.Deserialize<TestContainer>(retval); 
} 

和使用反序列化來幫助虛擬「容器」:

public class TestContainer 
{ 
    public List<YourModel> value { get; set; } 
}