আমি কীভাবে একটি সি # এমভিসি 4 ওয়েবএপিআই অ্যাপ্লিকেশনটির জন্য সমস্ত ব্যতিক্রম লগ করব?


175

পটভূমি

আমি একটি ক্লায়েন্টের জন্য একটি এপিআই পরিষেবা স্তর বিকাশ করছি এবং বিশ্বব্যাপী সমস্ত ত্রুটিগুলি ধরা এবং লগ করার জন্য আমাকে অনুরোধ করা হয়েছে।

সুতরাং, যখন কোনও অজানা এন্ডপয়েন্ট (বা ক্রিয়া) এর মতো কিছু সহজেই ELMAH ব্যবহার করে বা এর মতো কিছু যুক্ত করে সহজেই পরিচালনা করা হয় Global.asax:

protected void Application_Error()
{
     Exception unhandledException = Server.GetLastError();
     //do more stuff
}

। । .হানডেলড ত্রুটিগুলি যা রাউটিংয়ের সাথে সম্পর্কিত নয় লগ হয় না। উদাহরণ স্বরূপ:

public class ReportController : ApiController
{
    public int test()
    {
        var foo = Convert.ToInt32("a");//Will throw error but isn't logged!!
        return foo;
    }
}

আমি [HandleError]এই ফিল্টারটি নিবন্ধ করে বিশ্বব্যাপী বৈশিষ্ট্যটি সেট করার চেষ্টা করেছি :

filters.Add(new HandleErrorAttribute());

তবে এটি সমস্ত ত্রুটি লগ করে না।

সমস্যা / প্রশ্ন

/testউপরের দিকে কল করে উত্পন্ন যেমনটির মতো ত্রুটিগুলি কীভাবে আমি বাধা দেব যাতে আমি সেগুলি লগইন করতে পারি? দেখে মনে হচ্ছে এই উত্তরটি সুস্পষ্ট হওয়া উচিত, তবে আমি এতক্ষণ যা ভাবতে পারি তার সব চেষ্টা করেছি।

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

মীমাংসা!

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

এখানে কি কাজ করেছে:

1) আপনার নেমস্পেসে একটি কাস্টম ফিল্টার যুক্ত করুন:

public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext context)
    {
        if (context.Exception is BusinessException)
        {
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                Content = new StringContent(context.Exception.Message),
                ReasonPhrase = "Exception"
            });

        }

        //Log Critical errors
        Debug.WriteLine(context.Exception);

        throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
        {
            Content = new StringContent("An error occurred, please try again or contact the administrator."),
            ReasonPhrase = "Critical Exception"
        });
    }
}

2) এখন ফিল্টারটি বিশ্বজুড়ে WebApiConfig শ্রেণিতে নিবন্ধ করুন :

public static class WebApiConfig
{
     public static void Register(HttpConfiguration config)
     {
         config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });
         config.Filters.Add(new ExceptionHandlingAttribute());
     }
}

অথবা আপনি নিবন্ধকরণ এড়িয়ে যেতে পারেন এবং কেবলমাত্র [ExceptionHandling]বৈশিষ্ট্য সহ একটি একক নিয়ামককে সজ্জিত করতে পারেন ।


আমি একই সমস্যা আছে। ব্যতিক্রমহীন ব্যতিক্রমগুলি ব্যতিক্রম ফিল্টার অ্যাট্রিবিউট জরিমানায় ধরা পড়ে তবে আমি যখন নতুন ব্যতিক্রম ছুঁড়ে ফেলি তখন এটি ব্যতিক্রম ফিল্টার বৈশিষ্ট্যে ধরা পড়ে না, সে সম্পর্কে কোনও ধারণা?
daveBM

1
মাইহোস্ট / এপিআই / অপরিজ্ঞাতপিকন্ট্রোলার ত্রুটির মতো অজানা এপিআই কন্ট্রোলার কলগুলি এখনও ধরা পড়ে না। অ্যাপ্লিকেশন_রোয়ার এবং ব্যতিক্রম ফিল্টার কোড কার্যকর করা হয় না। কিভাবে তাদের ধরবেন?
অ্যান্ড্রুস

1
ওয়েবএপিআই v2.1 এ বিশ্বব্যাপী ত্রুটি হ্যান্ডলিং যুক্ত করা হয়েছিল। : এখানে আমার প্রতিক্রিয়া দেখতে stackoverflow.com/questions/17449400/...
DarrellNorton

1
এটি কিছু পরিস্থিতিতে ত্রুটিগুলি ধরবে না, যেমন "রিসোর্স পাওয়া যায় নি", বা একটি নিয়ামক নির্মাণকারীতে ত্রুটিগুলি। এখানে উল্লেখ
জর্ডান মরিস

হাই ম্যাট. আপনি প্রশ্নের অংশ হিসাবে উত্তরটি লিখেছেন তবে এটি এসও-তে সেরা অনুশীলন নয়। এখানে উত্তরগুলি প্রশ্ন থেকে পৃথক হওয়া উচিত। আপনি কি দয়া করে আলাদা উত্তর হিসাবে লিখতে পারেন (নীচে "আপনার নিজের প্রশ্নের উত্তর দিন" নীল বোতামটি ব্যবহার করতে পারেন)
সাশোম

