我在各种控制器上使用AuthorizeAttribute,这些控制器可能需要根据请求本身的某些属性返回403或429(请求太多)。我完全在一个自定义的OnAuthorization实现中实现它,然后在必要时抛出一个带有相应响应代码的新HttpResponseException。在我的机器上工作得很好......
在规模上(每分钟有数千个请求),这个实现很糟糕,它崩溃了网站。将相同的逻辑移动到控制器操作本身并且只返回一个适当的HttpResponseMessage就perf而言非常好用,因此在OnAuthorization中抛出异常的费用似乎是perf问题的根本原因。
我喜欢在一个属性中实现它的想法,我可以用来装饰多个控制器和动作,我强烈地不喜欢将少量逻辑移动到控制器动作中,然后重复多次。是否可以从注释返回适当的HTTP状态而不抛出异常?即使它不是从AuthorizeAttribute继承,以这种方式装饰代码也是可取的。
编辑:这是Web API 2,而不是MVC
答案 0 :(得分:17)
正如您所发现的,抛出异常是昂贵的。这种情况下的技巧是覆盖属性中的响应。由于MVC和WebAPI不同(至少在MVC6之前),因此有两种不同的方法。
设置AuthorizationContext.Result
可以有效地覆盖正在执行的操作。设置此值将阻止其附加的操作完全运行:
public override void OnAuthorization(AuthorizationContext filterContext)
{
if(Throw403)
{
filterContext.Result = new HttpStatusCodeResult(403);
}
}
非常相似但您必须设置HttpActionContext.Response
属性。一个方便的功能是,您可以获得HTTP状态代码的良好enum
:
public override void OnAuthorization(HttpActionContext actionContext)
{
if(Throw403)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
}
}
答案 1 :(得分:1)
自定义消息处理程序如何在命中控制器之前回复?这种情况发生在管道的早期。
修改 - 粘贴网站上的相关信息
委托处理程序也可以跳过内部处理程序并直接创建响应:
public class MessageHandler2 :DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// Create the response.
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("Hello!")
};
// Note: TaskCompletionSource creates a task that does not contain a delegate.
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response); // Also sets the task state to "RanToCompletion"
return tsc.Task;
}
}
这就是你注册处理程序的方式
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MessageHandlers.Add(new MessageHandler1());
config.MessageHandlers.Add(new MessageHandler2());
// Other code not shown...
}
}
参考此处:http://www.asp.net/web-api/overview/advanced/http-message-handlers
抱歉格式错误,这是我通过移动设备做的最好的