2017-06-13 91 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" 
}); 
相关问题