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
方法内部。应该注意的是,这个方法是我实际覆盖的基类中唯一的方法,其余的只是继承。
答案 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);
}