2013-02-19 65 views
103

我目前在我的Web API服務的消息處理程序覆蓋「SendAsync」如下:如何在Web API消息處理程序中提取自定義標題值?

protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{ 
    //implementation 
} 

在這個代碼,我需要檢查一個名爲MyCustomID自定義添加請求標頭值。問題是,當我做到以下幾點:

if (request.Headers.Contains("MyCustomID")) //OK 
    var id = request.Headers["MyCustomID"]; //build error - not OK 

...我收到以下錯誤信息:

不能申請用[]索引到 型「的表達System.Net.Http .Headers.HttpRequestHeaders'

如何通過傳遞到此OVE的HttpRequestMessageMSDN Documentation)實例訪問單個定製請求頭rridden方法?

+0

如果您使用'request.Headers.Get(「MyCustomID」);'? – udidu 2013-02-19 21:13:47

+0

「HttpRequestHeaders」類型沒有'Get'。消息:「無法解析符號'獲取'」被產生。 – atconway 2013-02-19 21:20:39

回答

179

嘗試這樣:

IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID"); 
var id = headerValues.FirstOrDefault(); 

還有你可以使用,如果你並不總是保證有機會獲得頭頭一個TryGetValues方法。

+18

GetValues的空檢查不提供任何值,因爲它永遠不會返回null。如果頭文件不存在,你會得到一個InvalidOperationException異常。你需要使用TryGetHeaders,如果請求中可能不存在標題並檢查錯誤響應,或者圍繞GetValues調用嘗試/ catch(不推薦)。 – 2013-02-19 22:58:36

+2

@Drew request.Headers.Single(h => h.Key ==「Authorization」);少得多的代碼也是這樣做的! – Elisabeth 2014-01-30 19:40:45

+13

爲什麼不僅僅是'var id = request.Headers.GetValues(「MyCustomID」)。FirstOrDefault();' – Gaui 2014-10-14 23:08:20

16

爲了擴大Youssef的回答,我寫了這個方法,這個方法是基於Drew關於頭部不存在的問題,因爲我在單元測試中遇到了這種情況。

private T GetFirstHeaderValueOrDefault<T>(string headerKey, 
    Func<HttpRequestMessage, string> defaultValue, 
    Func<string,T> valueTransform) 
    { 
     IEnumerable<string> headerValues; 
     HttpRequestMessage message = Request ?? new HttpRequestMessage(); 
     if (!message.Headers.TryGetValues(headerKey, out headerValues)) 
      return valueTransform(defaultValue(message)); 
     string firstHeaderValue = headerValues.FirstOrDefault() ?? defaultValue(message); 
     return valueTransform(firstHeaderValue); 
    } 

下面是一個例子用法:

GetFirstHeaderValueOrDefault("X-MyGuid", h => Guid.NewGuid().ToString(), Guid.Parse); 

也看看@ doguhan-uluca的回答一個更通用的解決方案。

+0

嗨!你能解釋這個代碼嗎? FUNC? ;) 謝謝!! – chemitaxis 2013-11-29 23:01:44

+1

'Func'和'Action'是.NET 3.5及以上版本的通用委託簽名結構。我很樂意討論有關該方法的具體問題,但我建議先了解這些方法。 – neontapir 2013-12-02 18:52:05

+1

@neontapir(和其他)第二個參數用於在未找到密鑰時提供默認值。第三個參數用於將返回值「轉換」爲所需類型,該類型還指定要返回的類型。根據這個例子,如果沒有找到'X-MyGuid',參數2 lambda基本上提供一個默認的guid作爲一個字符串(因爲它將從Header中獲取),而Guid.Parse第三個參數將轉換找到的或默認的字符串值到一個GUID。 – Mikee 2015-02-06 14:23:03

22

如果密鑰不存在,則在throws exception以下的行。

IEnumerable<string> headerValues = request.Headers.GetValues("MyCustomID"); 

解決方法:

包含System.Linq的;

IEnumerable<string> headerValues; 
var userId = string.Empty; 

    if (request.Headers.TryGetValues("MyCustomID", out headerValues)) 
    { 
     userId = headerValues.FirstOrDefault(); 
    }   
8

要在@ neontapir的解決方案進一步擴大,這裏是一個可以適用於HttpRequestMessage或HttpResponseMessage同樣的,不需要手工編碼的表達式或函數更通用的解決方案。

using System.Net.Http; 
using System.Collections.Generic; 
using System.Linq; 

public static class HttpResponseMessageExtensions 
{ 
    public static T GetFirstHeaderValueOrDefault<T>(
     this HttpResponseMessage response, 
     string headerKey) 
    { 
     var toReturn = default(T); 

     IEnumerable<string> headerValues; 

     if (response.Content.Headers.TryGetValues(headerKey, out headerValues)) 
     { 
      var valueString = headerValues.FirstOrDefault(); 
      if (valueString != null) 
      { 
       return (T)Convert.ChangeType(valueString, typeof(T)); 
      } 
     } 

     return toReturn; 
    } 
} 

使用範例:

var myValue = response.GetFirstHeaderValueOrDefault<int>("MyValue"); 
+0

看起來不錯,但'GetFirstHeaderValueOrDefault'有兩個參數,等等它在調用樣例用法'var myValue = response時抱怨缺少參數。GetFirstHeaderValueOrDefault (「MyValue」);'我錯過了什麼? – Jeb50 2017-04-15 05:20:42

+0

添加新的靜態類,替換爲請求響應。從API控制器調用,作爲'var myValue = myNameSpace.HttpRequestMessageExtension.GetFirstHeaderValueOrDefault (「productID」);'got **沒有給出的參數對應於'HttpRequestMessageExtension.GetFirstHeaderValueOrDefault (HttpRequestMessage,字符串)'** – Jeb50 2017-04-15 05:42:07

+0

@ Jeb50你是否在你試圖使用這個擴展名的文件中聲明'使用HttpResponseMessageExtensions'? – 2017-04-26 15:11:12

11

創建一個新的方法 - 「返回一個單獨的HTTP標頭值」,當你需要從HttpRequestMessage訪問多個關鍵值調用此方法與關鍵值,每次。

public static string GetHeader(this HttpRequestMessage request, string key) 
     { 
      IEnumerable<string> keys = null; 
      if (!request.Headers.TryGetValues(key, out keys)) 
       return null; 

      return keys.First(); 
     } 
2

對於ASP.Net核心有一個簡單的解決方案,如果希望直接在控制器方法使用PARAM:使用[FromHeader]註釋。

 public JsonResult SendAsync([FromHeader] string myParam) 
     { 
     if(myParam == null) //Param not set in request header 
     { 
      return null; 
     } 
     return doSomething(); 
    } 

附加信息:在我的情況下, 「myParam」 必須是一個字符串,整數總是0

1
request.Headers.FirstOrDefault(x => x.Key == "MyCustomID").Value?.FirstOrDefault() 

現代變種:)

0

對於ASP.NET,你可以得到在控制器方法中使用this simple library/package直接從參數中獲取頭文件。它提供了一個[FromHeader]屬性,就像你在ASP.NET核心:)一樣。例如:

... 
    using RazHeaderAttribute.Attributes; 

    [Route("api/{controller}")] 
    public class RandomController : ApiController 
    { 
     ... 
     // GET api/random 
     [HttpGet] 
     public IEnumerable<string> Get([FromHeader("pages")] int page, [FromHeader] string rows) 
     { 
      // Print in the debug window to be sure our bound stuff are passed :) 
      Debug.WriteLine($"Rows {rows}, Page {page}"); 
      ... 
     } 
    } 
相關問題