ব্রাউজার যখন অনুরোধটি বাতিল করে দেয় তখন এএসপি.নেট ওয়েব এপিআই অপারেশনকেনসেল এক্সপশন


119

যখন কোনও ব্যবহারকারী কোনও পৃষ্ঠা লোড করেন, তখন এটি এক বা একাধিক অ্যাজাক্স অনুরোধ করে, যা এএসপি.নেট ওয়েব এপিআই 2 নিয়ন্ত্রণকারীগুলিকে আঘাত করে। যদি ব্যবহারকারী এই পৃষ্ঠায় অজাক্স অনুরোধগুলি সম্পূর্ণ করার আগে অন্য পৃষ্ঠায় নেভিগেট করে, তবে অনুরোধগুলি ব্রাউজার দ্বারা বাতিল করা হয়। আমাদের ELMAH HTTPModule এর পরে প্রতিটি বাতিল হওয়া অনুরোধের জন্য দুটি ত্রুটি লগ করে:

ত্রুটি 1:

System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__0.MoveNext()

ত্রুটি 2:

System.OperationCanceledException: The operation was canceled.
   at System.Threading.CancellationToken.ThrowIfCancellationRequested()
   at System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.WebHost.HttpControllerHandler.<CopyResponseAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.WebHost.HttpControllerHandler.<ProcessRequestAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.TaskAsyncHelper.EndTask(IAsyncResult ar)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

স্ট্যাকট্রেসটি দেখে, আমি দেখতে পাচ্ছি যে ব্যতিক্রমটি এখান থেকে ছুঁড়ে ফেলা হচ্ছে: https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Http.WebHost/HttpControllerHandler.cs# L413

আমার প্রশ্ন: আমি কীভাবে এই ব্যতিক্রমগুলি পরিচালনা এবং উপেক্ষা করতে পারি?

এটি ব্যবহারকারীর কোডের বাইরের বলে মনে হচ্ছে ...

মন্তব্য:

  • আমি এএসপি.নেট ওয়েব এপিআই 2 ব্যবহার করছি
  • ওয়েব API এন্ডপয়েন্টগুলি হ'ল অ্যাসিঙ্ক এবং অ-অ্যাসিঙ্ক পদ্ধতির মিশ্রণ।
  • আমি ত্রুটি লগিং যেখানেই যুক্ত করি না কেন, আমি ব্যবহারকারীর কোডে ব্যতিক্রমটি ধরতে অক্ষম

1
কাতানা গ্রন্থাগারগুলিরও বর্তমান সংস্করণ সহ আমরা একই ব্যতিক্রমগুলি (টাস্ক ক্যান্সেলড এক্সেপশন এবং অপারেশন ক্যান্সেলড এক্সসেপশন) দেখেছি।
ডেভিড

দু'টি ব্যতিক্রম ঘটলে আমি আরও কিছু বিশদ পেয়েছি এবং বুঝতে পেরেছি যে এই কাজের মাত্রা তাদের মধ্যে একটির বিরুদ্ধে কাজ করে। এখানে কিছু বিশদ রয়েছে: স্ট্যাকওভারফ্লো
ইলিয়া

উত্তর:


78

এটি এএসপি.নেট ওয়েব এপিআই 2-এ একটি বাগ এবং দুর্ভাগ্যক্রমে, আমি মনে করি না যে এমন কোনও কাজ আছে যা সর্বদা সফল হবে। এটি আমাদের পক্ষে ঠিক করার জন্য আমরা একটি বাগ ফাইল করেছি।

শেষ পর্যন্ত সমস্যাটি হ'ল আমরা এ ক্ষেত্রে একটি বাতিল টাস্কটি এএসপি.নেটকে ফিরিয়ে দিই এবং এএসপি.এনইটি একটি বাতিল টাস্কটিকে একটি হাতছাড়া ব্যতিক্রমের মতো আচরণ করে (এটি অ্যাপ্লিকেশন ইভেন্টের লগে সমস্যাটি লগ করে)।

