Қателерді және ерекшеліктерді өңдеу asp.net mvc

Қателерді өңдеу және ASP.NET MVC құрылымында ерекше жағдайларды жою тәсілі қандай? Жалпы консенсус - ерекше жағдайлардың көбеюі. Сонымен, қандай қабат (View немесе Controller) сіз ерекше жағдайларды өңдейсіз бе (оларды қолдана/достық мәтінді көрсету және т.б.). Менің намазым - бұл контроллерде жасалады ма? EDITED: Мен әрбір контроллер әрекеттегі қате өңдеу кодын қайталаудан аулақ болғым келеді . Сондықтан осы кодты қайталамай-ақ қателерді өңдеуді қалай орындау керектігі туралы қысқа мысалды іздеймін.

9
Мен мына әрекеттерді аяқтадым: jQuery ajax ішіндегі Js жағында jsonresult сипаттары «> stackoverflow.com/questions/8249479/…
қосылды автор sarsnake, көзі
Тоқтату техникасын пайдалану мұнда шынымен көмектесе алады. Көптеген тәуелділік инъекциялық контейнерлер оны қолдайды; Мен Spring.NET және Castle Windsor-ді білемін, оларда asp.net mvc-мен интеграция бар. Сіз контроллерлерге қоңырауларға тыйым салатын боласыз және сіздің интерфейсіңіздегі ерекше жағдайларды өңдейсіз.
қосылды автор Marijn, көзі
Бұл сұрақ жақсы басталуы мүмкін: stackoverflow.com/questions/5442231/…
қосылды автор Marijn, көзі

7 жауаптар

Контроллердегі ерекше жағдайларды өңдеу көп қайталанатын кодқа әкелуі мүмкін. Жақсы тәсіл - бұл HandleErrorAttribute қолданатын әрекет сүзгісінде оларды өңдеу. Онда сіз ерекше жағдайларды жаза аласыз және кейін пайдаланушыға дұрыс емес нәрсе шыққанын көрсететін жақсы хабарды көрсететін бетке қайта бағыттай аласыз.

Алайда, контроллер әдістеріңіздегі ерекше жағдайларды өңдеу қажет болған кейбір жағдайлар бар, мысалы, сіз ерекше жағдайдан қалпына келтіріп, пайдаланушыға тиісті хабарды көрсете аласыз, мысалы, бизнес қабатыңыз арқылы шығарылған ерекшелік, Сіз берген жарамсыз. Бұл жағдайда, белгілі бір ерекшелікті ұстап, пайдаланушыға сәйкес хабармен бірге бірдей көріністі көрсету керек.

ӨҢДЕУ:

public class CustomErrorHandlerAttribute : HandleErrorAttribute
{
     public override void OnException(ExceptionContext filterContext)
     {
         var logger = log4net.LogManager.GetLogger("SomeLoggerHere");

         logger.Error("An unhandled error occurred", filterContext.Exception);

         if (filterContext.HttpContext.Request.IsAjaxRequest())
         {
             filterContext.HttpContext.Response.Clear();
             filterContext.HttpContext.Response.Status = "500 Internal Server Error";
             filterContext.Result = new JsonResult { Data = new { ErrorMessage = filterContext.Exception.Message } };
             filterContext.ExceptionHandled = true;                
         }
         else
         {
             base.OnException(filterContext);
         }

    }

}

EDIT 2: Then you use the attribute like this:

[CustomErrorHandler]
public class AnyController : Controller
{
...
}
15
қосылды
HandleErrorAttribute көмегімен қателерді өңдеуді қалай орындау туралы нақты жазылған мысал бересіз бе? Рақмет сізге
қосылды автор sarsnake, көзі
Мен бұл шешімге барғым келеді, бірақ мен жоғарыда аталған кодтың қайда баратынын түсінбеймін бе? Менің контроллерім?
қосылды автор sarsnake, көзі
рахмет, сондықтан CustomErrorHandlerAttribute өзі қайда барады? сол файл? Бұл маңызды ма?
қосылды автор sarsnake, көзі
рахмет, мен оны сынап көруге тура келеді. Мен награданы ұзартамын, себебі мен бүгінгі күні оны көруге мүмкіндігім болмайды
қосылды автор sarsnake, көзі
Мен сіздерге награданы беремін, мен ұқсас нәрсені істедім, бірақ JsonResult-ді өңдеу үшін кеңейтіп алдым, сондықтан пайдаланушыға қате туралы хабарды менің js-кодыма қайтара аламын
қосылды автор sarsnake, көзі
Контроллер сыныптарын бұл атрибутпен түсіндіре аласыз. Мен жауапты жаңарттым.
қосылды автор uvita, көзі
Қаласаңыз, басқа каталогтағы басқа классты жасай аласыз (мысалы, Сүзгілер)
қосылды автор uvita, көзі

Сіздің бұрышыңыз дұрыс. Контроллерге нақты тағайындалу керек. Міне мысал:

[HttpPost]
public ActionResult Create(OrderViewModel model)
{
   if (!ModelState.IsValid)
     return View(model);

   try
   {
      repository.Save(model);
      unitOfWork.Commit();
      return RedirectToAction("Index");
   }
   catch (Exception exc)
   {
      _loggingService.Error(exc);
      ModelState.AddModelError("KeyUsedInView", exc.Message);//or, show a generic error.
   }

   return View(model);
}

Ескертпелер:

  • Алдымен ModelState-ді тексеріңіз. Егер жарамсыз болса, қайтарыңыз.
  • Тіркеу қызметін жаңартпаңыз. Singleton данасын пайдаланыңыз және DI-ды контроллеріңізге енгізу үшін пайдаланыңыз, осылайша интерфейсті өшіріңіз, мысалы: ILoggingService . Бұл сондай-ақ тіркеу қызметін басқа қызметті қоса аласыз (мысалы, электрондық поштаны қолдау).
  • Төменгі қабаттарыңыз (қызметтер, репозиторий және т.б.) қателерді (кедендік немесе кіріктірілген) тастауы мүмкін, сондықтан контроллер оларды ұстайды, өйткені бұл «агрегатор» және жауапты клиент пен сервер арасындағы ағым үшін.
  • Көрініс көрсетуі мүмкін қателерді қосу үшін ModelState.AddModelError пайдаланыңыз. Сондай-ақ, пайдаланушыға ыңғайлы болуы мүмкін пайдаланушы ерекшеліктерін қолдануға және оларды пайдаланушыға көрсетуге болады. Төмен деңгейлі қателер (SQL, т.б.) үшін ModelState-ге жалпы қатені қосуға болады («Кешіріңіз, қате пайда болды, кейінірек қайталап көріңіз»).
3
қосылды
@ Amir978 - мен ұстанбаймын. Ол осы мәселені қай жерде сұрайды?
қосылды автор RPM1984, көзі
@ Amir978 - ештеңе жоқ. «Пайдаланушының есімін сақтап қалуға» неге сенгеніңіз - бұл сценарий дегеніміз не? Тіркелу? Мүмкін, басқа мәселе қойыңыз. Қате туралы есеп болсақ - бұл Elmah үшін. Сондай-ақ, тіркеу қателерін жазу үшін Sentinel сияқты нәрсені қолдануға болады.
қосылды автор RPM1984, көзі
Əрбір əрекеттен сол кодты қайталамас едім.
қосылды автор sarsnake, көзі
Бұл жағдайда пайдаланушы атын қалай сақтауға болады? Және барлық қателер туралы есеп қалай жасалды?
қосылды автор Amir978, көзі
Сіз дұрыс шешім қабылдадым.
қосылды автор Amir978, көзі

Бұл оңай көрінуі мүмкін емес.

Орталықтандырылған ерекшеліктерді өңдеу қажет болса, ең жылдам тәсілі - контроллерде OnException әдісін елемеу

[NonAction]
        protected override void OnException(ExceptionContext filterContext)
        {

            this.Session["ErrorException"] = filterContext.Exception;

            if (filterContext.Exception.GetType() == typeof(PEDException))
            {
               //Mark exception as handled
                filterContext.ExceptionHandled = true;

               //... logging, etc

               //Redirect
                filterContext.Result = this.RedirectToAction( "ShowError", "Errors");
            }

            base.OnException(filterContext);
        }

Бұл әдіс арқылы көріп отырмын, егер сіз өзіңіздің тапсырмаңызды алып тастасаңыз, PEDException барлық қоспағанда, мен OnException әдісімен базалық контроллерді жақсы шешетін бола аламын деп ойлаймын, бірақ бұл ықтимал жағдайларда қауіпті болуы. Әдетте, көптеген басқа мәселелерден аулақ болу үшін (мысалы, кэштеу арқылы, әрекеттеріңіз мүлде орындалмайды, ал атрибут әрқашан орындалатын болады) пайдаланушы атрибутын (ErrorAttributeFilter кеңейту) анықтау керек.

Қосымша ақпарат алу үшін мұнда қараңыз

2
қосылды

Өзгертпелі база контроллерін жасай аласыз және Base Controller сыныбынан мұра аласыз. Содан кейін Customcontroller бағдарламасында OnException переопределите. Содан кейін сіздің контроллеріңіздің әрқайсысы өзіңіздің жаңа реттелетін базалық бақылаушыңыздан мұраға алады.

Я болмаса, global_accid ішіндегі Application_Error оқиғасын ауыстыра аласыз

1
қосылды

Бұл шын мәнінде қол жеткізуге ұмтылған нәрсеге байланысты.

Кез келген қателіктерге қатысты өзгертпелі хабарды көрсетудің қарапайым сценарийі үшін сіз өзіңіздің web.config файлыңызда ескі теңшелетін қателердің дұрыс конфигурациясын қолдана аласыз.

Айта кетейік, бұл қателерде қолданылатын болады, тіпті бақылаушыларға қол жеткізу нүктесіне жете алмайды. URL мекенжайларында дұрыс кодталған арнайы мәндермен байланысты қиындықтар болған кездегідей.

