简体   繁体   中英

Overcoming ErrorInfo limitations in ABP Framework exception conversion

I implemented custom IExceptionToErrorInfoConverter for ASP.NET Boilerplate to convert custom exceptions in Web API.

Problem is that ABP has strict interface, that must return ErrorInfo type :

ErrorInfo Convert(Exception exception);

Problem is that ErrorInfo structure does not fit my requirements so I would like to have my own error DTO.

Anyone has an idea how to circumvent ABP exception conversion?

You can try one trick. May be, when Abp create json response, it will serialize error with it's all available properties via reflection and wrap it into MvcAjaxResponse object with other stuff, ie you can try to create your own class, derrived from ErrorInfo and replace it at IExceptionToErrorInfoConverter implementation:

[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};
    }
}

This is my complementary information thanks to @slava-utesinov accepted answer (in this QA) .

Indeed internally ABP as one would suspect uses object when dealing with serializing DTOs, therefore assumption was solid.

Some sample code from ABP source :

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)
{ ... }

So after success I stepped up the problem with try and hide original ErrorInfo member . Now, knowing that ABP uses Json.NET I found the feature of Conditional Property Serialization . By convention implementing bool ShouldSerialize[member name]() we can instruct serializer to ignore a property.

So I ended up with following proof of concept code :

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; }
}

Pleas note, for some reason you must replace base class implementation to ignore base class members.

That resulted in following JSON, as you can see there is no 'details' property but 'myField' is present.

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

            "code":420,
            "message":"Validation failed",
            "validationErrors":
                [{
                    "message":"'Order Number' should not be empty.",
                    "members":["OrderNumber"]
                }]
        },
        "unAuthorizedRequest":false
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM