Using HttpContext.Current in WebApi is dangerous because of async

前端 未结 3 488
感动是毒
感动是毒 2020-11-27 11:03

My question is a bit related to this: WebApi equivalent for HttpContext.Items with Dependency Injection.

We want to inject a class using HttpContext.Current in We

3条回答
  •  难免孤独
    2020-11-27 11:50

    I found very good article describing exactly this problem: http://byterot.blogspot.cz/2012/04/aspnet-web-api-series-part-3-async-deep.html?m=1

    author investigated deeply, how the ExecuteAsync method is called in the WebApi framework and came to this conclusion:

    ASP.NET Web API actions (and all the pipeline methods) will be called asynchronously only if you return a Task or Task. This might sound obvious but none of the pipeline methods with Async suffix will run in their own threads. Using blanket Async could be a misnomer. [UPDATE: ASP.NET team indeed have confirmed that the Async is used to denote methods that return Task and can run asynchronously but do not have to]

    What I understood from the article is, that the Action methods are called synchronously, but it is the caller decision.

    I created a small test app for this purpose, something like this:

    public class ValuesController : ApiController
    {
        public object Get(string clientId, string specialValue)
        {
            HttpRequest staticContext = HttpContext.Current.Request;
            string staticUrl = staticContext.Url.ToString();
    
            HttpRequestMessage dynamicContext = Request;
            string dynamicUrl = dynamicContext.RequestUri.ToString();
    
            return new {one = staticUrl, two = dynamicUrl};
        }
    }
    

    and one Async version returning async Task

    I tried to do a little DOS attack on it with jquery and could not determine any issue until I used await Task.Delay(1).ConfigureAwait(false);, which is obvious it would fail.

    What I took from the article is, that the problem is very complicated and Thread switch can happen when using async action method, so it is definetly NOT a good idea to use HttpContext.Current anywhere in the code called from the action methods. But as the controller is created synchronously, using HttpContext.Current in the constructor and as well in dependency injection is OK.

    When somebody has another explanation to this problem please correct me as this problem is very complicated an I am still not 100% convinced.

    diclaimer:

    • I ignore for now the problem of self-hosted Web-Api withoud IIS, where HttpContext.Current would not work probably anyway. We now rely on IIS.

    提交回复
    热议问题