5

我有以下 API 控制器:

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 方法中出现 null 。(我基于代码获取器)。

在我看来,这应该可行,但我似乎无法做到。关于我做错了什么以及我应该如何获取发布的参数的任何想法?

编辑:我尝试使用以下内容直接读取帖子数据:

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)"}

编辑:最后,这似乎可能是ApiController,System.Web.Http.AuthorizeAttributeHttpPost(它在使用时确实有效HttpGet)组合的错误。已提交错误报告。

4

4 回答 4

7

AuthorizeAttribute应该有一个AuthorizationContext参数而不是一个HttpActionContext,您应该可以从中访问RouteData例如

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

更新

注意到您正在使用ApiController并因此使用Http.AuthorizeAttribute(解释为什么您没有AuthorizationContext)。在这种情况下,您可以RouteData通过操作上下文获取

var folderId = actionContext.Request.GetRouteData().Values["folderId"];
于 2012-08-31T13:44:30.773 回答
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、Boolean、String 等,并且可以根据您的要求进行自定义。

扩展方法 GetQueryNameValuePairs 是 System.Net.Http.HttpRequestMessageExtensions 类的一部分,将读取查询字符串/表单数据。

示例使用:

object folderId = GetValueFromActionContext(actionContext, "folderId");
于 2013-02-20T18:11:34.733 回答
1

如果请求的内容类型是application/json;charset=utf-8

API 操作可以检索 Post 数据,如下所示:

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);
于 2016-10-27T08:46:21.927 回答
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];
}

我同意 James 的回答,在这种情况下,您必须通过 actionContext 访问请求上下文。

于 2012-08-31T13:47:44.127 回答