如何在ASP.NET Core中的请求之间获得独立的JSON参考分辨率



我正在尝试将自定义的iReferenCeresolver实现添加到ASP.NET Core 2.2 MVC API应用程序中,以减少JSON有效负载中的数据。但是,参考分辨率正在不同请求之间共享。

看来,在请求之间共享了参考文献的单个实例。我希望参考可以独立于其他请求解决,因为我的不同用户没有此共享参考上下文。

这是我的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"
    }
  ]
}

我希望我的第二个请求看起来像我的第一个请求,即可重复的输出。

您会为第二个请求获得不同的结果,因为MVC会创建一个序列化器并缓存它,然后如果您像这样的参考跟踪,则可以缓存引用。

我认为,如果您在每个结果中返回带有新的序列化器设置的JSONRESULT,那么您将不会遇到此问题:

new jsonresult(YourData,new JSonserializertings {...})

我想出的一个选项是绕过配置MVC提供的JSON Serialializer并为所涉及的请求创建我自己的。

        [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 is 不需要以下代码解决我的问题(因为我根据请求定义它)

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

我认为我会为自己的情况解决这个选择,但很想知道是否有更好的方法来实施它。

相关内容

  • 没有找到相关文章

最新更新