এএসপি.নেট কোর ওয়েব এপিআই ব্যতিক্রম হ্যান্ডলিং


280

আমি বহু বছর ধরে নিয়মিত এএসপি.নেট ওয়েব এপিআই ব্যবহার করার পরে আমার নতুন আরএসটি এপিআই প্রকল্পের জন্য এএসপি.নেট কোর ব্যবহার করছি। আমি এএসপি.নেট কোর ওয়েব এপিআই-তে ব্যতিক্রমগুলি পরিচালনা করার কোনও ভাল উপায় দেখছি না। আমি ব্যতিক্রম হ্যান্ডলিং ফিল্টার / বৈশিষ্ট্য প্রয়োগ করার চেষ্টা করেছি:

public class ErrorHandlingFilter : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        HandleExceptionAsync(context);
        context.ExceptionHandled = true;
    }

    private static void HandleExceptionAsync(ExceptionContext context)
    {
        var exception = context.Exception;

        if (exception is MyNotFoundException)
            SetExceptionResult(context, exception, HttpStatusCode.NotFound);
        else if (exception is MyUnauthorizedException)
            SetExceptionResult(context, exception, HttpStatusCode.Unauthorized);
        else if (exception is MyException)
            SetExceptionResult(context, exception, HttpStatusCode.BadRequest);
        else
            SetExceptionResult(context, exception, HttpStatusCode.InternalServerError);
    }

    private static void SetExceptionResult(
        ExceptionContext context, 
        Exception exception, 
        HttpStatusCode code)
    {
        context.Result = new JsonResult(new ApiResponse(exception))
        {
            StatusCode = (int)code
        };
    }
}

এবং এখানে আমার স্টার্টআপ ফিল্টার নিবন্ধকরণ:

services.AddMvc(options =>
{
    options.Filters.Add(new AuthorizationFilter());
    options.Filters.Add(new ErrorHandlingFilter());
});

আমার যে সমস্যাটি ছিল তা হ'ল ব্যতিক্রম যখন ঘটে তখন আমার AuthorizationFilterদ্বারা পরিচালিত হয় না ErrorHandlingFilter। আমি পুরানো এএসপি.নেট ওয়েব এপিআইয়ের সাথে কাজ করার মতোই এটিও সেখানে ধরা পড়বে বলে আশা করছিলাম।

তাহলে আমি কীভাবে সমস্ত অ্যাপ্লিকেশন ব্যতিক্রমের পাশাপাশি অ্যাকশন ফিল্টারগুলি থেকে কোনও ব্যতিক্রম ধরতে পারি?


3
আপনি UseExceptionHandlerমিডলওয়্যার চেষ্টা করেছেন ?
পাভেল

মিডলওয়্যার কীভাবে ব্যবহার করবেন সে সম্পর্কে আমার এখানে একটি উদাহরণ রয়েছেUseExceptionHandler
ইলিয়া চেরনমর্ডিক

উত্তর:


538

মিডলওয়্যার হ্যান্ডলিং ব্যতিক্রম

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

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate next;
    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        var code = HttpStatusCode.InternalServerError; // 500 if unexpected

        if      (ex is MyNotFoundException)     code = HttpStatusCode.NotFound;
        else if (ex is MyUnauthorizedException) code = HttpStatusCode.Unauthorized;
        else if (ex is MyException)             code = HttpStatusCode.BadRequest;

        var result = JsonConvert.SerializeObject(new { error = ex.Message });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;
        return context.Response.WriteAsync(result);
    }
}

এটা নিবন্ধন MVC সামনেStartupশ্রেণী:

app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseMvc();

আপনি স্ট্যাক ট্রেস, ব্যতিক্রমের নাম, ত্রুটি কোডগুলি বা আপনি এটি করতে চান এমন কিছু যুক্ত করতে পারেন। খুব নমনীয়। এখানে ব্যতিক্রম প্রতিক্রিয়া একটি উদাহরণ:

{ "error": "Authentication token is not valid." }

ইনজেকশনের বিবেচনা IOptions<MvcJsonOptions>করতে Invokeপদ্ধতি তারপর এটি ব্যবহার করতে যখন আপনি প্রতিক্রিয়া বস্তু ধারাবাহিকভাবে মধ্যে ASP.NET MVC এর ধারাবাহিকতাতে সেটিংস ব্যবহার করতে JsonConvert.SerializeObject(errorObj, opts.Value.SerializerSettings)সব এন্ড পয়েন্ট জুড়ে আরও ভালো ধারাবাহিকতাতে দৃঢ়তা জন্য।

পদ্ধতির ঘ

আর একটি অপ-সুস্পষ্ট এপিআই বলা হয়েছে UseExceptionHandlerযা সাধারণ দৃশ্যের জন্য "ঠিক আছে" কাজ করে:

app.UseExceptionHandler(a => a.Run(async context =>
{
    var feature = context.Features.Get<IExceptionHandlerPathFeature>();
    var exception = feature.Error;

    var result = JsonConvert.SerializeObject(new { error = exception.Message });
    context.Response.ContentType = "application/json";
    await context.Response.WriteAsync(result);
}));

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


4
আমি আজ কাজ করার জন্য একটি কাস্টম মিডলওয়্যার পাওয়ার চেষ্টা করে ডেস্কের বিরুদ্ধে আমার মাথাটি মারছি এবং এটি মূলত একইভাবে কাজ করে (আমি এটি অনুরোধের জন্য কাজের / লেনদেনের ইউনিট পরিচালনা করতে ব্যবহার করছি)। আমি যে সমস্যার মুখোমুখি হচ্ছি তা হ'ল 'পরবর্তী' এর উত্থাপিত ব্যতিক্রমগুলি মিডওয়্যারের মধ্যে ধরা পড়েনি। আপনি যেমন কল্পনা করতে পারেন, এটি সমস্যাযুক্ত। আমি কী ভুল / নিখোঁজ করছি? কোন পয়েন্টার বা পরামর্শ?
brappleye3

5
@ brappleye3 - সমস্যাটি কী তা আমি বুঝতে পেরেছি। আমি কেবল স্টার্টআপ। সি ক্লাসে মিডলওয়্যারটি ভুল জায়গায় নিবন্ধন করছিলাম। আমি app.UseMiddleware<ErrorHandlingMiddleware>();ঠিক আগে চলে এসেছি app.UseStaticFiles();। ব্যতিক্রমটি এখন সঠিকভাবে ধরা পড়েছে বলে মনে হচ্ছে। এটি আমাকে বিশ্বাস করতে পরিচালিত app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink();করে মিডলওয়্যারটিকে সঠিকভাবে অর্ডার করার জন্য কিছু অভ্যন্তরীণ যাদু মিডলওয়্যার হ্যাকারি করুন।
জামদান

4
আমি সম্মতি দিচ্ছি যে কাস্টম মিডলওয়্যারগুলি খুব কার্যকর হতে পারে তবে নটফাউন্ড, অননুমোদিত এবং BadRequest পরিস্থিতিতে ব্যতিক্রম ব্যবহার করে প্রশ্ন করবে। কেন কেবল স্ট্যাটাস কোডটি সেট করবেন না (নটফাউন্ড () ইত্যাদি ব্যবহার করে) এবং তারপরে এটি আপনার কাস্টম মিডলওয়্যার বা ইউজস্ট্যাটাসকোডপেজস উইথআরএক্সেকিউটের মাধ্যমে পরিচালনা করবেন? আরও তথ্যের জন্য devtrends.co.uk/blog/handling-erferences-in-asp.net-core-web-api দেখুন
পল

4
এটি খারাপ কারণ এটি সর্বদা জেএসএন-তে সিরিয়ালাইজ করা হয়, সামগ্রীতে সামগ্রীর আলোচনার বিষয়টি উপেক্ষা করে।
কনরাড