HandleError төлсипаты немесе өзіңіздің жеке теңшелім төлсипаты басқа сценарийлерде қалағаныңыздай жақсы басқаруға мүмкіндік береді.

Теңшелетін дескриптор қате төлсипатын Барлық контроллерлерге қолданғыңыз келсе, оны оны жаһандық әрекет сүзгісі ретінде қолдану арқылы жасай аласыз. Осылайша, оны әр контролерге нақты қолданудың қажеті жоқ.

0
қосылды

Мен әдетте Application_Error-ді Global.asax файлында алдын ала анықтап, пайдаланушыны алып тастауға кез-келген қоспағанда бетіне бағыттап, содан кейін электрондық поштаны кейбір мәліметтермен жіберемін. Жеткілікті қарапайым. Мен әдетте қолданамын:

protected void Application_Error(object sender, EventArgs e)
{
    if (Request.Url.ToString().StartsWith("http://localhost:"))
        return;
    string msg;
    Exception ex = Server.GetLastError().GetBaseException();
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("Exception Found");
    sb.AppendLine("Timestamp: " + System.DateTime.Now.ToString());
    sb.AppendLine("Error in: " + Request.Url.ToString());
    sb.AppendLine("Browser Version: " + Request.UserAgent.ToString());
    sb.AppendLine("User IP: " + Request.UserHostAddress.ToString());
    sb.AppendLine("Error Message: " + ex.Message);
    sb.AppendLine("Stack Trace: " + ex.StackTrace);
    msg = sb.ToString();
    Server.ClearError();
    YourMailHelper.SendException("Your Site Exception", msg);
    Response.Redirect("~/Error.html");
}
0
қосылды

Мен келісімді сақтау үшін BASE контроллер деңгейінде орталықтандырылуға тиіс екендігімен келісемін ... Мен сондай-ақ UI жүйесіндегі пайдаланушыға арналған қате туралы хабарларды көрсетудің стандартты әдісін тіркеу талаптарына қосымша ретінде қарастыру керек деп есептеймін. Контроллер деңгейінде жазылған және тіркелген ерекшеліктер «Достыққа қатысты ерекше жағдайға» оралып, орталық ерекшеліктер процессорына жіберіледі. Ортақ көрініс қалтасындағы error.cshtml файлы - «Өзекті ерекшеліктерді» орындайтын және Controller деңгейінде тіркеліп, error.cshtml файлына жіберілген «Достыққа қарсы» өңдеу және көрсету үшін жақсы орын.

Мен Custom базалық бақылауды пайдаланып, HandleErrorAttribute параметрін Global.asax Application_Start оқиғадан шақырылған FilterConfig класында RegisterGolbalFilters әдісін пайдаланып орнатамын

Base_Controller коды

public class Base_Controller : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        Exception e = filterContext.Exception;
        //Custom Exception Logging Here
        //Log Exception e
        //Elmah.Mvc.ElmahController ec = new Elmah.Mvc.ElmahController();
        base.OnException(filterContext);
    }
}

FilterConfig.cs коды

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

Global.asax Application_Start коды

void Application_Start(object sender, EventArgs e)
{
   //Code that runs on application startup
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

}

Бұл бөлік өте стандартты ... Келесіде сіз жасай аласыз, бұл шынымен пайдаланушыға айтарлықтай әсер етеді. Ерекшеліктерді орталықтандырылған түрде өңдейтін және «Достық» мәтінмәндік хабарларды пайдаланушыға Controller және Action негізінде қоспағанда, қате жіберетін сыныпты пайдаланамын. Төмендегі үлгі кодын қарап шығу үшін Көріністің/Бөлінген қалтасындағы error.cshtml бетін апару блогын ауыстырдым. Төмендегі код қарапайым код болып табылады, себебі бағдарлама мәтінмәнінің негізінде достық қате туралы хабар өзгереді және сіз ерекше жағдайларды өңдеуге қызмет көрсету үшін сыныпқа көшіргіңіз келуі мүмкін.

//Check for Transport Exception with "Actual Exception" stored
//in the inner exception property
if (Model.Exception.InnerException != null)
{
    errFriendly = Model.Exception.Message;
    modelEx = Model.Exception.InnerException;
}
else
{
    modelEx = Model.Exception;
}
try
{           
    throw modelEx; 
}
catch (System.Data.SqlClient.SqlException ex)
{
    //Display Landing page friendly error for exception caused by home controller
    //Display generic data access error for all other controllers/actions
    if (Model.ActionName == "Index" && Model.ControllerName == "Home")
    {errFriendly = "Landing page cannot display product data...";}
    else
    {errFriendly = "Problem Accessing Data...";}
    errType = ex.GetType().ToString();
    errActual = ex.Message;
}

To download the entire code sample see the blog post at: http://www.prodataman.com/Blog/Post/119/MVC-Custom-Exception-Handling

0
қосылды