এএসপি.নেট এমভিসি কাস্টম ত্রুটি হ্যান্ডলিং অ্যাপ্লিকেশন_এরর গ্লোবাল.অ্যাসাক্স?


108

আমার এমভিসি অ্যাপ্লিকেশনটিতে ত্রুটিগুলি নির্ধারণ করার জন্য আমার কাছে কিছু বেসিক কোড রয়েছে। বর্তমানে আমার প্রকল্প আমি একটি নিয়ামক নামের Errorকর্ম পদ্ধতি HTTPError404(), HTTPError500()এবং General()। তারা সকলেই একটি স্ট্রিং প্যারামিটার গ্রহণ করে error। নীচের কোডটি ব্যবহার বা সংশোধন করা। প্রক্রিয়াজাতকরণের জন্য ত্রুটি নিয়ন্ত্রণকারীকে ডেটা পাস করার সর্বোত্তম / সঠিক উপায় কী? আমি যতটা সম্ভব দৃust় সমাধান পেতে চাই।

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Response.Clear();

    HttpException httpException = exception as HttpException;
    if (httpException != null)
    {
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        switch (httpException.GetHttpCode())
        {
            case 404:
                // page not found
                routeData.Values.Add("action", "HttpError404");
                break;
            case 500:
                // server error
                routeData.Values.Add("action", "HttpError500");
                break;
            default:
                routeData.Values.Add("action", "General");
                break;
        }
        routeData.Values.Add("error", exception);
        // clear error on server
        Server.ClearError();

        // at this point how to properly pass route data to error controller?
    }
}

উত্তর:


104

এর জন্য একটি নতুন রুট তৈরি করার পরিবর্তে, আপনি কেবল আপনার নিয়ামক / ক্রিয়ায় পুনর্নির্দেশ করতে এবং ক্যোরিস্ট্রিংয়ের মাধ্যমে তথ্যটি পাস করতে পারেন। এই ক্ষেত্রে:

protected void Application_Error(object sender, EventArgs e) {
  Exception exception = Server.GetLastError();
  Response.Clear();

  HttpException httpException = exception as HttpException;

  if (httpException != null) {
    string action;

    switch (httpException.GetHttpCode()) {
      case 404:
        // page not found
        action = "HttpError404";
        break;
      case 500:
        // server error
        action = "HttpError500";
        break;
      default:
        action = "General";
        break;
      }

      // clear error on server
      Server.ClearError();

      Response.Redirect(String.Format("~/Error/{0}/?message={1}", action, exception.Message));
    }

তারপরে আপনার নিয়ামক আপনি যা চান তা পাবেন:

// GET: /Error/HttpError404
public ActionResult HttpError404(string message) {
   return View("SomeView", message);
}

আপনার পদ্ধতির সাথে কিছু ট্রেড অফ রয়েছে। এই জাতীয় ত্রুটি পরিচালনার লুপিংয়ের সাথে খুব সতর্কতা অবলম্বন করুন। অন্য জিনিসটি হ'ল যেহেতু আপনি 404 হ্যান্ডেল করার জন্য এসপ নেট পাইপলাইনটি অতিক্রম করছেন, আপনি সেই সমস্ত হিটগুলির জন্য একটি সেশন অবজেক্ট তৈরি করবেন। এটি ভারী ব্যবহৃত সিস্টেমগুলির জন্য একটি সমস্যা (পারফরম্যান্স) হতে পারে।


আপনি যখন "লুপিং সম্পর্কে সতর্ক হন" বলছেন তখন আপনার সঠিক অর্থ কী? এই ধরণের ত্রুটি পুনর্নির্দেশের জন্য এটির আরও ভাল উপায় আছে (এটিকে ধরে নেওয়া একটি ভারী ব্যবহৃত সিস্টেম হ'ল)?
অ্যারিক

4
লুপিং দ্বারা আমি বোঝাতে চাইছি যখন আপনার ত্রুটি পৃষ্ঠায় কোনও ত্রুটি রয়েছে, তখন আপনাকে বারবার আপনার ত্রুটি পৃষ্ঠায় পুনঃনির্দেশিত করা হবে ... (উদাহরণস্বরূপ, আপনি নিজের ত্রুটিটি একটি ডাটাবেসে লগ করতে চান এবং এটি ডাউন))
andrecarlucci

125
ত্রুটিগুলিতে পুনঃনির্দেশ করা ওয়েবে আর্কিটেকচারের বিপরীতে যায়। ইউআরআই একই থাকতে হবে যখন সার্ভার সঠিক HTTP স্থিতি কোডটি প্রতিক্রিয়া জানায় যাতে ক্লায়েন্ট ব্যর্থতার সঠিক প্রসঙ্গটি জানে। হ্যান্ডলিরর অ্যাট্রিবিউট.অনেক্সেপশন বা কন্ট্রোলারঅনএক্সেপশন বাস্তবায়ন একটি আরও ভাল সমাধান। এবং যদি সেগুলি ব্যর্থ হয় তবে Global.asax এ একটি সার্ভার করুন। ট্রান্সফার ("~ / ত্রুটি") করুন।
Asbjørn Ulsberg

1
@ ক্রিস, এটি গ্রহণযোগ্য তবে সেরা অনুশীলন নয়। বিশেষত যেহেতু এটি প্রায়শই কোনও এমন কোনও রিসোর্স ফাইলে পুনর্নির্দেশ করা হয় যা এইচটিটিপি 200 স্থিতি কোডের সাথে পরিবেশন করা হয়, যা ক্লায়েন্টকে বিশ্বাস করে যে সবকিছু ঠিকঠাক হয়েছে।
Asbjørn Ulsberg

1
সার্ভারে এই কাজটি করার জন্য আমাকে ওয়েলকনফাইগ্রে <httpErferences ত্রুটিমোড = "বিস্তারিত" /> যুক্ত করতে হয়েছিল।
জেরোইন কে

28

প্রাথমিক প্রশ্নের উত্তর দেওয়ার জন্য "কীভাবে ত্রুটি নিয়ন্ত্রণকারীকে রাউডেটাটা সঠিকভাবে পাস করবেন?":

IController errorController = new ErrorController();
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));