ইতিমধ্যে আপনি নীচের কোডের মতো কিছু চেষ্টা করতে পারেন। এটি একটি শীর্ষ-স্তরের বার্তা হ্যান্ডলার যুক্ত করেছে যা বাতিলকরণ টোকেন আগুনের সময় সামগ্রীটি সরিয়ে দেয়। যদি প্রতিক্রিয়াটির কোনও বিষয়বস্তু না থাকে তবে বাগটি ট্রিগার করা উচিত নয়। এটি এখনও ঘটতে পারে এমন একটি ছোট্ট সম্ভাবনা রয়েছে, কারণ মেসেজ হ্যান্ডলার বাতিলকরণ টোকেনটি পরীক্ষা করার পরে ক্লায়েন্টটি সরাসরি সংযোগ বিচ্ছিন্ন করতে পারে তবে উচ্চ স্তরের ওয়েব এপিআই কোড একই পরীক্ষা করে নেওয়ার আগে। তবে আমি মনে করি এটি বেশিরভাগ ক্ষেত্রে সহায়তা করবে।

ডেভিড

config.MessageHandlers.Add(new CancelledTaskBugWorkaroundMessageHandler());

class CancelledTaskBugWorkaroundMessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

        // Try to suppress response content when the cancellation token has fired; ASP.NET will log to the Application event log if there's content in this case.
        if (cancellationToken.IsCancellationRequested)
        {
            return new HttpResponseMessage(HttpStatusCode.InternalServerError);
        }

        return response;
    }
}

2
আপডেট হিসাবে, এটি কয়েকটি অনুরোধ ক্যাপচার করে। আমরা এখনও আমাদের লগগুলিতে বেশ কয়েকটি দেখতে পাই। কাজের আশেপাশের জন্য ধন্যবাদ। একটি স্থির প্রত্যাশায়।
বেটস ওয়েস্টমোরল্যান্ড

2
@ কিরানচাল্লা - আমি নিশ্চিত করতে পারি যে 5.2.2 এ উন্নীত করার পরেও এই ত্রুটি রয়েছে।
নাইটফক্স

2
তবুও আমি ত্রুটি পাচ্ছি। আমি উপরের পরামর্শ, অন্য কোনও ক্লু ব্যবহার করেছি।
M2012