উত্তর:


56

যদি আপনার ওয়েব এপিআই কোনও এএসপি.এনইটি অ্যাপ্লিকেশনটির অভ্যন্তরে হোস্ট করা থাকে, তবে Application_Errorইভেন্টটি আপনার কোডটিতে থাকা সমস্ত ব্যতিক্রমহীন ব্যতিক্রমগুলির জন্য ডাকা হবে, আপনি দেখানো পরীক্ষার ক্রিয়াকলাপটি সহ। সুতরাং আপনাকে যা করতে হবে তা হ'ল অ্যাপ্লিকেশন_রর ইভেন্টের মধ্যে এই ব্যতিক্রমটি পরিচালনা করতে হবে। নমুনা কোডটিতে আপনি দেখিয়েছেন যে আপনি কেবলমাত্র টাইপের ব্যতিক্রম পরিচালনা করছেন HttpExceptionযা অবশ্যই Convert.ToInt32("a")কোডের ক্ষেত্রে নয় । সুতরাং নিশ্চিত হয়ে নিন যে আপনি লগ এবং সেখানে সমস্ত ব্যতিক্রম পরিচালনা করেছেন:

protected void Application_Error()
{
    Exception unhandledException = Server.GetLastError();
    HttpException httpException = unhandledException as HttpException;
    if (httpException == null)
    {
        Exception innerException = unhandledException.InnerException;
        httpException = innerException as HttpException;
    }

    if (httpException != null)
    {
        int httpCode = httpException.GetHttpCode();
        switch (httpCode)
        {
            case (int)HttpStatusCode.Unauthorized:
                Response.Redirect("/Http/Error401");
                break;

            // TODO: don't forget that here you have many other status codes to test 
            // and handle in addition to 401.
        }
        else
        {
            // It was not an HttpException. This will be executed for your test action.
            // Here you should log and handle this case. Use the unhandledException instance here
        }
    }
}

ওয়েব এপিআইয়ে ব্যতিক্রম হ্যান্ডলিং বিভিন্ন স্তরে করা যেতে পারে। detailed articleবিভিন্ন সম্ভাবনা ব্যাখ্যা করার জন্য এখানে :

  • কাস্টম ব্যতিক্রম ফিল্টার বৈশিষ্ট্য যা বিশ্বব্যাপী ব্যতিক্রম ফিল্টার হিসাবে নিবন্ধিত হতে পারে

    [AttributeUsage(AttributeTargets.All)]
    public class ExceptionHandlingAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception is BusinessException)
            {
                throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
                {
                    Content = new StringContent(context.Exception.Message),
                    ReasonPhrase = "Exception"
                });
            }
    
            //Log Critical errors
            Debug.WriteLine(context.Exception);
    
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError)
            {
                Content = new StringContent("An error occurred, please try again or contact the administrator."),
                ReasonPhrase = "Critical Exception"
            });
        }
    }
    
  • কাস্টম ক্রিয়া চালক

    public class MyApiControllerActionInvoker : ApiControllerActionInvoker
    {
        public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
        {
            var result = base.InvokeActionAsync(actionContext, cancellationToken);
    
            if (result.Exception != null && result.Exception.GetBaseException() != null)
            {
                var baseException = result.Exception.GetBaseException();
    
                if (baseException is BusinessException)
                {
                    return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content = new StringContent(baseException.Message),
                        ReasonPhrase = "Error"
    
                    });
                }
                else
                {
                    //Log critical error
                    Debug.WriteLine(baseException);
    
                    return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)
                    {
                        Content = new StringContent(baseException.Message),
                        ReasonPhrase = "Critical Error"
                    });
                }
            }
    
            return result;
        }
    }
    

আমি আশা করি এটি সাধারণ ছিল তবে ত্রুটিটি এখনও ধরা পড়েনি। বিভ্রান্তি এড়াতে আমি প্রশ্ন আপডেট করেছি। ধন্যবাদ।
ম্যাট ক্যাস্যাট

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

আবার ধন্যবাদ, তবে যাই হোক না কেন, /testউদাহরণটি আঘাত হানে না। আমি প্রথম লাইনে একটি ব্রেকপয়েন্ট রেখেছি ( Exception unhandledException = . . .) তবে দৃশ্যে সেই ব্রেকপয়েন্টটিকে আঘাত করতে পারি না /test। যদি আমি কোনও বোগাস ইউআরএল রাখি তবে ব্রেকপয়েন্টটি হিট হয়।
ম্যাট ক্যাস্যাট

1
@ ম্যাথেজপ্যাট্রিকক্যাসট, আপনি পুরোপুরি ঠিক বলেছেন। Application_Errorঘটনা ওয়েব এপিআই ব্যতিক্রম পরিচালনা করতে, কারণ এটি সব ক্ষেত্রে আলোড়ন সৃষ্টি করা হইনি সঠিক স্থান নয়। আমি এটি অর্জনের বিভিন্ন সম্ভাবনার ব্যাখ্যা করে একটি খুব বিস্তারিত নিবন্ধ পেয়েছি: ওয়েবলগস.এএসপিএন
দারিন দিমিত্রোভ