তারপরে আপনার ত্রুটি নিয়ন্ত্রণকারী শ্রেণিতে এই জাতীয় ফাংশনটি প্রয়োগ করুন:

[AcceptVerbs(HttpVerbs.Get)]
public ViewResult Error(Exception exception)
{
    return View("Error", exception);
}

এটি ব্যতিক্রমটিকে ভিউতে ঠেলে দেয়। ভিউ পৃষ্ঠাটি নীচে ঘোষণা করা উচিত:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<System.Exception>" %>

এবং ত্রুটি প্রদর্শনের জন্য কোড:

<% if(Model != null) { %>  <p><b>Detailed error:</b><br />  <span class="error"><%= Helpers.General.GetErrorMessage((Exception)Model, false) %></span></p> <% } %>

ব্যতিক্রম গাছ থেকে সমস্ত ব্যতিক্রম বার্তা সংগ্রহ করে এমন ফাংশনটি এখানে:

    public static string GetErrorMessage(Exception ex, bool includeStackTrace)
    {
        StringBuilder msg = new StringBuilder();
        BuildErrorMessage(ex, ref msg);
        if (includeStackTrace)
        {
            msg.Append("\n");
            msg.Append(ex.StackTrace);
        }
        return msg.ToString();
    }

    private static void BuildErrorMessage(Exception ex, ref StringBuilder msg)
    {
        if (ex != null)
        {
            msg.Append(ex.Message);
            msg.Append("\n");
            if (ex.InnerException != null)
            {
                BuildErrorMessage(ex.InnerException, ref msg);
            }
        }
    }

9

আমি লায়ন_সিএল দ্বারা উল্লেখিত এজাক্স সমস্যার সমাধান পেয়েছি।

global.asax:

protected void Application_Error()
    {           
        if (HttpContext.Current.Request.IsAjaxRequest())
        {
            HttpContext ctx = HttpContext.Current;
            ctx.Response.Clear();
            RequestContext rc = ((MvcHandler)ctx.CurrentHandler).RequestContext;
            rc.RouteData.Values["action"] = "AjaxGlobalError";

            // TODO: distinguish between 404 and other errors if needed
            rc.RouteData.Values["newActionName"] = "WrongRequest";

            rc.RouteData.Values["controller"] = "ErrorPages";
            IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
            IController controller = factory.CreateController(rc, "ErrorPages");
            controller.Execute(rc);
            ctx.Server.ClearError();
        }
    }

ErrorPagesController

public ActionResult AjaxGlobalError(string newActionName)
    {
        return new AjaxRedirectResult(Url.Action(newActionName), this.ControllerContext);
    }

AjaxRedirectResult