5
@ কনরাডের বৈধ পয়েন্ট। এ কারণেই আমি বলেছিলাম যে এই উদাহরণটিই আপনি যেখানে শুরু করতে পারেন, শেষ ফলাফল নয়। 99% APIs এর জন্য JSON পর্যাপ্ত চেয়ে বেশি। যদি আপনি এই উত্তরটি যথেষ্ট ভাল না বলে মনে করেন তবে অবদান রাখতে নির্দ্বিধায়।
আন্দ্রেই

60

সর্বশেষ Asp.Net Core(কমপক্ষে 2.2 থেকে সম্ভবত সম্ভবত) এর একটি অন্তর্নির্মিত মিডওয়্যার রয়েছে যা গৃহীত উত্তরের প্রয়োগের তুলনায় এটি কিছুটা সহজ করে তোলে:

app.UseExceptionHandler(a => a.Run(async context =>
{
    var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
    var exception = exceptionHandlerPathFeature.Error;

    var result = JsonConvert.SerializeObject(new { error = exception.Message });
    context.Response.ContentType = "application/json";
    await context.Response.WriteAsync(result);
}));

এটি লেখার জন্য কিছুটা কম কোড করা উচিত।

গুরুত্বপূর্ণ: অর্ডার গুরুত্বপূর্ণ হিসাবে এটি আগে UseMvc(বা UseRoutingইন নেট কোর 3) যুক্ত করার কথা মনে রাখবেন ।


এটি ডিআইডিটিকে হ্যান্ডলারের একটি আর্গ হিসাবে সমর্থন করে, বা হ্যান্ডলারের মধ্যে একজনকে কোনও পরিষেবা লোকেটার প্যাটার্নটি ব্যবহার করতে হবে?
এলপি

32

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

আপনার নির্দিষ্ট উদাহরণস্বরূপ, যদি আপনি এক্সটেনশান এক ব্যবহার করতে পারেন StatusCodePage মিডলওয়্যার বা মত আপনার নিজের রোল এই

লগিং ব্যতিক্রমগুলির জন্য আপনি এখানে একটি উদাহরণ খুঁজে পেতে পারেন: এক্সেপশনহ্যান্ডলারমিতলওয়্যার। সি

public void Configure(IApplicationBuilder app)
{
    // app.UseErrorPage(ErrorPageOptions.ShowAll);
    // app.UseStatusCodePages();
    // app.UseStatusCodePages(context => context.HttpContext.Response.SendAsync("Handler, status code: " + context.HttpContext.Response.StatusCode, "text/plain"));
    // app.UseStatusCodePages("text/plain", "Response, status code: {0}");
    // app.UseStatusCodePagesWithRedirects("~/errors/{0}");
    // app.UseStatusCodePagesWithRedirects("/base/errors/{0}");
    // app.UseStatusCodePages(builder => builder.UseWelcomePage());
    app.UseStatusCodePagesWithReExecute("/Errors/{0}");  // I use this version

    // Exception handling logging below
    app.UseExceptionHandler();
}

যদি আপনি এই নির্দিষ্ট প্রয়োগটি পছন্দ না করেন তবে আপনি ইএলএম মিডলওয়্যারও ব্যবহার করতে পারেন এবং এখানে কয়েকটি উদাহরণ রয়েছে: এলম ব্যতিক্রম মিডলওয়্যার

public void Configure(IApplicationBuilder app)
{
    app.UseStatusCodePagesWithReExecute("/Errors/{0}");
    // Exception handling logging below
    app.UseElmCapture();
    app.UseElmPage();
}

যদি এটি আপনার প্রয়োজনের জন্য কাজ করে না, আপনি নিজের তৈরির জন্য ধারণাগুলি উপলব্ধি করতে এক্সপেশনহ্যান্ডলারমিতলওয়ার এবং এলমমিটলওয়ারের প্রয়োগগুলি দেখে সর্বদা আপনার নিজের মিডলওয়্যার উপাদানটি রোল করতে পারেন।

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


