2013-04-11 9 views
8

私は、MVC4とEF5.xを使用してアプリケーションを作成しており、レビューのために例外を記録するためにELMAHを使用しています。私たちは最近、このアプリケーションをリリースしました。予想通り、ELMAHログには数十の例外がありました。偉大な(そしてない)!問題は、私はELMAHが持っている知っている詳細およびスタックトレースが私のSubmitChanges()ELMAH MVCを使用してEntityValidationエラーを記録するにはどうすればよいですか?

までのラップのためEntityValidationErrorsプロパティを参照してくださいする方法はありません、これらの例外の一つはもちろん

System.Data.Entity.Validation.DbEntityValidationException 
Validation failed for one or more entities. 
See 'EntityValidationErrors' property for more details. 

であるということです私たち自身の例外を発生させ、何らかの方法でログに記録されるものや方法をカスタマイズできるようにする機能。残念ながら、私はまだELMAHとMVCには新しく、Googleの検索では関連性のあるものは見当たりません。私はEntityValidationErrorsのログにa blog articleを見つけました。著者は、ELMAHでこれを行う方法を投稿すると述べましたが、それは2012年の9月に投稿されて以来、何も見ませんでした。

ご協力いただければ幸いです!

答えて

9

この場合、おそらく最も良いことはtry...catchブロックにcontext.SaveChanges();コールをラップし、ValidationExceptionsから個々のアイテムを記録することです。次のようなものは、あなたが始める必要があります。

try 
{ 
    context.SaveChanges(); 
} 
catch (DbEntityValidationException ve) 
{ 
    var error = ve.EntityValidationErrors.First().ValidationErrors.First(); 
    var msg = String.Format("Validation Error :: {0} - {1}", 
       error.PropertyName, error.ErrorMessage); 
    var elmahException = new Exception(msg); 

    Elmah.ErrorSignal.FromCurrentContext().Raise(elmahException); 
} 
+3

なぜDbEntityValidationExceptionをキャッチする代わりにキャストしていないだけ? –

+0

また、LINQを使用して、すべてのエラーを文字列のリストとして選択し、最初のものを選択するのではなく、それらを結合することができます。 –

+0

より中心的な解決策が好ましいだろう。 Elmahがエラーをキャッチして、それが 'DbValidationError'であるかどうかを調べる関数をオーバーライドするなどしてください。 – Zapnologica

5

方法上記に基づいて、この拡張メソッドについて..

public static void SaveChangesWithBetterValidityException(this DbContext context) 
    { 
     try 
     { 
      context.SaveChanges(); 
     } 
     catch (DbEntityValidationException ve) 
     { 
      var errors = new List<string>(); 
      foreach (var e in ve.EntityValidationErrors) 
      { 
       errors.AddRange(e.ValidationErrors.Select(e2 => string.Join("Validation Error :: ", e2.PropertyName, " : ", e2.ErrorMessage))); 
      } 
      var error = string.Join("\r\n", errors); 
      var betterException = new Exception(error, ve); 

      throw betterException; 
     } 
    } 

ELMAHはそれでより良い例外がありますが

2

Iを記録していますすべてのDbEntityValidationException例外をElmahに転送するために、に以下を追加しました:

private void ElmahEntityValidationException() 
{ 
    var dbEntityValidationException = Server.GetLastError() as DbEntityValidationException; 

    if (dbEntityValidationException != null) 
    { 
     var errors = new List<string>(); 
     foreach (var entityError in dbEntityValidationException.EntityValidationErrors) 
     { 
      errors.AddRange(entityError.ValidationErrors.Select(e2 => string.Join("Validation Error :: ", e2.PropertyName, " : ", e2.ErrorMessage))); 
     } 
     var error = string.Join("\r\n", errors); 
     var betterException = new Exception(error, dbEntityValidationException); 

     Elmah.ErrorSignal.FromCurrentContext().Raise(betterException); 
    } 
} 

protected void Application_Error(object sender, EventArgs e) 
{ 
    ElmahEntityValidationException(); 
} 

このコードの一部は、@Paige Cook'sと@ Original10の投稿から再利用されました。

public class ElmahHandleWebApiErrorAttribute : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     var e = context.Exception; 
     // Try parse as entity error (i'm not sure of performance implications here) 
     var efValidationError = e as DbEntityValidationException; 
     if (efValidationError == null) 
     { 
      RaiseErrorSignal(e); 
     } 
     else 
     { 
      RaiseEntityFrameWorkValidationErrorSignal(efValidationError); 
     } 
    } 

    private static bool RaiseErrorSignal(Exception e) 
    { 
     var context = HttpContext.Current; 
     if (context == null) 
      return false; 
     var signal = ErrorSignal.FromContext(context); 
     if (signal == null) 
      return false; 
     signal.Raise(e, context); 
     return true; 
    } 

    private static bool RaiseEntityFrameWorkValidationErrorSignal(DbEntityValidationException e) 
    { 
     var context = HttpContext.Current; 
     if (context == null) 
      return false; 
     var signal = ErrorSignal.FromContext(context); 
     if (signal == null) 
      return false; 

     //Taken from post above 
     var errors = new List<string>(); 
     foreach (var entityError in e.EntityValidationErrors) 
     { 
      errors.AddRange(entityError.ValidationErrors.Select(e2 => string.Join("Validation Error :: ", e2.PropertyName, " : ", e2.ErrorMessage))); 
     } 
     var error = string.Join("\r\n", errors); 
     var betterException = new Exception(error, e); 

     signal.Raise(betterException, context);   
     return true; 
    } 
} 

、その後、私はApp_Start

config.Filters.Add(new ElmahHandleWebApiErrorAttribute()); 
+0

これをapp_startのフィルタセクションに追加できませんか? – Zapnologica

0

はELMAHとEF検証エラーのためのグローバルウェブAPIソリューションのための私の実装です以下のコードでは完璧ではありません(ここにコールスタックをリセットしても構いませんが、Elmahのログに記録されているアドレスの詳細が表示されますので、あなたのセキュリティ暗示NS、これは&かなり簡潔ですが、私のニーズを満たし:

try 
{ 
    return base.SaveChanges(); 
} 
catch (DbEntityValidationException e) 
{ 
    var de = new DetailedEntityValidationException(e); 
    throw de; 
} 

public class DetailedEntityValidationException : Exception 
{ 
    public DetailedEntityValidationException(DbEntityValidationException ve) 
     : base(ve.Message + ":\r\n\t-" + string.Join(new string('-',20) + "\r\n\t-", ve.EntityValidationErrors.Select(ev=>string.Join("\r\n\t-",ev.ValidationErrors.Select(e=>e.ErrorMessage))))) 
    {} 
} 
1

再投げなどの下WebApiConfig.csファイルに属性を登録します。ここでは

関連する問題