Сериализация исключения возвращает очень большой JSON - PullRequest
0 голосов
/ 03 октября 2018

Я перевожу приложение с полного фреймворка на сетевое ядро.Я изо всех сил пытаюсь получить диспетчер исключений для apis для работы.

В настоящее время я использую решение на основе атрибутов.

У меня есть этот класс

public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override async void OnException(ExceptionContext context)
    {
        context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        var ex = context.Exception;
        if (ex == null) return;

        context.HttpContext.Response.ContentType = "application/json";

        using (var writer = new StreamWriter(context.HttpContext.Response.Body))
        {
            var js = new JsonSerializer();
            js.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            js.Serialize(writer, ex);
            await writer.FlushAsync().ConfigureAwait(false);
        }
    }
}

и я использую соответствующий атрибут на желаемом контроллере.[ApiExceptionFilter]

Дело в том, что когда я ловлю исключение и выкидываю его клиенту в виде строки JSON.Я получил загрузку в 27 Мб, и это потому, что он сериализует TargetSite и внутри него сериализует DefinedTypes, который представляет собой список сборок и типов.

Кто-нибудь знает, как я могу сериализовать исключение, избегая этих свойств?

Вот пример исключения:

{
Id: null,
Message: "Hubo errores en la validación de los parámetros de la operación.",
Data: { },
InnerException: {
Detail: {
Details: [
{
Key: "Cuit",
Message: "The field Cuit must match the regular expression '^[0-9]{11}$'.",
ParameterName: "request"
}
]
},
Action: null,
Code: {
IsPredefinedFault: true,
IsSenderFault: true,
IsReceiverFault: false,
Namespace: "http://schemas.xmlsoap.org/soap/envelope/",
Name: "Client",
SubCode: null
},
Message: "Hubo errores en la validación de los parámetros de la operación.",
Reason: {
Translations: [
{
XmlLang: "en-US",
Text: "Hubo errores en la validación de los parámetros de la operación."
}
]
},
Data: { },
InnerException: null,
TargetSite: {
Name: "HandleReply",
DeclaringType: "System.ServiceModel.Channels.ServiceChannel, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
ReflectedType: "System.ServiceModel.Channels.ServiceChannel, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
MemberType: 8,
MetadataToken: 100671507,
Module: {
MDStreamVersion: 131072,
FullyQualifiedName: "C:\Users\rotha\.nuget\packages\system.private.servicemodel\4.5.3\runtimes\win\lib\netstandard2.0\System.Private.ServiceModel.dll",
ModuleVersionId: "c5851175-5eba-412a-8f03-6cd647a2a897",
MetadataToken: 1,
ScopeName: "System.Private.ServiceModel.dll",
Name: "System.Private.ServiceModel.dll",
Assembly: {
CodeBase: "file:///C:/Users/xxx/.nuget/packages/system.private.servicemodel/4.5.3/runtimes/win/lib/netstandard2.0/System.Private.ServiceModel.dll",
FullName: "System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
EntryPoint: null,
DefinedTypes: [
"FxResources.System.Private.ServiceModel.SR, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.NotImplemented, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.__HResults, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.FxTrace, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.SR, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Xml.XmlBinaryNodeType, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Collections.Generic.KeyedByTypeCollection`1, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Collections.Generic.SynchronizedCollection`1, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Collections.Generic.SynchronizedKeyedCollection`2, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
"System.Collections.Generic.SynchronizedReadOnlyCollection`1, System.Private.ServiceModel, Version=4.5.0.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
..........

этот список определенных типов, как миллион элементов ...: (

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Это должно быть исправлено в Выпуск 12.0.1 Json.NET:

Изменение - исключенный TargetSite при сериализации исключений без SerializableAttribute

Исправление было сделано в коммите Исключить TargetSite из несериализуемой сериализации исключений (# 1897) 27 октября 2018 года.

Кажется, проблема возникла в Json.NET 11.0 Release 1 :

Изменение - типы, которые реализуют ISerializable, но не имеют [SerializableAttribute], не сериализуются с использованием ISerializable

Для обсуждения того, почему изначально было сделано изменение в 11.0.1, см. этот ответ до Десериализация пользовательских исключений в Newtonsoft.Json .

0 голосов
/ 04 октября 2018

Нет необходимости писать его, используя любой писатель, просто используйте context.Result:

public class ApiExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        var ex = context.Exception;
        if (ex == null) return;

        context.Result = new JsonResult(ex);
    }
}
...