У меня есть приложение .NET Core Web Api 2.1, в котором я сериализую только свойства, запрошенные клиентом.
Пример: GET orders/1?select=Id,TotalAmount
Пример: GET orders/1?select=Id,CustomerName,DeliveryAddress,Location,ZipCode
Для этого приложение создает объект в каждом запросе (Lifetime Scoped) для получения запрошенных свойств.
Затем я создал пользовательский класс ContractResolver
, который создается в каждом запросе глобальным IResultFilter
:
public class SerializationFilter : IResultFilter
{
private readonly IApiQueryParameters _apiQueryParameters;
public SerializationFilter(IApiQueryParameters apiQueryParameters)
{
this._apiQueryParameters = apiQueryParameters;
}
public void OnResultExecuting(ResultExecutingContext context)
{
var objectResult = context.Result as ObjectResult;
if (objectResult != null)
{
var contractResolver = new SelectiveResourceContractResolver(this._apiQueryParameters);
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = contractResolver
};
var jsonFormatter = new JsonOutputFormatter(
serializerSettings,
ArrayPool<char>.Shared);
objectResult.Formatters.Add(jsonFormatter);
}
}
}
Теперь это работает для первого запроса, сделанного после подключения приложения к сети.,Второй запрос создает ContractResolver правильно, но ответ не является правильным.Возвращенные сериализованные свойства не являются запрошенными клиентом.
Отладка кода, я заметил, что когда создается SelectiveResourceContractResolver, он обращается к методу конструктора вправо,
public SelectiveResourceContractResolver(IApiQueryParameters apiQueryParameters)
{
this._apiQueryParameters = apiQueryParameters;
}
Также,он запускает метод переопределения CreateProperty:
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
Но во втором запросе CreatePropertyMethod
не запускается.
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize =
instance =>
{
...
};
return property;
}
Во второй раз, он просто выполняет property.ShouldSerialize = instance =>
часть.Я думаю, что какое-то кэширование выполняется приложением, но более странным является то, что ContractResolver создается при каждом запросе (он не устанавливается глобально в Startup.cs) при выполнении фильтра.Кроме того, когда я отлаживаю его во втором запросе, свойство IApiQueryParameters в ContractResolver имеет все значения первого запроса, а не второго выполнения конструктора.
Чего мне здесь не хватает?