public class AjaxRedirectResult : RedirectResult
{
    public AjaxRedirectResult(string url, ControllerContext controllerContext)
        : base(url)
    {
        ExecuteResult(controllerContext);
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context.RequestContext.HttpContext.Request.IsAjaxRequest())
        {
            JavaScriptResult result = new JavaScriptResult()
            {
                Script = "try{history.pushState(null,null,window.location.href);}catch(err){}window.location.replace('" + UrlHelper.GenerateContentUrl(this.Url, context.HttpContext) + "');"
            };

            result.ExecuteResult(context);
        }
        else
        {
            base.ExecuteResult(context);
        }
    }
}

AjaxRequestExtension

public static class AjaxRequestExtension
{
    public static bool IsAjaxRequest(this HttpRequest request)
    {
        return (request.Headers["X-Requested-With"] != null && request.Headers["X-Requested-With"] == "XMLHttpRequest");
    }
}

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

8

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

এটি মূলত গ্লোবাল.এএসএক্সে আপনার সমস্ত অ্যাপ্লিকেশন ত্রুটিগুলি কোনও ত্রুটি নিয়ামকের প্রয়োজন ছাড়াই, [HandlerError]অ্যাট্রিবিউট দিয়ে সজ্জিত করা, বা ওয়েবকনফাইগের customErrorsনোডের সাথে ফিডিংয়ে পরিচালনা করে।


6

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


1
আপনি কীভাবে 404ত্রুটি পরিচালনা করবেন ? যেহেতু কোন নিয়ামক / অ্যাকশন এর জন্য মনোনীত করা হয়নি?
ডেমেন্টিক

গৃহীত উত্তরের মধ্যে 404 টি রয়েছে। এই পদ্ধতির 500 টি ত্রুটি শুধুমাত্র কার্যকর।
ব্রায়ান

আপনার উত্তরটি এটিকে সম্পাদনা করা উচিত। Perhaps a better way of handling errorsখুব বেশি সমস্ত ত্রুটিগুলির মতো শোনাচ্ছে এবং কেবল 500 নয়।
ডেমেন্টিক

4

অ্যাপ্লিকেশন_আরজ্যাকের অনুরোধে সমস্যা রয়েছে ror যদি অজ্যাক্স দ্বারা ডাকা অ্যাকশনে ত্রুটি পরিচালিত হয় - তবে এটি ফলাফলযুক্ত ধারকটির ভিতরে আপনার ত্রুটি দর্শন প্রদর্শন করবে।


4

এটি এমভিসির জন্য সেরা উপায় নাও হতে পারে ( https://stackoverflow.com/a/9461386/5869805 )

নীচে আপনি কীভাবে অ্যাপ্লিকেশন_আররে একটি ভিউ রেন্ডার করেন এবং এটিকে HTTP প্রতিক্রিয়াতে লিখেন। আপনাকে পুনঃনির্দেশ ব্যবহার করার দরকার নেই। এটি সার্ভারে দ্বিতীয় অনুরোধ রোধ করবে, তাই ব্রাউজারের ঠিকানা বারের লিঙ্কটি একই থাকবে। এটি ভাল বা খারাপ হতে পারে, এটি আপনি যা চান তার উপর নির্ভর করে।

Global.asax.cs

protected void Application_Error()
{
    var exception = Server.GetLastError();
    // TODO do whatever you want with exception, such as logging, set errorMessage, etc.
    var errorMessage = "SOME FRIENDLY MESSAGE";

    // TODO: UPDATE BELOW FOUR PARAMETERS ACCORDING TO YOUR ERROR HANDLING ACTION
    var errorArea = "AREA";
    var errorController = "CONTROLLER";
    var errorAction = "ACTION";
    var pathToViewFile = $"~/Areas/{errorArea}/Views/{errorController}/{errorAction}.cshtml"; // THIS SHOULD BE THE PATH IN FILESYSTEM RELATIVE TO WHERE YOUR CSPROJ FILE IS!

    var requestControllerName = Convert.ToString(HttpContext.Current.Request.RequestContext?.RouteData?.Values["controller"]);
    var requestActionName = Convert.ToString(HttpContext.Current.Request.RequestContext?.RouteData?.Values["action"]);

    var controller = new BaseController(); // REPLACE THIS WITH YOUR BASE CONTROLLER CLASS
    var routeData = new RouteData { DataTokens = { { "area", errorArea } }, Values = { { "controller", errorController }, {"action", errorAction} } };
    var controllerContext = new ControllerContext(new HttpContextWrapper(HttpContext.Current), routeData, controller);
    controller.ControllerContext = controllerContext;

    var sw = new StringWriter();
    var razorView = new RazorView(controller.ControllerContext, pathToViewFile, "", false, null);
    var model = new ViewDataDictionary(new HandleErrorInfo(exception, requestControllerName, requestActionName));
    var viewContext = new ViewContext(controller.ControllerContext, razorView, model, new TempDataDictionary(), sw);
    viewContext.ViewBag.ErrorMessage = errorMessage;
    //TODO: add to ViewBag what you need
    razorView.Render(viewContext, sw);
    HttpContext.Current.Response.Write(sw);
    Server.ClearError();
    HttpContext.Current.Response.End(); // No more processing needed (ex: by default controller/action routing), flush the response out and raise EndRequest event.
}

দৃশ্য

@model HandleErrorInfo
@{
    ViewBag.Title = "Error";
    // TODO: SET YOUR LAYOUT
}
<div class="">
    ViewBag.ErrorMessage
</div>
@if(Model != null && HttpContext.Current.IsDebuggingEnabled)
{
    <div class="" style="background:khaki">
        <p>
            <b>Exception:</b> @Model.Exception.Message <br/>
            <b>Controller:</b> @Model.ControllerName <br/>
            <b>Action:</b> @Model.ActionName <br/>
        </p>
        <div>
            <pre>
                @Model.Exception.StackTrace
            </pre>
        </div>
    </div>
}

এটিই সেরা উপায় আইএমও। ঠিক আমি খুঁজছেন ছিল কি.
স্টিভ হ্যারিস

@ স্টিভ হারিস এটির সাহায্যে আনন্দিত! :)
বুর্কাই

