克服 ABP 框架异常转换中的 ErrorInfo 限制
Overcoming ErrorInfo limitations in ABP Framework exception conversion
我为 ASP.NET 样板实现了自定义 IExceptionToErrorInfoConverter
以在 Web API 中转换自定义异常。
问题是ABP有严格的接口,必须return ErrorInfo
类型:
ErrorInfo Convert(Exception exception);
问题是 ErrorInfo
结构不符合我的要求,所以我想有自己的错误 DTO。
有人知道如何绕过 ABP 异常转换吗?
你可以试试一招。可能是,当 Abp 创建 json 响应时,它会通过反射用它的 所有可用的 属性序列化错误,并将它与其他东西一起包装到 MvcAjaxResponse
对象中,即你可以尝试创建自己的 class,派生自 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 。
确实在 ABP 内部,正如人们所怀疑的那样,在处理序列化 DTO 时使用 object
,因此假设是可靠的。
来自 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 我发现了 Conditional Property Serialization 的特性。按照惯例实现 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; }
}
请注意,由于某些原因,您必须替换基础 class 实现以忽略基础 class 成员。
结果是 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
}
我为 ASP.NET 样板实现了自定义 IExceptionToErrorInfoConverter
以在 Web API 中转换自定义异常。
问题是ABP有严格的接口,必须return ErrorInfo
类型:
ErrorInfo Convert(Exception exception);
问题是 ErrorInfo
结构不符合我的要求,所以我想有自己的错误 DTO。
有人知道如何绕过 ABP 异常转换吗?
你可以试试一招。可能是,当 Abp 创建 json 响应时,它会通过反射用它的 所有可用的 属性序列化错误,并将它与其他东西一起包装到 MvcAjaxResponse
对象中,即你可以尝试创建自己的 class,派生自 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
确实在 ABP 内部,正如人们所怀疑的那样,在处理序列化 DTO 时使用 object
,因此假设是可靠的。
来自 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 我发现了 Conditional Property Serialization 的特性。按照惯例实现 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; }
}
请注意,由于某些原因,您必须替换基础 class 实现以忽略基础 class 成员。
结果是 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
}