Преодоление ограничений ErrorInfo в преобразовании исключений ABP Framework

Я реализовал кастом IExceptionToErrorInfoConverter для ASP.NET Boilerplate для преобразования пользовательских исключений в веб-API.

Проблема в том, что ABP имеет строгий интерфейс, который должен вернуть ErrorInfo тип:

ErrorInfo Convert(Exception exception);

Проблема в том, что ErrorInfo структура не соответствует моим требованиям, поэтому я хотел бы иметь свою собственную ошибку DTO.

У кого-нибудь есть идеи, как обойти преобразование исключений ABP?

2 ответа

Решение

Вы можете попробовать один трюк. Может быть, когда Abp создаст ответ json, он будет сериализовать ошибку со всеми доступными свойствами через отражение и обернуть ее в MvcAjaxResponse объект с другими вещами, то есть вы можете попытаться создать свой собственный класс, полученный из ErrorInfo и заменить его на IExceptionToErrorInfoConverter реализация:

[Serializable]
public class MyErrorInfo : ErrorInfo
{
    public string MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
}

public class MyExceptionToErrorInfoConverter : IExceptionToErrorInfoConverter
{
    public IExceptionToErrorInfoConverter Next { set { } }        

    public ErrorInfo Convert(Exception exception)
    {
        return new MyErrorInfo{ MyProperty1 = "test", MyProperty2  = 1};
    }
}

Это моя дополнительная информация, благодаря @slava-utesinov принятому ответу (в этом QA).

Действительно внутри ABP, как можно было бы предположить, использует object поэтому при работе с сериализацией DTO предположение было твердым.

Пример кода из источника ABP:

public static string ToJsonString(this object obj, bool camelCase = false, bool indented = false)
{ ... }

protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{ ... }

Поэтому после успеха я усилил проблему с попыткой скрыть оригинальный элемент ErrorInfo. Теперь, зная, что ABP использует Json.NET, я обнаружил функцию условной сериализации свойств. По соглашению bool ShouldSerialize[member name]() мы можем дать указание сериализатору игнорировать свойство.

В итоге я получил следующие доказательства кода концепции:

public class ErrorInfoEx : ErrorInfo
{
   public new string Details { get; set; }
   public bool ShouldSerializeDetails() { return false; }

   public ErrorInfoEx(int code, string message) : base(code, message) { }
   public string MyField { get; set; }
}

Обратите внимание, по какой-то причине вы должны заменить реализацию базового класса, чтобы игнорировать членов базового класса.

Это привело к следующему JSON, как вы можете видеть, что нет свойства 'details', но присутствует myField.

{
    "success":false,
    "result":null,
    "error":
        {
            "myField":"123",

            "code":420,
            "message":"Validation failed",
            "validationErrors":
                [{
                    "message":"'Order Number' should not be empty.",
                    "members":["OrderNumber"]
                }]
        },
        "unAuthorizedRequest":false
}
Другие вопросы по тегам