3

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


0

রুট পৃষ্ঠায় পুনঃনির্দেশের জন্য নিম্নলিখিত কোড ব্যবহার করুন। ব্যতিক্রম ব্যবহার করুন exception ব্যতিক্রমের অন্তর্নিহিত অন্তর্ভুক্তি। কোয়েরি ব্যতিক্রম কোয়েরি স্ট্রিং ত্রুটি দেয় যদি এটি ক্যোরিস্ট্রিংয়ের দৈর্ঘ্য প্রসারিত করে।

routeData.Values.Add("error", exception.Message);
// clear error on server
Server.ClearError();
Response.RedirectToRoute(routeData.Values);

-1

এই ত্রুটি পরিচালনার পদ্ধতির সাথে আমার সমস্যা আছে: ওয়েবকনফিগের ক্ষেত্রে:

<customErrors mode="On"/>

ত্রুটি হ্যান্ডলারটি ব্যতিক্রম ত্রুটি.শটিএমটিএল এবং কন্ট্রোল ফ্লো পদক্ষেপটি কেবল ব্যতিক্রমের পরে অ্যাপ্লিকেশন_এরর গ্লোবাল.অ্যাক্সেসে সন্ধান করছে

System.InuthorOperationException: 'ত্রুটি' দর্শন বা এর মাস্টারটি পাওয়া যায় নি বা কোনও ভিউ ইঞ্জিন অনুসন্ধান করা অবস্থানগুলিকে সমর্থন করে না। নিম্নলিখিত অবস্থানগুলি অনুসন্ধান করা হয়েছিল: ~ / দর্শন / বাড়ি / ত্রুটি.এএসপিএক্স Views / দর্শন / বাড়ি / তদন্ত System.Web.Mvc.ViewResult.FindView (কন্ট্রোলার কনটেক্সট প্রসঙ্গ) ........ সিটিএসটিএমএল Views / ভিউস / হোম / ত্রুটি.ভবিএইচটিএমএল Views / ভিউ / শেয়ার / ত্রুটি.সিবিটিএমটিএল ~ ............

সুতরাং

 Exception exception = Server.GetLastError();
  Response.Clear();
  HttpException httpException = exception as HttpException;

httpException সর্বদা নাল থাকে তারপরে কাস্টমআররিস মোড = "চালু" :( এটি বিভ্রান্তিকর হয় তারপরে <customErrors mode="Off"/>বা <customErrors mode="RemoteOnly"/>ব্যবহারকারীরা কাস্টমআরিয়ার্স এইচটিএমএল দেখেন, তারপরে কাস্টমআরিয়ার্স মোড = "চালু" এই কোডটিও ভুল


এই কোড অন্য সমস্যা

Response.Redirect(String.Format("~/Error/{0}/?message={1}", action, exception.Message));

302 কোডের পরিবর্তে আসল ত্রুটি কোড (402,403 ইত্যাদি) সহ পৃষ্ঠাটি ফিরুন

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