Hi,
I have a method in Application layer. It is responsible for validating and adding an account. It is very much the same as what you have done with OrganizationUnit. The problem is that I can not use it this way in my custom API which is in a custom project. (added manually to the solution). I want to send almost the same message as AjaxResponse in the ABP Framework.
public async Task<AccountDto> Create(CreateAccountInput input)
{
var account = new Account
{
Id = (input.Id == Guid.Empty ? Guid.NewGuid() : input.Id),
AccountNumber = input.AccountNumber,
Name = input.Name
};
// When not valid, it throws the first exception and immediately bubbles up to the caller.
if (account.Name.IsNullOrWhiteSpace())
throw new UserFriendlyException(111, L("AccountName_IsMandatory", account.Name));
if (account.Name.Length < 3)
throw new UserFriendlyException(112, L("AccountName_IsTooShort", account.Name));
if (await AccountNameAlreadyExists(account.ParentId, account.Name))
throw new UserFriendlyException(113, L("AccountName_AlreadyExists", account.Name));
// Save
using (var unitOfWork = UnitOfWorkManager.Begin())
{
await _accountRepository.InsertAsync(account);
UnitOfWorkManager.Current.Completed += (sender, args) => { /* TODO: Send email to assigned person or do something else */ };
await unitOfWork.CompleteAsync();
}
return account.MapTo<AccountDto>();
}
This is an example. In reality I would like to know 'exactly' which error was the cause of failure. Throwing "UserFriendlyException" for a validation is not something I could use and test. Look at the code below from the test project:
[Fact]
public async Task Should_Not_Create_Account_With_Same_Name_In_Same_Level2()
{
//Arrange
var account = new CreateAccountInput
{
AccountNumber = "123",
Name = "Same Name"
};
UsingDbContext(
context =>
{
context.Accounts.Add(
new Account
{
Name = account.Name, // "Same Name"
AccountNumber = "456"
});
});
//Act & Assert -- This just tells me that there was an "UserFriendlyException". Nothing more.
var ex = await Assert.ThrowsAsync<UserFriendlyException>(
() => _accountAppService.Create(account)
);
Assert.NotNull(ex);
ex.Code.ShouldBe(113);
}
I have to say that I have many custom API's which I put in their own project in the solution. Their project is a copy of the xx.Web.Host project. They are not intended for the UI. They have their own controller and just call the Application App services. You recommended this approach to me.
By the way I saw AjaxResponse and ErrorInfo classes in the ABP. Should I use them or is there any other better way? I want to response message for all of my custom API's are very much like the AjaxResponse.
Thanks.