从action属性返回“429 Too Many Requests”

时间:2015-04-09 23:49:18

标签: c# asp.net asp.net-web-api rate-limiting

我正在编写一个类,我可以将其用作ASP.NET Web API操作的属性,该操作将根据用户的IP地址对用户进行速率限制。

该类的逻辑工作正常,其基本结构如下:

public class ThrottleAttribute : ActionFilterAttribute
{

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        // Do various logic to determine if we should respond with a 429

        base.OnActionExecuting(actionContext);
    }
}

我通过在方法定义上方添加[Throttle]注释,在我的控制器操作上使用它。

OnActionExecuting方法的某处,我想返回一个带有429 HTTP代码的响应。从查看其他SO帖子(例如this one)看来,我可以通过以下方式做到这一点:

actionContext.Response = actionContext.Request.CreateResponse(
            HttpStatusCode.Conflict, 
            Message.Replace("{n}", Seconds.ToString())
        );

当我尝试使用此代码时,出现以下错误:

  

' System.Net.Http.HttpRequestMessage'不包含' CreateResponse'的定义没有扩展方法' CreateResponse'接受类型为#System; Net.Net.Http.HttpRequestMessage'的第一个参数。可以找到(你错过了使用指令或程序集引用吗?)

显然CreateResponse方法并不存在于HttpRequestMessage,但我不知道如何返回自定义回复来告诉用户他们已经点击了他们的速度限制。我也试过这个:

actionContext.Response.StatusCode = HttpStatusCode.BadRequest;

但是这也导致了一个错误,即没有将Object引用设置为对象的实例。

如何从我的课程中返回429 Too Many Requests个回复,或者失败,只有Bad Request回复?

2 个答案:

答案 0 :(得分:4)

你可以抛出一个HttpResponseException:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    if (TooManyRequests()) {
        throw new HttpResponseException((HttpStatusCode)429);
    }
    base.OnActionExecuting(filterContext);
}

您可以将429转换为HttpStatusCode,即使该值不是枚举的一部分(来自C# language specification 5.0)。

答案 1 :(得分:1)

尝试设置上下文的HttpContext.Response属性的Response以及Result属性的设置。通过设置结果,它将强制不再调用后续过滤器。

一个例子如下:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    filterContext.HttpContext.Response.StatusCode = 429; // Too many requests
    filterContext.Result = new ContentResult
    {
        Content = "Too Many Requests"
    };
    base.OnActionExecuting(filterContext);
}