Как получить независимое разрешение ссылок JSON между запросами в ASP.NET Core? - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь добавить пользовательскую реализацию IReferenceResolver в приложение ASP.NET Core 2.2 MVC API, чтобы уменьшить объем данных в полезной нагрузке JSON.Однако эталонные разрешения распределяются между различными запросами.

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

Это мой метод ConfigureServices в Startup.cs :

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddJsonOptions(opts =>
                {
                    opts.SerializerSettings.ReferenceResolverProvider = () => new ThingReferenceResolver();
                });
        }

Это моя реализация контроллера вместе с моим пользовательским IReferenceResolver

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet("")]
        public ActionResult<ThingsResponse> Get()
        {
            return new ThingsResponse
            {
                MainThing = new Thing { Id = "foo" },

                Things = new List<Thing>
                {
                    new Thing { Id = "foo" },
                    new Thing { Id = "bar" }
                }
            };
        }
    }

    public class ThingsResponse
    {
        [JsonProperty(IsReference = true)]
        public Thing MainThing { get; set; }

        [JsonProperty(ItemIsReference = true)]
        public List<Thing> Things { get; set; }
    }

    public class Thing
    {
        public string Id { get; set; }
    }

    public class ThingReferenceResolver : IReferenceResolver
    {
        private readonly IDictionary<string, Thing> _idReference = new Dictionary<string, Thing>();

        public void AddReference(object context, string reference, object value)
        {
            _idReference[reference] = (Thing)value;
        }

        public string GetReference(object context, object value)
        {
            var thing = (Thing)value;

            _idReference[thing.Id] = thing;

            return thing.Id.ToString();
        }

        public bool IsReferenced(object context, object value)
        {
            var thing = (Thing)value;

            return _idReference.ContainsKey(thing.Id);
        }

        public object ResolveReference(object context, string reference)
        {
            _idReference.TryGetValue(reference, out Thing thing);

            return thing;
        }
    }

На мой первый запрос я получаю следующий ответ:

{
  "mainThing": {
    "$id": "foo",
    "id": "foo"
  },
  "things": [
    {
      "$ref": "foo"
    },
    {
      "$id": "bar",
      "id": "bar"
    }
  ]
}

На мой второй запрос я получаю следующий ответ:

{
  "mainThing": {
    "$ref": "foo"
  },
  "things": [
    {
      "$ref": "foo"
    },
    {
      "$ref": "bar"
    }
  ]
}

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

Ответы [ 2 ]

1 голос
/ 21 марта 2019

Вы получаете разные результаты для второго запроса, потому что MVC создает один сериализатор и кэширует его, который затем кэширует ссылки, если у вас есть отслеживание ссылок, как у вас.

Я думаю, если вы вернете JsonResult с новым сериализаторомнастройки в каждом результате, то у вас не будет этой проблемы:

new JsonResult (yourData, new JsonSerializerSettings {...})

0 голосов
/ 21 марта 2019

Один из предложенных мной вариантов - обойти настройку сериализатора JSON, который предоставляет MVC, и создать свой собственный для рассматриваемого запроса.

        [HttpGet("")]
        public ActionResult<ThingsResponse> Get()
        {
            var serializerSettings = JsonSerializerSettingsProvider.CreateSerializerSettings();

            serializerSettings.ReferenceResolverProvider = () => new ThingReferenceResolver();

            return new JsonResult(
                new ThingsResponse
                {
                    MainThing = new Thing { Id = "foo" },

                    Things = new List<Thing>
                    {
                        new Thing { Id = "foo" },
                        new Thing { Id = "bar" }
                    }
                },

                serializerSettings
            );
        }

В моем конкретном сценарии это нормально, потому что яне так много конечных точек, для которых это необходимо было бы настроить.

Это означает, что следующий код из примера Startup.cs не нужен для решения моей проблемы (как я определяю для каждого запроса)

                .AddJsonOptions(opts =>
                {
                    opts.SerializerSettings.ReferenceResolverProvider = () => new ThingReferenceResolver();
                });

Я думаю, что я остановлюсь на этом варианте для моих обстоятельств, но хотел бы знать, если есть лучшие способы его реализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...