UserFriendlyException для профиля Automapper - PullRequest
0 голосов
/ 19 мая 2019

Я столкнулся с проблемой.У меня есть бизнес-правило, которое определено в Entity, при проверке этого правила в сущности, я выкидываю UserFriendlyException в случае нарушения бизнес-правила.Пример:

private DateTime? _expireDate;

public DateTime? ExpireDate {
    get => _expireDate;
    set {
        if (value.HasValue) {
            _expireDate = EnsureExpireDateRules (value.Value);
            PeriodInMonth = 0;
        }
    }
}

private DateTime EnsureExpireDateRules (DateTime dateTime) {
    dateTime = dateTime.GetDateZeroTime ();

    var currentUtcDateTime = DateTime.UtcNow.GetDateZeroTime ();

    if (dateTime <= currentUtcDateTime)
        throw new UserFriendlyException ("License date should be at least one day late than today.");

    return dateTime;
}

А в профиле Automapper у меня есть правило по умолчанию

CreateMap ();

И когда это происходит, у меня нет UserFriendlyException на клиентесторона, вместо этого у меня есть обычное исключение с кодом 500 (Внутренняя ошибка сервера).В лог-системе я вижу следующее:

AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
LicenseRequestInput -> LicenseRequest
LicenseManager.LicenseManager.Dto.LicenseRequestInput -> LicenseManager.LicenseManager.Entities.LicenseRequest

Type Map configuration:
LicenseRequestInput -> LicenseRequest
LicenseManager.LicenseManager.Dto.LicenseRequestInput -> LicenseManager.LicenseManager.Entities.LicenseRequest

Destination Member:
ExpireDate
 ---> Abp.UI.UserFriendlyException: License date should be at least one day late than today.
   at LicenseManager.LicenseManager.Entities.LicenseRequest.EnsureExpireDateRules(DateTime dateTime) in /Users/grinay/License management portal/src/LicenseManager.Core/LicenseManager/Entities/LicenseRequest.cs:line 56
.....more...... 

Похоже, ABP не перехватывает исключение, которое приходит из профиля Automap.Пожалуйста, помогите мне решить эту проблему.

Ответы [ 2 ]

0 голосов
/ 25 мая 2019

Я расширяю AbpExceptionFilter для этого.Не уверен, что это хорошая практика, но я все равно уже использовал его для переноса возвращаемых значений Task.

Поэтому я развернул UserFriendlyException.

Я унаследовал AbpExceptionFilter и переопределил метод HandleAndWrapException.

protected override void HandleAndWrapException(ExceptionContext context, WrapResultAttribute wrapResultAttribute)
        {
  if (!ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType))
            {
                return;
            }

            context.HttpContext.Response.StatusCode = GetStatusCode(context, wrapResultAttribute.WrapOnError);

            if (!wrapResultAttribute.WrapOnError)
            {
                return;
            }

            if (context.Exception is AutoMapperMappingException && context.Exception.InnerException is UserFriendlyException)
            {
                context.Exception = context.Exception.InnerException;;
            }

            context.Result = new ObjectResult(
                new AjaxResponse(
                    _errorInfoBuilder.BuildForException(context.Exception),
                    context.Exception is AbpAuthorizationException
                )
            );

            EventBus.Trigger(this, new AbpHandledExceptionData(context.Exception));

            context.Exception = null; //Handled!

        }

и заменил фильтр по умолчанию на мой

 public override void PreInitialize()
        {
...
            Configuration.ReplaceService<AbpExceptionFilter, CustomAbpExceptionFilter>();

...
        }

Теперь он возвращает мне мое UserFriendlyException в случае ошибки сопоставления.

0 голосов
/ 21 мая 2019

Проблема:

Автоматический картограф обертывает UserFriendlyException с AutoMapperMappingException.Поскольку внешнее исключение больше не UserFriendlyException, ABP не может его обработать!

Решение:

Поместите EnsureExpireDateRules() в DTO (LicenseRequestInput) ивсе будет работать нормально.

Обновление:

Лучшая практика для того, что вы хотите сделать, это:

Сделайте все свои свойства protected set, сделайтеконструктор защищен.Вы можете создать публичный метод для инициализации вашей сущности с обязательными свойствами.И пусть ваш менеджер справится с логикой вашей бизнес-области.

public class MyEntity 
{
    public DateTime? ExpireDate {get; protected set;}

    protected MyEntity()
    {

    }

    public MyEntity(mandatoryPropertiesToCreateYourEntity...)
    {

    }
}

 public class MyEntityManager
    {

        public void SetExpireDate(MyEntity myEntity, DateTime? expireDate){
        {
              if(myBusinessLogicIsOk) {
                  myEntity.ExpireDate = expireDate;
              }
              else
              {
                  throw new Exception("Invalid expire date!");
              }
        }
   }
...