I have an web api on dotnet core 3.1 and I want to set different timeout specific controller action.I try to create an actionfilter something like below
public class TimeOutAttribute : ActionFilterAttribute
{
private readonly int _timeout;
public TimeOutAttribute(int timeout)
{
_timeout = timeout;
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
try
{
var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(_timeout));
await Task.Run(async () => await next(), cts.Token);
}
catch (TaskCanceledException)
{
var request = context.HttpContext.Request;
var message = $"Action exceeded the set timeout limit {_timeout} milisecond for {request.PathBase}{request.Path}";
throw new ActionTimeOutException(message);
}
}
}
and I use it on controller method
[TimeOut(100)]
public async Task<IActionResult> Get()
{
}
Although Get method takes more than 100 ms I can not get exception.Could you see any problem on code or If you have a another options for controller timeout Im ready to try it
Yes; passing a cancellation token to
Task.Runisn't going to work. The token for that method only cancels the scheduling of the task to the thread pool, not the delegate itself.The only way to cancel your delegate code is to have your delegate take a
CancellationTokenand observe that (usually by passing it to other methods). I have a blog post series on the subject of cancellation.So, that's a harder problem.
There is built-in support for
CancellationTokenin ASP.NET Core; you can add aCancellationTokenargument to any controller action method. However, this token doesn't have anything to do with timeouts; it cancels if the user request is aborted (e.g., the user closes their browser).One approach is to add a
CancellationTokenparameter to your action method and have your filter modify the model binding results, replacing the providedCancellationToken. Something like this should work:This will work - to an extent. Your host (i.e., IIS) likely has its own timeout, and this timeout is completely separate from that one.