2017-06-13 346 views
3

我正在使用flurl提交HTTP請求,這非常有用。現在,我需要改變「的Content-Type」頭對於一些要求的「應用/ JSON;的OData =詳細」如何更改FLURL客戶端的HTTP請求內容類型?

public async Task<Job> AddJob() 
    { 

     var flurlClient = GetBaseUrlForGetOperations("Jobs").WithHeader("Content-Type", "application/json;odata=verbose"); 
     return await flurlClient.PostJsonAsync(new 
     { 
      //Some parameters here which are not the problem since tested with Postman 

     }).ReceiveJson<Job>(); 
    } 

    private IFlurlClient GetBaseUrlForOperations(string resource) 
    { 
     var url = _azureApiUrl 
      .AppendPathSegment("api") 
      .AppendPathSegment(resource) 
      .WithOAuthBearerToken(AzureAuthentication.AccessToken) 
      .WithHeader("x-ms-version", "2.11") 
      .WithHeader("Accept", "application/json"); 
     return url; 
    } 

你可以看到我是如何嘗試添加上述標題( .WithHeader("Content-Type", "application/json;odata=verbose")

不幸的是這給了我以下錯誤:

"InvalidOperationException: Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."

我也試過flurl的「ConfigureHttpClient」方法,但怎麼也找不到/在哪裏設置conten t型標題。

+0

的可能的複製[如何內容頭部添加到Flurl(https://stackoverflow.com/questions/32829763/how-to- add-content-header-to-flurl) –

+0

你需要創建一個'HttpRequestMessage'添加一個內容並指定它的類型 – NtFreX

+0

這是2.0版本中修復的小故障(https://www.nuget.org/packages/ Flurl.Http /)。 –

回答

0

的意見和另一篇文章中,我發現(會當我添加引用再次找到它)已經指出我正確的方向。 我的問題的解決方案是這樣的:

 var jobInJson = JsonConvert.SerializeObject(job); 
     var json = new StringContent(jobInJson, Encoding.UTF8); 
     json.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json; odata=verbose"); 

     var flurClient = GetBaseUrlForOperations("Jobs"); 

     return await flurClient.PostAsync(json).ReceiveJson<Job>(); 

編輯:找到相關SO問題:Azure encoding job via REST Fails

+0

纔有效。我發佈了一個替代答案,你可能會更喜歡。 –

0

我不是OData的專家,我不知道你在調用什麼API(SharePoint?),但是基於我見過的大多數例子,你通常想要做的是請求服務器發送在響應中詳細說明OData,而不是聲明您在請求中發送它。換句話說,您想要設置Accept標頭上的;odata=verbose位,而不是Content-Typeapplication/json應該是Content-Type的不夠好,和Flurl將自動設置爲你,所以只是嘗試這種變化,看看它的工作原理:

.WithHeader("Accept", "application/json;odata=verbose"); 
+0

我正在使用Azure媒體服務API。如此處所述,https://docs.microsoft.com/en-us/rest/api/media/operations/job設置接受標題正如您所描述的應該足夠了。但是,只有將Content-Type標題設置爲相同的 – mJay

2

這個答案已經過時。升級至latest version(2.0或以上),問題消失。

事實證明real issueSystem.Net.Http API驗證標頭的方式有關。它區分了請求級別標頭和內容級別標頭,因爲原始HTTP沒有這種區別(除了可能在多部分場景中),我總是會發現它有點奇怪。 Flurl的WithHeaderHttpRequestMessage對象添加了標題,但未驗證Content-Type,它預計將其添加到HttpContent對象中。

這些API做,你可以跳過驗證,雖然Flurl不直接暴露它,你可以在引擎蓋下變得相當容易,而不會破壞流利鏈:

return await GetBaseUrlForGetOperations("Jobs") 
    .ConfigureHttpClient(c => c.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json;odata=verbose")) 
    .PostJsonAsync(new { ... }) 
    .ReceiveJson<Job>(); 

這可能是最好的這樣做你需要什麼,還是利用Flurl的善良的,即不具有直接處理系列化,HttpContent對象等

我強烈考慮改變Flurl的AddHeader(s)實現基於對這個問題用TryAddWithoutValidation

+1

謝謝!非常高興與此,謝天謝地,我可以使用flurl現在與一個Api,需要一個頭,system.net.http認爲無效 –

0
public static class Utils 
{ 
    public static IFlurlClient GetBaseUrlForOperations(string resource) 
    { 
     var _apiUrl = "https://api.mobile.azure.com/v0.1/apps/"; 

     var url = _apiUrl 
      .AppendPathSegment("Red-Space") 
      .AppendPathSegment("HD") 
      .AppendPathSegment("push") 
      .AppendPathSegment("notifications") 
      .WithHeader("Accept", "application/json") 
      .WithHeader("X-API-Token", "myapitocken"); 

      return url; 
    } 

    public static async Task Invia() 
    { 
     FlurlClient _client; 
     PushMessage pushMessage = new PushMessage(); 
     pushMessage.notification_content = new NotificationContent(); 

     try 
     { 
      var flurClient = Utils.GetBaseUrlForOperations("risorsa"); 
      // News news = (News)contentService.GetById(node.Id); 
      //pushMessage.notification_target.type = ""; 
      pushMessage.notification_content.name = "A2"; 
      // pushMessage.notification_content.title = node.GetValue("TitoloNews").ToString(); 
      pushMessage.notification_content.title = "Titolo"; 
      pushMessage.notification_content.body = "Contenuto"; 
      var jobInJson = JsonConvert.SerializeObject(pushMessage); 
      var json = new StringContent(jobInJson, Encoding.UTF8); 
      json.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json"); 
      dynamic data2 = await flurClient.PostAsync(json).ReceiveJson(); 
      var expandoDic = (IDictionary<string, object>)data2; 
      var name = expandoDic["notification_id"]; 
      Console.WriteLine(name); 
     } 
     catch (FlurlHttpTimeoutException ex) 
     { 
      Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + " " + ex); 
     } 
     catch (FlurlHttpException ex) 
     { 
      Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + " " + ex); 
      if (ex.Call.Response != null) 
       Console.WriteLine("Failed with response code " + ex.Call.Response.StatusCode); 
      else 
       Console.WriteLine("Totally failed before getting a response! " + ex.Message); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + " " + ex); 
     } 
    } 
} 

public class NotificationTarget 
{ 
    public string type { get; set; } 
} 

public class CustomData {} 

public class NotificationContent 
{ 
    public string name { get; set; } 
    public string title { get; set; } 
    public string body { get; set; } 
    public CustomData custom_data { get; set; } 
} 

public class PushMessage 
{ 
    public NotificationTarget notification_target { get; set; } 
    public NotificationContent notification_content { get; set; } 
} 
0

我可以對同一問題發表3個答案嗎?:)

Upgrade. Flurl.Http 2.0包括以下改進頭:

  1. WithHeader(s)現在使用TryAddWithoutValidation罩下。只要有這種變化,OP的代碼將按照最初發布的方式工作。

  2. 標題現在設置在請求級別,它解決了another known issue

  3. 當使用SetHeaders與對象表示法,underscores in property names will be converted to hyphens在標題名稱,因爲在標頭連字符是很常見的,底線不是,和連字符不是在C#標識符允許的。

這將是你的情況非常有用:

.WithHeaders(new { 
    x_ms_version = "2.11", 
    Accept = "application/json" 
}); 
相關問題