26

コントローラーのアクションから呼び出された独自のコードによって例外がスローされた場合、どのように処理する必要がありますか? try-catch ステートメントがまったくないベスト プラクティスの例がたくさんあります。たとえば、リポジトリからのデータへのアクセス:

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

呼び出しがアクセスできないデータベースであり、たとえば Entity Framework のような ORM を使用している場合、このコードは明らかに例外をスローする可能性があります。

しかし、私が見ることができるのは、例外が発生し、ユーザーに厄介なエラー メッセージが表示されることだけです。

私は HandleError 属性を認識していますが、未処理の例外が発生した場合にエラー ページにリダイレクトするために主に使用されることを理解しています。

もちろん、このコードは try-catch でラップすることもできますが、特にロジックがさらにある場合はうまく分離できません。

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 クラスに、データベース呼び出しなどの例外をスローする可能性のあるすべてのコードを抽出しました。

これを処理する最良の方法は何ですか?一部の例外ではそうすべきではないため、常にエラーページに戻りたいとは限りません。代わりに、ユーザーへのエラー メッセージを通常のビューで表示する必要があります。以前の方法は正しかったですか、それともより良い解決策はありますか?

4

4 に答える 4

24

よりユーザーフレンドリーなメッセージを表示するために、次の 3 つのことを行います。

  1. グローバル例外ハンドラを活用してください。MVC の場合: Global.asax の Application_Error。ここで使用方法を学びます: http://msdn.microsoft.com/en-us/library/24395wz3(v=vs.100).aspx
  2. Exception を UserFriendlyException にサブクラス化します。基礎となるすべてのサービス クラスで、単純な古い例外ではなく、この UserFriendlyException をスローするように最善を尽くしています。私は常に、これらのカスタム例外にユーザーにとって意味のあるメッセージを入れようとしています. その主な目的は、Application_Error メソッドで例外の型チェックを実行できるようにすることです。UserFriendlyExceptions については、「ヘイ! 91 度は有効な緯度の値ではありません!」など、サービスの奥深くに設定したユーザー フレンドリーなメッセージを使用するだけです。それが通常の例外である場合、それは私が処理していないケースであるため、「おっと、問題が発生しました! 修正するために最善を尽くします!」のような、より一般的なエラー メッセージを表示します。
  3. また、ユーザー フレンドリーなビューまたは JSON のレンダリングを担当する ErrorController も作成します。これは、メソッドが Application_Error メソッドから呼び出されるコントローラーです。

編集: ASP.NET Web API は密接に関連しているため、言及したいと思います。Web API エンドポイントのコンシューマーは必ずしもブラウザーではないため、私は少し違った方法でエラーを処理したいと考えています。私はまだ "FriendlyException" (上記の #2) を使用していますが、ErrorController にリダイレクトする代わりに、すべてのエンドポイントが Error プロパティを含む何らかの基本型を返すようにしています。そのため、例外が Web API コントローラーに到達した場合は、そのエラーを API 応答の Error プロパティに貼り付けます。このエラー メッセージは、API コントローラーが依存するクラスから発生したわかりやすいメッセージか、例外の種類が FriendlyException でない場合の一般的なメッセージのいずれかになります。そうすれば、消費するクライアントは、API 応答の Error プロパティが空かどうかを簡単に確認できます。エラーが存在する場合はメッセージを表示し、そうでない場合は通常どおり続行します。良い点は、フレンドリーなメッセージの概念により、メッセージは一般的な「エラー!」よりもユーザーにとってはるかに意味のあるものになる可能性があることです。メッセージ。Xamarin でモバイル アプリを作成するときにこの戦略を使用します。これにより、Web サービスと iOS/Android アプリの間で C# 型を共有できます。

于 2013-06-11T14:48:24.923 に答える
3

エラーを処理するコントローラーを持つプロジェクトを参照するプロジェクトがいくつかあるため、OnException オーバーライドを使用しました。

セキュリティ/HandleErrorsController.cs

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;
}
于 2014-08-20T19:53:20.067 に答える