আপনাকে স্বাগতম. প্রান্তের ক্ষেত্রে ডিফল্ট ইউজস্ট্যাটাস পৃষ্ঠাগুলি ওভাররাইড করার জন্য আমি একটি উদাহরণের একটি লিঙ্কও সরবরাহ করেছি যা আপনার অনুরোধটি আরও ভালভাবে পূরণ করতে পারে।
অ্যাশলে লি

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

2
লিঙ্কটি এখন ভেঙে গেছে।
ম্যাথিয়াস লাইক্কেগার্ড লরেনজেন

@ অ্যাশলেলি, আমি প্রশ্ন করি UseStatusCodePagesযা ওয়েব এপিআই পরিষেবা প্রয়োগের ক্ষেত্রে কার্যকর use কোনও দর্শন বা এইচটিএমএল কোনও দর্শন নেই, কেবল জেএসএন প্রতিক্রিয়া ...
পল মিশালিক

23

উত্তমরূপে গৃহীত উত্তর আমাকে অনেক সাহায্য করেছে তবে রানটাইম সময়ে ত্রুটি স্থিতির কোড পরিচালনা করতে আমি আমার মিডলওয়্যারটিতে এইচটিপিস্ট্যাটাসকোডটি পাস করতে চেয়েছিলাম।

এই লিঙ্কটি অনুসারে আমি একই কাজ করার জন্য কিছু ধারণা পেয়েছি। সুতরাং আমি এর সাথে Andrei উত্তরটি একত্রিত করেছি। সুতরাং আমার চূড়ান্ত কোড নীচে:
1. বেস ক্লাস

public class ErrorDetails
{
    public int StatusCode { get; set; }
    public string Message { get; set; }

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

2. কাস্টম ব্যতিক্রম শ্রেণির ধরণ

 public class HttpStatusCodeException : Exception
{
    public HttpStatusCode StatusCode { get; set; }
    public string ContentType { get; set; } = @"text/plain";

    public HttpStatusCodeException(HttpStatusCode statusCode)
    {
        this.StatusCode = statusCode;
    }

    public HttpStatusCodeException(HttpStatusCode statusCode, string message) : base(message)
    {
        this.StatusCode = statusCode;
    }

    public HttpStatusCodeException(HttpStatusCode statusCode, Exception inner) : this(statusCode, inner.ToString()) { }

    public HttpStatusCodeException(HttpStatusCode statusCode, JObject errorObject) : this(statusCode, errorObject.ToString())
    {
        this.ContentType = @"application/json";
    }

}


3. কাস্টম ব্যতিক্রম মিডলওয়্যার

public class CustomExceptionMiddleware
    {
        private readonly RequestDelegate next;

    public CustomExceptionMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
            await next(context);
        }
        catch (HttpStatusCodeException ex)
        {
            await HandleExceptionAsync(context, ex);
        }
        catch (Exception exceptionObj)
        {
            await HandleExceptionAsync(context, exceptionObj);
        }
    }

    private Task HandleExceptionAsync(HttpContext context, HttpStatusCodeException exception)
    {
        string result = null;
        context.Response.ContentType = "application/json";
        if (exception is HttpStatusCodeException)
        {
            result = new ErrorDetails() { Message = exception.Message, StatusCode = (int)exception.StatusCode }.ToString();
            context.Response.StatusCode = (int)exception.StatusCode;
        }
        else
        {
            result = new ErrorDetails() { Message = "Runtime Error", StatusCode = (int)HttpStatusCode.BadRequest }.ToString();
            context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        }
        return context.Response.WriteAsync(result);
    }

    private Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        string result = new ErrorDetails() { Message = exception.Message, StatusCode = (int)HttpStatusCode.InternalServerError }.ToString();
        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        return context.Response.WriteAsync(result);
    }
}