3
যখন আমি উপরের সুপারিশটি চেষ্টা করেছি, তখনও অনুরোধটি পাস হওয়ার আগেই বাতিল হয়ে গিয়েছিল তখনও আমি ব্যতিক্রম পেয়েছি SendAsync(আপনি আপনার এপিকে F5অনুরোধ করে এমন ইউআরএলে ব্রাউজারে চেপে ধরে এটি অনুকরণ করতে পারেন I আমিও এই সমস্যাটি সমাধান করেছি if (cancellationToken.IsCancellationRequested)কলটিতে উপরের চেকটি যুক্ত করুন SendAsyncthe ব্রাউজারটি দ্রুত আবেদন বাতিল করলে এখন ব্যতিক্রমগুলি আর দেখাবে না
seangwright

2
দু'টি ব্যতিক্রম ঘটলে আমি আরও কিছু বিশদ পেয়েছি এবং বুঝতে পেরেছি যে এই কাজের মাত্রা তাদের মধ্যে একটির বিরুদ্ধে কাজ করে। এখানে কিছু বিশদ রয়েছে: স্ট্যাকওভারফ্লো.com
ইলিয়া চেরনমর্ডিক

17

WebApi এর জন্য ব্যতিক্রম লগার প্রয়োগ করার সময়, এক্সপেশনফিল্টার System.Web.Http.ExceptionHandling.ExceptionLoggerতৈরি না করে শ্রেণিটি বাড়ানোর পরামর্শ দেওয়া হয় । WebApi ইন্টার্নালগুলি বাতিল অনুরোধগুলির জন্য এক্সসেপশনলগারগুলির লগ পদ্ধতিতে কল করবে না (তবে, ব্যতিক্রম ফিল্টারগুলি সেগুলি পাবে)। এটি নকশা দ্বারা।

HttpConfiguration.Services.Add(typeof(IExceptionLogger), myWebApiExceptionLogger); 

দেখে মনে হচ্ছে যে এই পদ্ধতির সাথে সমস্যাটি হ'ল গ্লোবাল.অ্যাসাক্স ত্রুটি পরিচালনার ক্ষেত্রে ত্রুটিটি এখনও পপ আপ হয়েছে ... ঘটনা যদিও এটি ব্যতিক্রম হ্যান্ডলারের কাছে প্রেরণ করা হয়নি
ইলিয়া চেরনমর্ডিক

14

এই ইস্যুটির জন্য এখানে অন্য একটি কৌশল রয়েছে। OWIN পাইপলাইনের শুরুতে কেবল একটি কাস্টম OWIN মিডলওয়্যার যুক্ত করুন যা এটি ধরা OperationCanceledException:

#if !DEBUG
app.Use(async (ctx, next) =>
{
    try
    {
        await next();
    }
    catch (OperationCanceledException)
    {
    }
});
#endif

2
আমি এই ত্রুটিটি মূলত ওউইএন প্রসঙ্গেই পেয়েছিলাম এবং এটির এটি আরও ভাল করে লক্ষ্য করে
নিতিনসিংহ

3

আপনি এর মাধ্যমে ডিফল্ট টিপিএল টাস্ক ব্যতিক্রম হ্যান্ডলিং আচরণটি পরিবর্তন করে দেখতে পারেন web.config:

<configuration> 
    <runtime> 
        <ThrowUnobservedTaskExceptions enabled="true"/> 
    </runtime> 
</configuration>

তারপরে আপনার ওয়েব অ্যাপ্লিকেশনে একটি staticক্লাস (একজন staticকনস্ট্রাক্টর সহ) রাখুন যা পরিচালনা করবে AppDomain.UnhandledException

তবে, এটি প্রদর্শিত হয় যে এই ব্যতিক্রমটি আসলে এএসপি.নেট ওয়েব এপিআই রানটাইমের অভ্যন্তরে কোথাও হ্যান্ডেল হয়ে আসছে, এমনকি আপনার নিজের কোডটি দিয়ে এটি পরিচালনা করার সুযোগ পাওয়ার আগে।

এই ক্ষেত্রে, আপনি একটি 1st সুযোগ ব্যতিক্রম যেমন ধরা সঙ্গে সক্ষম হওয়া উচিত AppDomain.CurrentDomain.FirstChanceException, কিভাবে এখানে । আমি বুঝতে পারি এটি আপনি যা খুঁজছেন তা নাও হতে পারে।


1
তাদের কেউই আমাকেও ব্যতিক্রম পরিচালনা করতে দেয়নি।
বেটস ওয়েস্টমোরল্যান্ড

@ বেটস ওয়েস্টমোরল্যান্ড, এমনকি না FirstChanceException? আপনি কি কোনও স্থির শ্রেণীর সাথে এটি পরিচালনা করার চেষ্টা করেছেন যা এইচটিটিপি অনুরোধ জুড়েই আছে?
নাসেরটিও

2
এই সমস্যাটি ধরার জন্য আমি এটি সমাধান করার চেষ্টা করছি এবং এই ব্যতিক্রমগুলি উপেক্ষা করছি। ব্যবহার AppDomain.UnhandledExceptionবা AppDomain.CurrentDomain.FirstChanceExceptionআমাকে ব্যতিক্রম পরিদর্শন করার অনুমতি দিতে পারে, কিন্তু ধরা এবং উপেক্ষা করা নয়। আমি এই ব্যতিক্রমগুলি হ'ল এই পদ্ধতির কোনওটিই ব্যবহার করে হ্যান্ডেল হিসাবে চিহ্নিত করার কোনও উপায় দেখিনি। আমি ভুল হলে আমাকে সংশোধন করুন।
বেটস ওয়েস্টমোরল্যান্ড

2

আমি কখনও কখনও আমার ওয়েব এপিআই 2 অ্যাপ্লিকেশনটিতে একই 2 ব্যতিক্রম পাই, তবে আমি জেনেরিক ব্যতিক্রম ফিল্টারটিApplication_Error পদ্ধতিতে Global.asax.csএবং ব্যবহার করে তাদের ধরতে পারি ।

মজার বিষয় হ'ল, যদিও আমি এই ব্যতিক্রমগুলি ধরতে পছন্দ করি না, কারণ আমি সবসময় যে সমস্ত অপ্রয়োজনীয় ব্যতিক্রমগুলি অ্যাপ্লিকেশনটি ক্র্যাশ করতে পারে লগইন করি (এই 2 টি অবশ্য আমার জন্য অপ্রাসঙ্গিক এবং দৃশ্যত না হয় বা কমপক্ষে ক্রাশ হওয়া উচিত নয়) এটি, তবে আমি ভুল হতে পারি)। আমার সন্দেহ হয়েছে যে কিছু সময়সীমা শেষ হওয়ার কারণে বা ক্লায়েন্টের সুস্পষ্ট বাতিল হওয়ার কারণে এই ত্রুটিগুলি প্রকাশিত হয়েছে তবে আমি আশা করতাম যে এএসপি.এনইটি কাঠামোর মধ্যে সেগুলি চিকিত্সা করা হবে এবং এর বাইরে অপরিবর্তিত ব্যতিক্রম হিসাবে প্রচার করা হবে না।


আমার ক্ষেত্রে, এই ব্যতিক্রমগুলি ঘটে কারণ ব্যবহারকারী একটি নতুন ইউআরএল নেভিগেট করার সাথে সাথে ব্রাউজারটি অনুরোধটি বাতিল করে।
বেটস ওয়েস্টমোরল্যান্ড

1
আমি দেখি. আমার ক্ষেত্রে, অনুরোধগুলি WinHTTPব্রাউজার থেকে নয়, এপিআইয়ের মাধ্যমে জারি করা হয় ।
গ্যাব্রিয়েল এস

2

আমি এই ত্রুটিটি সম্পর্কে আরও কিছু বিশদ পেয়েছি। সম্ভাব্য দুটি ব্যতিক্রম ঘটতে পারে:

  1. OperationCanceledException
  2. TaskCanceledException

কন্ট্রোলারে থাকা আপনার কোডটি কার্যকর করার সময় সংযোগটি বাদ দেওয়া হলে প্রথমটি ঘটে (বা সম্ভবত এটির কিছু সিস্টেম কোডও)। দ্বিতীয়টি ঘটে যখন এক্সিকিউটেশনটি কোনও অ্যাট্রিবিউটের মধ্যে থাকা অবস্থায় সংযোগটি বাদ দেওয়া হয় (উদাহরণস্বরূপ AuthorizeAttribute)।

সুতরাং প্রদত্ত ওয়ার্কআউন্ড আংশিকভাবে প্রথম ব্যতিক্রমকে প্রশমিত করতে সহায়তা করে, এটি দ্বিতীয়টির সাথে সাহায্য করার জন্য কিছুই করে না। পরবর্তী ক্ষেত্রে এটি কল করার TaskCanceledExceptionসময় ঘটে থাকে base.SendAsyncবরং বাতিলকরণ টোকেনকে সত্য হিসাবে সেট করা হয়।

এগুলি সমাধানের দুটি উপায় আমি দেখতে পাচ্ছি:

  1. গ্লোবাল.এক্স্যাক্সে কেবল উভয় ব্যতিক্রম উপেক্ষা করা। তাহলে প্রশ্নটি আসে যদি হঠাৎ পরিবর্তে গুরুত্বপূর্ণ কিছু উপেক্ষা করা সম্ভব হয়?
  2. হ্যান্ডলারে অতিরিক্ত চেষ্টা / ক্যাপচার করা (যদিও এটি বুলেটপ্রুফ নয়) এখনও সম্ভাবনা রয়েছে TaskCanceledExceptionযে আমরা লগ করতে চাইছি এমন একটি হবে।

config.MessageHandlers.Add(new CancelledTaskBugWorkaroundMessageHandler());

class CancelledTaskBugWorkaroundMessageHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        try
        {
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

            // Try to suppress response content when the cancellation token has fired; ASP.NET will log to the Application event log if there's content in this case.
            if (cancellationToken.IsCancellationRequested)
            {
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
        }
        catch (TaskCancellationException)
        {
            // Ignore
        }

        return response;
    }
}

