授权EntitySetController的GetEntityByKey属性未被调用

时间:2013-07-15 13:37:59

标签: c# asp.net-web-api odata

NB:应该注意的是,在回答了这个问题之后,这个具体问题似乎与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/Users方法时,OnAuthorization类的ApiAuthorize方法已正确调用。当我使用GetEntityByKey调用/odata/Users(1284)方法时,ApiAuthorize属性被完全忽略,程序立即在方法内跳转。但是,正如我之前所说,当我从方法中删除属性并将其应用于整个类时,GetEntityByKey确实会调用ApiAuthorize属性。

这本身就是奇怪的,但更重要的是因为在我转换到OData之前(因此使用ApiController而不是当前使用的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方法内部。应该注意的是,这个方法是我实际覆盖的基类中唯一的方法,其余的只是继承。

1 个答案:

答案 0 :(得分:1)

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

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

    /// <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);
    }