৪. সম্প্রসারণ পদ্ধতি

public static void ConfigureCustomExceptionMiddleware(this IApplicationBuilder app)
    {
        app.UseMiddleware<CustomExceptionMiddleware>();
    }

5. স্টার্টআপ.সিগুলিতে পদ্ধতিটি কনফিগার করুন

app.ConfigureCustomExceptionMiddleware();
app.UseMvc();

অ্যাকাউন্ট কন্ট্রোলারে এখন আমার লগইন পদ্ধতি:

 try
        {
            IRepository<UserMaster> obj = new Repository<UserMaster>(_objHeaderCapture, Constants.Tables.UserMaster);
            var Result = obj.Get().AsQueryable().Where(sb => sb.EmailId.ToLower() == objData.UserName.ToLower() && sb.Password == objData.Password.ToEncrypt() && sb.Status == (int)StatusType.Active).FirstOrDefault();
            if (Result != null)//User Found
                return Result;
            else// Not Found
                throw new HttpStatusCodeException(HttpStatusCode.NotFound, "Please check username or password");
        }
        catch (Exception ex)
        {
            throw ex;
        }

সর্বোপরি যদি আমি খুঁজে পেলাম না ব্যবহারকারী তারপর HttpStatusCodeException যা আমি অতিক্রান্ত HttpStatusCode.NotFound অবস্থা এবং একটি কাস্টম বার্তা উত্থাপন আপনি দেখতে পারেন
মিডলওয়্যার ইন

ধরা (HttpStatusCodeException প্রাক্তন)

অবরুদ্ধকে বলা হবে যা নিয়ন্ত্রণটি পাস করবে

প্রাইভেট টাস্ক হ্যান্ডেলএক্সেপশনএেন্সেকশন




তবে যদি আমি আগে রানটাইম ত্রুটি পেয়েছি? তার জন্য আমি ট্র্যাচ ক্যাচ ব্লক ব্যবহার করেছি যা ব্যতিক্রম ছুঁড়ে ফেলেছে এবং ক্যাচে ধরা হবে (ব্যতিক্রম ব্যতিক্রম) ব্লক এবং নিয়ন্ত্রণটি পাস করবে

টাস্ক হ্যান্ডেলএক্সেপশনএসেনসিঙ্ক (এইচটিটিপি কনটেক্সট প্রসঙ্গ, ব্যতিক্রম ব্যতিক্রম)

পদ্ধতি।

আমি অভিন্নতার জন্য একক ত্রুটিপত্রের ক্লাস ব্যবহার করেছি।


এক্সটেনশন পদ্ধতি কোথায় রাখবেন? দুর্ভাগ্যবশত মধ্যে startup.csমধ্যে void Configure(IapplicationBuilder app)আমি কোনো ত্রুটির সম্মুখীন হয়েছেন IApplicationBuilder does not contain a definition for ConfigureCustomExceptionMiddleware। এবং আমি রেফারেন্স যোগ, যেখানে CustomExceptionMiddleware.cs
স্পিডো দে লা রসায়

ব্যতিক্রমগুলি তারা আপনার এপিসটি ধীর করে দেওয়ার কারণে আপনি ব্যবহার করতে চান না। ব্যতিক্রমগুলি খুব ব্যয়বহুল।
lnaie

@ আইনা, এটি সম্পর্কে বলতে পারব না ... তবে মনে হচ্ছে আপনি সামলাতে কখনও কোনও ব্যতিক্রম পেলেন না .. দুর্দান্ত কাজ
অর্জুন

19

ব্যতিক্রম প্রতি ব্যতিক্রম হ্যান্ডলিং আচরণ কনফিগার করতে আপনি নিউগেট প্যাকেজগুলি থেকে মিডলওয়্যার ব্যবহার করতে পারেন:

কোড নমুনা:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddExceptionHandlingPolicies(options =>
    {
        options.For<InitializationException>().Rethrow();

        options.For<SomeTransientException>().Retry(ro => ro.MaxRetryCount = 2).NextPolicy();

        options.For<SomeBadRequestException>()
        .Response(e => 400)
            .Headers((h, e) => h["X-MyCustomHeader"] = e.Message)
            .WithBody((req,sw, exception) =>
                {
                    byte[] array = Encoding.UTF8.GetBytes(exception.ToString());
                    return sw.WriteAsync(array, 0, array.Length);
                })
        .NextPolicy();

        // Ensure that all exception types are handled by adding handler for generic exception at the end.
        options.For<Exception>()
        .Log(lo =>
            {
                lo.EventIdFactory = (c, e) => new EventId(123, "UnhandlerException");
                lo.Category = (context, exception) => "MyCategory";
            })
        .Response(null, ResponseAlreadyStartedBehaviour.GoToNextHandler)
            .ClearCacheHeaders()
            .WithObjectResult((r, e) => new { msg = e.Message, path = r.Path })
        .Handled();
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseExceptionHandlingPolicies();
    app.UseMvc();
}

16

প্রথমত, আন্দ্রেইকে ধন্যবাদ যেহেতু আমি তার সমাধানটির ভিত্তিতে আমার সমাধানটি ভিত্তি করে রেখেছি।

এটি আমার সম্পূর্ণ নমুনা হিসাবে অন্তর্ভুক্ত করছি এবং পাঠকদের কিছুটা সময় সাশ্রয় হতে পারে।

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

আমার পদ্ধতির জন্য একটি অবজেক্টস রিসাল্ট ব্যবহার করা যা আমাদের এমভিসিতে বেকড কার্যকারিতাটি ব্যবহার করতে দেয়।

এই কোডটি প্রতিক্রিয়া ক্যাচিং প্রতিরোধ করে।

ত্রুটির প্রতিক্রিয়াটি এমনভাবে সজ্জিত করা হয়েছে যাতে এটি এক্সএমএল সিরিয়ালাইজার দ্বারা সিরিয়ালাইজ করা যায়।

public class ExceptionHandlerMiddleware
{
    private readonly RequestDelegate next;
    private readonly IActionResultExecutor<ObjectResult> executor;
    private readonly ILogger logger;
    private static readonly ActionDescriptor EmptyActionDescriptor = new ActionDescriptor();

    public ExceptionHandlerMiddleware(RequestDelegate next, IActionResultExecutor<ObjectResult> executor, ILoggerFactory loggerFactory)
    {
        this.next = next;
        this.executor = executor;
        logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, $"An unhandled exception has occurred while executing the request. Url: {context.Request.GetDisplayUrl()}. Request Data: " + GetRequestData(context));

            if (context.Response.HasStarted)
            {
                throw;
            }

            var routeData = context.GetRouteData() ?? new RouteData();

            ClearCacheHeaders(context.Response);

            var actionContext = new ActionContext(context, routeData, EmptyActionDescriptor);

            var result = new ObjectResult(new ErrorResponse("Error processing request. Server error."))
            {
                StatusCode = (int) HttpStatusCode.InternalServerError,
            };

            await executor.ExecuteAsync(actionContext, result);
        }
    }

    private static string GetRequestData(HttpContext context)
    {
        var sb = new StringBuilder();

        if (context.Request.HasFormContentType && context.Request.Form.Any())
        {
            sb.Append("Form variables:");
            foreach (var x in context.Request.Form)
            {
                sb.AppendFormat("Key={0}, Value={1}<br/>", x.Key, x.Value);
            }
        }

        sb.AppendLine("Method: " + context.Request.Method);

        return sb.ToString();
    }

    private static void ClearCacheHeaders(HttpResponse response)
    {
        response.Headers[HeaderNames.CacheControl] = "no-cache";
        response.Headers[HeaderNames.Pragma] = "no-cache";
        response.Headers[HeaderNames.Expires] = "-1";
        response.Headers.Remove(HeaderNames.ETag);
    }

    [DataContract(Name= "ErrorResponse")]
    public class ErrorResponse
    {
        [DataMember(Name = "Message")]
        public string Message { get; set; }

        public ErrorResponse(string message)
        {
            Message = message;
        }
    }
}

