2013-06-11 3 views
20

컨트롤러의 작업에서 호출 된 코드에서 예외가 발생하면 어떻게 처리해야합니까? try-catch 문이 전혀없는 모범 사례에 대한 사례가 많이 있습니다. 호출이 액세스 할 수있는 데이터베이스에있는 경우컨트롤러 (ASP.NET MVC)에서 예외 처리

public ViewResult Index() 
{ 
    IList<CustomModel> customModels = _customModelRepository.GetAll(); 
    return View(customModels); 
} 

은 분명히이 코드가 예외를 던질 수 있고 우리는 예를 들어, 엔티티 프레임 워크와 같은 ORM을 사용하는 예를 들어, 저장소에서 데이터에 액세스.

그러나 내가 볼 수있는 것은 예외가 발생하여 사용자에게 불쾌한 오류 메시지가 표시된다는 것입니다.

HandleError 특성을 알고 있지만 처리되지 않은 예외가 발생하면 오류 페이지로 리디렉션하는 데 주로 사용된다는 것을 알고 있습니다. 물론

,이 코드는 시도 - 캐치에 싸여 할 수 있지만, 더 많은 논리가 특히 잘 분리되지 않습니다

public ViewResult Index() 
{ 
    if (ValidationCheck()) 
    { 
     IList<CustomModel> customModels = new List<CustomModel>(); 
     try 
     { 
      customModels = _customModelRepository.GetAll(); 
     } 
     catch (SqlException ex) 
     { 
      // Handle exception 
     } 

     if (CustomModelsAreValid(customModels)) 
      // Do something 
     else 
      // Do something else 
    } 

    return View(); 
} 

은 이전에 내가 좋아하는 예외를 던질 수있는 모든 코드를 추출했다 데이터베이스 호출은 오류를 처리하고 사용자에게 메시지를 표시하기 위해 다시 메시지를 반환하는 DataProvider 클래스로 호출합니다.

이 문제를 처리하는 가장 좋은 방법은 무엇입니까? 나는 예외 페이지로 돌아 가기를 원하지 않는다. 대신, 정상적인보기로 사용자에게 오류 메시지가 표시되어야합니다. 이전 방법이 정확 했습니까? 아니면 더 나은 솔루션이 있습니까?

답변

20

는 좀 더 사용자 친화적 인 메시지를 표시 할 세 가지를 수행합니다

  1. 은 글로벌 예외 핸들러을 활용할 수 있습니다. MVC의 경우 : Application_Error in Global.asax. 여기에서 사용 방법을 배웁니다. http://msdn.microsoft.com/en-us/library/24395wz3(v=vs.100).aspx
  2. 예외를 UserFriendlyException으로 하위 클래스화합니다. 전 기본 서비스 클래스에서 최선을 다해 일반 오래된 예외 대신이 UserFriendlyException을 발생시킵니다. 나는 항상 이러한 사용자 지정 예외에 사용자에게 의미있는 메시지를 넣으려고합니다. 그 주요 목적은 Application_Error 메서드에서 예외에 대한 형식 검사를 수행하는 것입니다. UserFriendlyExceptions의 경우, "Hey! 91 degrees는 유효한 위도 값이 아닙니다!"와 같이 서비스에 깊이 사용 된 사용자 친화적 인 메시지를 사용합니다. " 일반적인 예외 인 경우 처리하지 않은 경우가 있습니다. 따라서 "Oops, something went wrong!와 같은보다 일반적인 오류 메시지가 표시됩니다. 해결을 위해 최선을 다할 것입니다!"
  3. 또한 사용자 친화적 인보기 또는 JSON 렌더링을 담당하는 ErrorController를 만듭니다. 이것은 메소드가 Application_Error 메소드에서 호출 될 컨트롤러입니다.

