1

注意:应该注意的是,在回答了这个问题之后,这个特定的问题似乎与 OData 非常相关,而不是一般的 C#。

我有一个奇怪的问题。我从AuthorizeAttribute类派生了一个ApiAuthorize属性。除了标准登录过程之外,此属性还会执行一些额外的类似 ACL 的检查。

当我将此属性应用于整个类时,它在所有方法上都像预期的那样工作。但是,当我将它单独应用于方法时,它不适用于所有方法。

以下是一段代码,使用 OData 和 Web Api:

public class UsersController : EntitySetController<User, int>
{
    [ApiAuthorize]
    public override IQueryable<User> Get()
    {
        DoSomething();
    }

    [ApiAuthorize]
    protected override User GetEntityByKey(int key)
    {
        DoSomethingElse();
    }
}

当我使用 调用该Get方法时,该类/odata/UsersOnAuthorization方法ApiAuthorize被正确调用。当我使用该属性调用该GetEntityByKey方法时,该属性会被完全忽略,程序会立即在该方法内跳转。但是,正如我之前所说,当我从方法中删除属性并将其作为一个整体应用到类时,确实调用了该属性。/odata/Users(1284)ApiAuthorizeGetEntityByKeyApiAuthorize

就其本身而言,这当然很奇怪,但更是如此,因为在我转换到 OData 之前(因此使用 anApiController而不是当前使用的EntitySetController),无论以何种方式应用,该属性始终有效。所以这似乎是EntitySetController中断。

会不会是 OData 以某种方式破坏了这个实现?

更新

为了回答 Josh E 的问题:

派生属性非常大,所以我猜测它的简化版本不会对问题产生影响,因为它是微不足道的,但它看起来像这样:

public class ApiAuthorize : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        HttpRequestHeaders headers = actionContext.Request.Headers;
        NameValueCollection getParams = HttpUtility.ParseQueryString(actionContext.Request.RequestUri.Query);

        DoALotOfThings();
    }
}

这只是派生属性的一个非常片段,但代码至少应该到达OnAuthorization方法内部。需要注意的是,这个方法是我实际覆盖的基类中唯一的方法,其余的只是继承。

4

1 回答 1

1

您当前注意到的行为GetEntityByKey是预期的。您将需要覆盖该方法Get([FromODataUri] TKey key)并将属性应用到它,在这种情况下您会看到您所期望的行为。

以下是来自的源代码EntitySetController。如果您注意到,GetEntityByKey 是从 Get([FromODataUri] TKey key) 操作中调用的:

    /// <summary>
    /// Handles GET requests that attempt to retrieve an individual entity by key from the entity set.
    /// </summary>
    /// <param name="key">The entity key of the entity to retrieve.</param>
    /// <returns>The response message to send back to the client.</returns>
    public virtual HttpResponseMessage Get([FromODataUri] TKey key)
    {
        TEntity entity = GetEntityByKey(key);
        return EntitySetControllerHelpers.GetByKeyResponse(Request, entity);
    }
于 2013-07-15T15:11:06.090 回答