আমি ভুল ব্যতিক্রমগুলি চিহ্নিত করার চেষ্টা করতে পারার একমাত্র উপায়টি স্ট্যাকট্রেসে কিছু অ্যাস্প.নেট স্টাফ রয়েছে কিনা তা যাচাই করে। যদিও খুব মজবুত মনে হয় না।

PS এইভাবে আমি এই ত্রুটিগুলি ফিল্টার করে ফেলেছি:

private static bool IsAspNetBugException(Exception exception)
{
    return
        (exception is TaskCanceledException || exception is OperationCanceledException) 
        &&
        exception.StackTrace.Contains("System.Web.HttpApplication.ExecuteStep");
}

1
আপনার প্রস্তাবিত কোডে, আপনি responseচেষ্টাটির ভিতরে ভেরিয়েবল তৈরি করে চেষ্টা করে বাইরে ফিরিয়ে দিন। এটা কি সম্ভব কাজ করতে পারে না? এছাড়াও আপনি ইস্প নেটব্যাগএক্সসেপশনটি কোথায় ব্যবহার করবেন?
স্কুফ

1
না, এটি কাজ করতে পারে না, এটি কেবল চেষ্টা / ক্যাপ ব্লকের বাইরে ঘোষণা করতে হবে এবং সমাপ্ত টাস্কের মতো কিছু দিয়ে শুরু করতে হবে। এটি সমাধানের কেবল উদাহরণ যা কোনওভাবেই বুলেটপ্রুফ নয়। অন্যান্য প্রশ্ন হিসাবে আপনি এটি গ্লোবাল.এক্স অ্যাক্স অনারার হ্যান্ডলারটিতে ব্যবহার করেন। আপনি যদি নিজের বার্তাগুলি লগ করতে সেটিকে ব্যবহার না করেন তবে আপনাকে আর চিন্তা করার দরকার নেই। যদি আপনি এটি করেন তবে এটি সিস্টেম থেকে কীভাবে "অ ত্রুটিগুলি" ছাঁটাবেন তার একটি উদাহরণ।
ইলিয়া চেরনমর্ডিক