편집 : 나는 그것이 밀접하게 관련이 있기 때문에 내가 ASP.NET 웹 API에 대한 언급을 줄 거라고 생각 . 웹 API 엔드 포인트의 사용자가 반드시 브라우저 일 필요는 없으므로 나는 약간 다른 방식으로 오류를 처리하려고합니다. 나는 여전히 "FriendlyException"(# 2 위)을 사용하지만, ErrorController로 리디렉션하는 대신 모든 엔드 포인트가 Error 속성을 포함하는 일종의 기본 유형을 반환하도록합니다. 따라서 예외가 웹 API 컨트롤러까지 완전히 버블 링되면 API 응답의 Error 속성에 해당 오류를 표시해야합니다. 이 오류 메시지는 API 컨트롤러가 의존하는 클래스에서 버블 링 된 친숙한 메시지이거나 예외 유형이 FriendlyException이 아닌 경우 일반 메시지입니다. 그렇게하면 소비하는 클라이언트는 API 응답의 Error 속성이 비 었는지 여부를 간단히 확인할 수 있습니다. 오류가있는 경우 메시지를 표시하고 그렇지 않은 경우 평소와 같이 진행하십시오. 좋은 점은 친숙한 메시지 개념으로 인해 메시지가 일반 "오류!"메시지보다 사용자에게 훨씬 의미있을 수 있다는 것입니다. 메시지. Xamarin으로 모바일 앱을 작성할 때이 전략을 사용합니다. Xamarin에서는 웹 서비스와 iOS/Android 앱간에 C# 유형을 공유 할 수 있습니다.

+1

: 나는 오류를 처리하는 컨트롤러를 하나에 여러 프로젝트의 referenes을 가지고 있기 때문에 – NovaJoe

0

모든 질문은 오류 처리를 다루는 방법이 너무 많기 때문에 대답은 항상 "의존적"이므로 매우 건설적인 것은 아닙니다.

많은 예외가 기본적으로 복구 할 수 없기 때문에 많은 사람들이 HandleError 메서드를 사용하고 싶어합니다. 내 물건을 반납 할 수 없다면 어떻게 할거 니? 당신은 어쨌든 그들에게 오류를 보여줄 것입니다, 그렇죠?

질문에 오류가 표시되는 방식이 달라집니다. 오류 페이지를 표시하면 HandleError가 정상적으로 작동하고 오류를 기록하기 쉬운 위치가 제공됩니다. Ajax를 사용하거나 더 좋아하는 것을 원한다면, 그렇게 할 수있는 방법을 개발해야한다.

DataProvider 클래스에 대해 이야기합니다. 이것이 기본적으로 저장소입니다. 왜 그것을 저장소에 구축하지 않습니까?

16

Asp.Net MVC를 사용하면 컨트롤러에 대한 OnException 메서드를 재정의 할 수도 있습니다.

protected override void OnException(ExceptionContext filterContext) 
{ 
    if (filterContext.ExceptionHandled) 
    { 
     return; 
    } 
    filterContext.Result = new ViewResult 
    { 
     ViewName = ... 
    }; 
    filterContext.ExceptionHandled = true; 
} 

이렇게하면 원할 경우 예외를 참조하는 메시지가 포함 된 사용자 지정 오류 페이지로 리디렉션 할 수 있습니다.

보안/HandleErrorsController.cs 나는 또한 패트릭 Desjardins에 '대답에 동의

protected override void OnException(ExceptionContext filterContext) 
{ 
    MyLogger.Error(filterContext.Exception); //method for log in EventViewer 

    if (filterContext.ExceptionHandled) 
     return; 

    filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError; 

    filterContext.Result = new JsonResult 
    { 
     Data = new 
     { 
      Success = false, 
      Error = "Please report to admin.", 
      ErrorText = filterContext.Exception.Message, 
      Stack = filterContext.Exception.StackTrace 
     }, 
     JsonRequestBehavior = JsonRequestBehavior.AllowGet 
    }; 
    filterContext.ExceptionHandled = true; 
} 
+0

downvoters 조금 논쟁 :이 대답은 무엇이 잘못 되었나요? – Askolein

+1

@Askolein 나는 이해하지 못한다. 내가하는 것처럼 그것이 가능한 해결책이라고 생각하면 투표를 0으로 다시 설정할 수 있습니다. –

+0

그리고 끝났습니다 ... +1 – Askolein

1

가 나는 OnException 재정의를 사용 오버라이드 (override) OnException은 오류를 처리하는 가장 좋은 방법입니다. 특히 기본 컨트롤러에있는 경우 다른 모든 컨트롤러가 상속합니다.
+2

메시지 및 스택 추적과 같은 원시 예외 내용을 사용자에게 반환하는 것은 정말 좋은 생각이 아닙니다. –

관련 문제