2012-08-31 25 views
5

我有以下API控制器:MVC Api Action&System.Web.Http.AuthorizeAttribute - 如何獲取發佈參數?

public class TestController : ApiController 
{ 
    [HttpPost] 
    [APIAuthorizeAttribute] 
    public IQueryable<Computers> ListOfComputersInFolder(Guid folderId) 
    { 
     return GetListOfComputersForFolder(folderId); 
    } // End of ListOfComputersInFolder 
} // End of TestController 

而下面是我的基本APIAuthorizeAttribute

public class APIAuthorizeAttribute : System.Web.Http.AuthorizeAttribute 
{ 
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     var Request = System.Web.HttpContext.Current.Request; 
     var folderId = Request.RequestContext.RouteData.Values["folderId"] ?? Request.Params["folderId] as string; 
     if(null == folderId) 
     { 
      folderId = actionContext.ControllerContext.RouteData.Values["folderId"]; 
     } 

     base.OnAuthorization(actionContext); 
    } 
} 

說我有問題是,folderId是走出空在onAuthorize方法。 (我基於this代碼的獲取者)。

在我看來,這應該是工作,但我似乎無法得到它。任何想法,我做錯了什麼,我應該如何去獲得張貼的參數?

編輯:我試圖直接與下面的讀取後數據:

using (StreamReader inputStream = new StreamReader(request.InputStream)) 
{ 
    output = inputStream.ReadToEnd(); 
} 
request.InputStream.Position = 0; 

這讓我JSON格式的數據後,我可以再解析,但後來我的電話從來不使它雖然。我得到的響應以下異常:

<h2>500 - Internal server error.</h2> 
    <h3>There is a problem with the resource you are looking for, and it cannot be displayed. 

at System.Json.JXmlToJsonValueConverter.JXMLToJsonValue(Stream jsonStream, Byte[] jsonBytes)\u000d\u000a at System.Net.Http.Formatting.JsonMediaTypeFormatter.<>c__DisplayClass7.<OnReadFromStreamAsync>b__6()\u000d\u000a at System.Net.Http.Internal.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)"} 

編輯: 最後,好像這也可能會被使用的ApiControllerSystem.Web.Http.AuthorizeAttributeHttpPost組合中的錯誤(它使用HttpGet時不工作)。一個錯誤報告已經提交。

回答

7

AuthorizeAttribute應該有一個AuthorizationContext參數,而不是一個HttpActionContext一個,從你應該能夠訪問RouteData例如您正在使用ApiController和使用Http.AuthorizeAttribute這樣

public override void OnAuthorization(AuthorizationContext filterContext) 
{ 
    var folderId = filterContext.RouteData.Values["folderId"]; 
    ... 
} 

更新

注意的(解釋了爲什麼沒有一個AuthorizationContext做)。在這種情況下,您可以通過操作環境獲得RouteData,例如

var folderId = actionContext.Request.GetRouteData().Values["folderId"]; 
+3

注意,因爲這是一個[APIController] (http://msdn.microsoft.com/en-us/library/system.web.http.apicontroller(v=vs.108).aspx)而不是[Controller](http://msdn.microsoft.com /en-us/library/system.web.mvc.controller(v=vs.108 ).aspx),我使用'System.Web.Http.AuthorizeAttribute'而不是'System.Web.Mvc.AuthorizeAttribute'。我試着訪問它的'ControllerContext.RouteData.Values [「folderId」],它仍然返回null。 – Kyle

+0

@Zenox看到我更新的答案。 – James

+0

謝謝我也看過這個,但仍然沒有運氣。 'actionContext.Request'類是[HttpRequestMessage](http://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage_methods),不包含'GetRouteData'方法。另外,如果我看:actionContext.ControllerContext.RouteData.Values它只包含兩個鍵:控制器和操作。我認爲我最好的選擇是從inputStream中讀取發佈數據。我試了一下,並確認我可以看到我的發佈數據,但看起來有點冒失,所以我現在要繼續尋找。 – Kyle

0

你可以給這個擴展方法一試:(這是工作的代碼摘錄)

public static string GetParameter(this RequestContext requestContext, string key) 
{ 
    if (key == null) throw new ArgumentNullException("key"); 

    var lowKey = key.ToLower(); 

    return requestContext.RouteData.Values.ContainsKey(lowKey) && 
      requestContext.RouteData.Values[lowKey] != null 
       ? requestContext.RouteData.Values[lowKey].ToString() 
       : requestContext.HttpContext.Request.Params[lowKey]; 
} 

我與詹姆斯的答案達成一致,必須通過ActionContext的訪問請求上下文這種情況。

1

我也遇到過這個問題。

要解決它,我寫了下面的方法,這是我從OnAuthorization方法中調用:

private static object GetValueFromActionContext(HttpActionContext actionContext, string key) 
{ 
    var queryNameValuePairs = actionContext.Request.GetQueryNameValuePairs(); 

    var value = queryNameValuePairs 
     .Where(pair => pair.Key.Equals(key, StringComparison.OrdinalIgnoreCase)) 
     .Select(pair => pair.Value) 
     .FirstOrDefault(); 

    var methodInfo = ((ReflectedHttpActionDescriptor) (actionContext.ActionDescriptor)).MethodInfo; 
    var parameters = methodInfo.GetParameters(); 
    var parameterType = 
     parameters.Single(p => p.Name.Equals(key, StringComparison.OrdinalIgnoreCase)).ParameterType; 

    var converter = TypeDescriptor.GetConverter(parameterType); 

    return converter.ConvertFromString(value); 
} 

此代碼作以下假設:

  • 關鍵你提取匹配的參數名稱在操作方法上。

  • 您正在獲取的參數類型將具有適用於該類型的轉換器。

  • 您未在參數上使用任何自定義綁定或格式。

在此場景中,我使用的代碼,我只希望簡單類型如的Guid,布爾型,字符串等,並可以定製按您的要求。

擴展方法GetQueryNameValuePairs是System.Net.Http.HttpRequestMessageExtensions類的一部分,它將讀取查詢字符串/表單數據。

使用例:

object folderId = GetValueFromActionContext(actionContext, "folderId"); 
0

如果請求的contentType中是application/json;charset=utf-8

的API動作可以檢索後的數據如下:

Stream stream = actionContext.Request.Content.ReadAsStreamAsync().Result; 
Encoding encoding = Encoding.UTF8; 
stream.Position = 0; 
string responseData = ""; 

using (StreamReader reader = new StreamReader(stream, encoding)) 
{ 
    responseData = reader.ReadToEnd().ToString(); 
} 

var dic = JsonConvert.DeserializeObject<IDictionary<string, string>>(responseData); 
相關問題