9

প্রথমত, Startupওয়েব সার্ভার থেকে কোনও ত্রুটি এবং কোনও অপ্রয়োজনীয় ব্যতিক্রমগুলির জন্য ত্রুটি পৃষ্ঠায় পুনরায় সম্পাদন করতে এএসপি.নেট কোর 2 কনফিগার করুন ।

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment()) {
        // Debug config here...
    } else {
        app.UseStatusCodePagesWithReExecute("/Error");
        app.UseExceptionHandler("/Error");
    }
    // More config...
}

এরপরে, একটি ব্যতিক্রম প্রকারটি সংজ্ঞায়িত করুন যা আপনাকে HTTP স্থিতি কোডগুলির সাথে ত্রুটি ছুঁড়ে দেয়।

public class HttpException : Exception
{
    public HttpException(HttpStatusCode statusCode) { StatusCode = statusCode; }
    public HttpStatusCode StatusCode { get; private set; }
}

অবশেষে, ত্রুটি পৃষ্ঠার জন্য আপনার নিয়ামকটিতে, ত্রুটির কারণের ভিত্তিতে প্রতিক্রিয়াটি কাস্টমাইজ করুন এবং কোনও প্রতিক্রিয়া শেষ ব্যবহারকারী দ্বারা সরাসরি প্রদর্শিত হবে কিনা। এই কোডটি সমস্ত এপিআই ইউআরএল দিয়ে শুরু করে /api/

[AllowAnonymous]
public IActionResult Error()
{
    // Gets the status code from the exception or web server.
    var statusCode = HttpContext.Features.Get<IExceptionHandlerFeature>()?.Error is HttpException httpEx ?
        httpEx.StatusCode : (HttpStatusCode)Response.StatusCode;

    // For API errors, responds with just the status code (no page).
    if (HttpContext.Features.Get<IHttpRequestFeature>().RawTarget.StartsWith("/api/", StringComparison.Ordinal))
        return StatusCode((int)statusCode);

    // Creates a view model for a user-friendly error page.
    string text = null;
    switch (statusCode) {
        case HttpStatusCode.NotFound: text = "Page not found."; break;
        // Add more as desired.
    }
    return View("Error", new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier, ErrorText = text });
}

এএসপি.এনইটি কোর আপনার সাথে ত্রুটি বিশদটি ডিবাগ করার জন্য লগ করবে, সুতরাং একটি স্ট্যাটাস কোড আপনি (সম্ভাব্য অবিশ্বস্ত) একজন আবেদনকারীকে সরবরাহ করতে চান এমন সমস্ত কিছু হতে পারে। আপনি যদি আরও তথ্য দেখাতে চান তবে আপনি এটি সরবরাহ করতে উন্নত করতে পারেন HttpException। এপিআই ত্রুটির জন্য আপনি প্রতিস্থাপন বার্তার মূল অংশে তাদেরকে JSON এনকোডেড ত্রুটি তথ্য লাগাতে পারেন return StatusCode...সঙ্গে return Json...


0

মিডলওয়্যার বা IExceptionHandlerPathFeature ব্যবহার করুন ঠিক আছে। সেখানে আরেকটি উপায় eShop

একটি ব্যতিক্রমী ফিল্টার তৈরি করুন এবং এটি নিবন্ধ করুন

public class HttpGlobalExceptionFilter : IExceptionFilter
{
  public void OnException(ExceptionContext context)
  {...}
}
services.AddMvc(options =>
{
  options.Filters.Add(typeof(HttpGlobalExceptionFilter));
})
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.