2012-03-18 9 views
11

क्या एएसपी.नेट वेब एपीआई बीटा में पता लगाने का कोई तरीका है कि HTTP अनुरोध रद्द कर दिया गया था (किसी अन्य कारण से उपयोगकर्ता द्वारा निरस्त किया गया था)? मैं एक प्रकार का रद्दीकरण टोकन आउट ऑफ़ द बॉक्स रखने का मौका ढूंढ रहा हूं जो संकेत देगा कि अनुरोध निरस्त कर दिया गया है और इसलिए लंबे समय से चलने वाले ओप को भी निरस्त किया जाना चाहिए।एएसपी.नेट वेब एपीआई + लॉन्ग रनिंग ऑपरेशन रद्दीकरण

संभावित संबंधित प्रश्न - रद्द करने के लिए उपयोग केस टोकनमोडेल बाइंडर वर्ग। रद्दीकरण टोकन के लिए अलग बांधने का कारण क्या है?

उत्तर

7

आप समय-समय पर Response.IsClientConnected देख सकते हैं कि ब्राउज़र अभी भी सर्वर से कनेक्ट है या नहीं।

+0

इस के लिए

HttpContext.Current.Response.IsClientConnected HttpContext.Response.ClientDisconnectedToken 

का उल्लेख कर सकते, ASP.NET MVC ढेर से हो रहा है ASP.NET से नहीं एमवीसी वेब एपीआई। गलत होने पर मुझे सही करें। –

+2

यह कोर एएसपी.Net इंजन से है। केवल आईआईएस एकीकरण पाइपलाइन के साथ काम करता है (वीएस डीबग मोड नहीं)। एमएसडीएन में एक अच्छा प्रलेखन शामिल है: http://msdn.microsoft.com/en-us/library/system.web.httpresponse.isclientconnected.aspx –

+0

सुझाव के लिए धन्यवाद। यह एकमात्र विकल्प प्रतीत होता है, मैं शायद इस पर आधार बनाने का समाधान तैयार करूंगा। –

8

मैं थोड़ा सा जोड़ना चाहता हूं। काम करने लगते एकमात्र दृष्टिकोण Response.IsClientConnected की जांच कर रहा है। यहाँ कुछ तकनीकी क्या मंच के पीछे जा रहा है के बारे में विवरण: here और here यह दृष्टिकोण कुछ खामियां हैं: केवल आईआईएस (कोई आत्म होस्टिंग, कोई देव सर्वर) के तहत

  • काम करता है,
  • कुछ SO उत्तरों के अनुसार धीमा हो सकता है (क्लाइंट डिस्कनेक्ट होने के तुरंत बाद प्रतिक्रिया न करें): here; here

अंत में मैं CancellationToken सुई कोड का निम्न भाग वेब एपीआई नियंत्रक में IsClientConnected के आधार पर के साथ आया था:

public class ConnectionAbortTokenAttribute : System.Web.Http.Filters.ActionFilterAttribute 
{ 
    private readonly string _paramName; 
    private Timer _timer; 
    private CancellationTokenSource _tokenSource; 
    private CancellationToken _token; 

    public ConnectionAbortTokenAttribute(string paramName) 
    { 
     _paramName = paramName; 
    } 

    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 
    { 
     object value; 
     if (!actionContext.ActionArguments.TryGetValue(_paramName, out value)) 
     { 
      // no args with defined name found 
      base.OnActionExecuting(actionContext); 
      return; 
     } 

     var context = HttpContext.Current; 
     if (context == null) 
     { 
      // consider the self-hosting case (?) 
      base.OnActionExecuting(actionContext); 
      return; 
     } 

     _tokenSource = new CancellationTokenSource(); 
     _token = _tokenSource.Token; 
     // inject 
     actionContext.ActionArguments[_paramName] = _token; 
     // stop timer on client disconnect 
     _token.Register(() => _timer.Dispose()); 

     _timer = new Timer 
     (
      state => 
      { 
       if (!context.Response.IsClientConnected) 
       { 
        _tokenSource.Cancel(); 
       } 
      }, null, 0, 1000 // check each second. Opts: make configurable; increase/decrease. 
     ); 

     base.OnActionExecuting(actionContext); 
    } 

    /* 
    * Is this guaranteed to be called? 
    * 
    * 
    */ 
    public override void OnActionExecuted(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext) 
    { 
     if(_timer != null) 
      _timer.Dispose(); 

     if(_tokenSource != null) 
      _tokenSource.Dispose(); 

     base.OnActionExecuted(actionExecutedContext); 
    } 
} 
+0

सिग्नलआर और इसी तरह के समाधानों का उपयोग करने का एक विकल्प भी है, लेकिन वे मेरे लिए गुंजाइश से थोड़ी दूर हैं। –

0

तो

  • इस कॉल लागत के बारे में विचार कर रहे हैं आपने नियंत्रक विधियों में रद्दीकरण टोकन जोड़ा है, इसे स्वचालित रूप से ढांचे द्वारा इंजेक्शन दिया जाएगा, और जब कोई ग्राहक xhr.abort() को कॉल करता है तो टोकन स्वचालित रूप से रद्द हो जाएगा

    कुछ

    public Task<string> Get(CancellationToken cancellationToken = default(CancellationToken)) 
    

    के समान MVC के लिए आप भी .NetCore

    services.AddTransient<ICustomInterface>(provider => { 
        var accessor = provider.GetService<IHttpContextAccessor>); 
        accessor.HttpContext.RequestAborted; 
        }); 
    
  • संबंधित मुद्दे