1
@ ডারিন দিমিত্রভ অজানা এপিআই কন্ট্রোলার কলগুলি মাইহোস্ট / এপি / অনির্ধারিত ত্রুটির মতো কলগুলি এখনও ধরা যায় না। অ্যাপ্লিকেশন_রোয়ার এবং ব্যতিক্রম ফিল্টার কোড কার্যকর করা হয় না। কিভাবে তাদের ধরবেন?
অ্যান্ড্রুস

79

পূর্বের উত্তরের সংযোজন হিসাবে।

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

সংক্ষেপে, আপনি গ্লোবাল ব্যতিক্রম লগার এবং / বা বৈশ্বিক ব্যতিক্রম হ্যান্ডলার যুক্ত করুন (কেবল একটি)।
আপনি এগুলি কনফিগারেশনে যুক্ত করুন:

public static void Register(HttpConfiguration config)
{
  config.MapHttpAttributeRoutes();

  // There can be multiple exception loggers.
  // (By default, no exception loggers are registered.)
  config.Services.Add(typeof(IExceptionLogger), new ElmahExceptionLogger());

  // There must be exactly one exception handler.
  // (There is a default one that may be replaced.)
  config.Services.Replace(typeof(IExceptionHandler), new GenericTextExceptionHandler());
}

এবং তাদের উপলব্ধি:

public class ElmahExceptionLogger : ExceptionLogger
{
  public override void Log(ExceptionLoggerContext context)
  {
    ...
  }
}

public class GenericTextExceptionHandler : ExceptionHandler
{
  public override void Handle(ExceptionHandlerContext context)
  {
    context.Result = new InternalServerErrorTextPlainResult(
      "An unhandled exception occurred; check the log for more information.",
      Encoding.UTF8,
      context.Request);
  }
}

2
এটি পুরোপুরি কাজ করে। আমি একযোগে লগ এবং হ্যান্ডেল করি (কারণ আমি লগআইডিটি পাই এবং এটি আবার পাস করি যাতে ব্যবহারকারী মন্তব্যটি যুক্ত করতে পারে), তাই আমি একটি নতুন রেসপন্সমেসেজের রেজাল্টে ফলাফল সেট করছি। ধন্যবাদ এটি কিছুক্ষণের জন্য আমাকে বগল করছে।
ব্রেট

8

কেন পুনর্বিবেচনা ইত্যাদি? এটি কাজ করে এবং এটি পরিষেবাটি রিটার্নের স্ট্যাটাস 500 ইত্যাদি করে দেবে

public class LogExceptionFilter : ExceptionFilterAttribute
{
    private static readonly ILog log = LogManager.GetLogger(typeof (LogExceptionFilter));

    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        log.Error("Unhandeled Exception", actionExecutedContext.Exception);
        base.OnException(actionExecutedContext);
    }
}

2

আপনি কি হ্যান্ডেল ত্রুটি অ্যাকশন ফিল্টার এর মতো কিছু করার কথা ভেবেছেন?

[HandleError]
public class BaseController : Controller {...}

আপনি একটি কাস্টম সংস্করণও তৈরি করতে পারেন যার সাহায্যে [HandleError]আপনি ত্রুটি সম্পর্কিত তথ্য এবং অন্যান্য সমস্ত বিবরণ লগ করতে পারেন


ধন্যবাদ, তবে আমার কাছে এটি ইতিমধ্যে বিশ্বব্যাপী সেট আছে। এটি উপরের মতো একই সমস্যা পোজ দেয়, সমস্ত ত্রুটি লগ হয় না।
ম্যাট ক্যাস্যাট

1

একটি চেষ্টা / সম্পূর্ণরূপে পুরো জিনিসটি মোড়ানো এবং অবিচ্ছিন্ন ব্যতিক্রম লগইন করুন, তারপরে এটি পাস করুন। যদি না এটির জন্য আরও ভাল অন্তর্নির্মিত উপায় থাকে।

এখানে একটি রেফারেন্স ক্যাচ অল (হ্যান্ডেলড বা পরিচালনা না করা) ব্যতিক্রম

(সম্পাদনা করুন: ওহ এপিআই)


সেক্ষেত্রে তাকেও ব্যতিক্রমটি পুনর্বিবেচনা করতে হবে।
DigCamara

@ ডিজকামারা দুঃখিত, আমি এটি পাস করার মাধ্যমেই বোঝাতে চাইছি। নিক্ষেপ; যে হ্যান্ডেল করা উচিত। আমি প্রথমে বলেছিলাম "প্রস্থান করুন বা পুনরায় লোড করবেন কিনা তা স্থির করুন", তখন বুঝতে পারলেন যে তিনি বলেছিলেন এটি একটি এপিআই। সেক্ষেত্রে অ্যাপ্লিকেশনটিকে পাস দিয়ে কী করতে চায় তা স্থির করে দেওয়া সবচেয়ে ভাল।
টিম

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