1

আমরা একই ব্যতিক্রম পেয়েছি, আমরা @ ড্যাম্যাটসনের কার্যকারিতাটি ব্যবহার করার চেষ্টা করেছি, তবে আমরা এর পরেও কিছু ব্যতিক্রম পেতে চাই। আমরা সম্প্রতি পর্যন্ত এটি মোকাবেলা করেছি। আমরা লক্ষ্য করেছি যে কয়েকটি উইন্ডোজ লগ উদ্বেগজনক হারে বাড়ছে।

ত্রুটিযুক্ত ফাইলগুলি এতে অবস্থিত: সি: \ উইন্ডোজ \ সিস্টেম 32 \ লগফিলস \ HTTPERR

বেশিরভাগ ত্রুটিগুলি সমস্তই "টাইমার_সংযোগআইডল" এর জন্য ছিল। আমি আশেপাশে অনুসন্ধান করেছি এবং মনে হয়েছিল যে ওয়েব এপিআই কলটি শেষ হলেও, সংযোগটি এখনও মূল সংযোগের দুই মিনিট ধরে স্থায়ী ছিল।

আমি তখন অনুভব করেছি যে আমাদের প্রতিক্রিয়াতে সংযোগটি বন্ধ করার চেষ্টা করা উচিত এবং দেখুন কী ঘটে।

আমি response.Headers.ConnectionClose = true;সেন্ডঅ্যান্সেস মেসেজহ্যান্ডলারের সাথে যুক্ত করেছি এবং ক্লায়েন্টদের কী বলতে পারি তা থেকে সংযোগগুলি বন্ধ করে দেওয়া হচ্ছে এবং আমরা আর সমস্যাটি অনুভব করছি না।

আমি জানি এটি সর্বোত্তম সমাধান নয়, তবে এটি আমাদের ক্ষেত্রে কার্যকর। আমি আরও নিশ্চিত যে পারফরম্যান্স-ওয়াইজ হ'ল এটি এমন কিছু নয় যা যদি আপনার এপিআই একই ক্লায়েন্টের পিছনে থেকে একাধিক কল পেতে থাকে তবে আপনি যা করতে চাইবেন না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.