Hi, I have this try/catch block in my app services
try
{
newEntity = _repository.Insert(newEntity);
CurrentUnitOfWork.SaveChanges();
}
catch (DbEntityValidationException ex)
{
var validationErrors = ex.EntityValidationErrors?.SelectMany(e => e.ValidationErrors?.Select(v => new ValidationResult(v.ErrorMessage, new string[] { v.PropertyName }))).ToList();
throw new AbpValidationException(FriendlyMessages.FormDataValidationFailed, validationErrors);
}
I want to move above handler for DbEntityValidationException from App Services to some single base level and seems it can be done via implementing and registering IExceptionToErrorInfoConverter via IErrorInfoBuilder.AddExceptionConverter(IExceptionToErrorInfoConverter converter)
The question is where from I can get acces to IErrorInfoBuilder for app service ? Or maybe someone could advise another good approach to have above handler in one place and to be used by all app services by default
3 Answer(s)
-
1
I think a good place is to override SaveChanges and SaveChangesAsync in your dbcontext. Base base method in a try catch and do the same you are doing now.
If you want to make it via IExceptionToErrorInfoConverter, then;
- create a class inherits from IExceptionToErrorInfoConverter
- In postinitialize of your module, use such a code:
IocManager.Resolve<ErrorInfoBuilder>().AddExceptionConverter(new MyConverter())
If you want to inject dependencies to MyConverter, you can register it to dependency injection (see <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/Dependency-Injection#DocHelperInterfaces">http://www.aspnetboilerplate.com/Pages/ ... Interfaces</a>) then use the code like that:
IocManager.Resolve<ErrorInfoBuilder>().AddExceptionConverter(IocManager.Resolve<MyConverter>())
-
0
I've decided to use SaveChanges approaches, works good, thank you.
-
0
Seems I found small issues with that approach and looks like it should be fixed in Abp core:
public override int SaveChanges() { try { return base.SaveChanges(); } catch (DbEntityValidationException ex) { this.Logger.Warn(FriendlyMessages.FormDataValidationFailed, ex); var validationErrors = ex.EntityValidationErrors?.SelectMany(e => e.ValidationErrors?.Select(v => new ValidationResult(v.ErrorMessage, new string[] { v.PropertyName }))).ToList(); throw new AbpValidationException(FriendlyMessages.FormDataValidationFailed, validationErrors); } }
Below exception rised by running seed with invalid data for entity. Ideally there should be AbpValidationException details but another SerializationException raised instead...
System.Runtime.Serialization.SerializationException: Type is not resolved for member 'Abp.Runtime.Validation.AbpValidationException,Abp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner) at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force) at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0() at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command) Type is not resolved for member 'Abp.Runtime.Validation.AbpValidationException,Abp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.