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.AuthorizeAttributeとの組み合わせのバグである可能性があるようですHttpPost( を使用すると機能しHttpGetます)。バグレポートが提出されました。

4

4 に答える 4

7

AuthorizeAttributeには、 AuthorizationContextパラメーターではなく、 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 に答える
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 に答える