2012-08-31 61 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); 
相关问题