2013-04-11 1 views
8

Я пишу приложение с использованием MVC4 и EF5.x и используя ELMAH для регистрации исключений для проверки. Недавно мы выпустили приложение, и, как ожидалось, журнал ELMAH заполнил несколько десятков исключений. Великий (и не)! Проблема состоит в том, что один из этих исключенийКак регистрировать ошибки EntityValidation с помощью ELMAH MVC?

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

Конечно, нет никакого способа, чтобы увидеть свойство EntityValidationErrors для получения более подробной информации и трассировка стеки оборачивает мой SubmitChanges()

Я знаю ELMAH имеет способность позволять нам поднимать собственные исключения и каким-то образом настраивать то, что регистрируется и как. К сожалению, я все еще очень новичок в ELMAH и MVC, и поиск в Google не стал чем-то значимым. Я нашел a blog article при регистрации EntityValidationErrors, и автор специально упомянул, что он опубликует, как это сделать в ELMAH, но опубликован в сентябре 2012 года, и с тех пор я ничего не видел.

Любая помощь была бы принята с благодарностью!

ответ

9

Возможно, самое лучшее, что нужно сделать в этом случае, - это обернуть свой вызов context.SaveChanges(); в блок try...catch, а затем зарегистрировать отдельные элементы из 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 добавила следующее к моему Global.asax.cs, чтобы переслать все исключения DbEntityValidationException в Эльму через мое приложение MVC:

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 и @ Original10.

+0

Невозможно добавить это в раздел фильтров под app_start? – Zapnologica

0

Вот моя реализация глобального решения Web API для Elmah и EF Validation ошибок:

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; 
    } 
} 

, а затем зарегистрировать атрибут в файле WebApiConfig.cs под App_Start

config.Filters.Add(new ElmahHandleWebApiErrorAttribute()); 
1

Re метания как в соответствии с приведенным ниже кодом не является совершенным (хотя я не возражаю, чтобы сбросить стек вызовов здесь, поскольку зарегистрированные данные Эльмы о адресе, который вы отправили, покажут мне, что приведет к исключению), и вам придется разработать свою собственную импликацию безопасности нс, но это довольно кратким & отвечает моим потребностям:

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))))) 
    {} 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^