Итак, я создаю сервис, который должен использоваться через OData, и мне очень трудно понять, как добавить в него собственные средства форматирования. Мне нужен мой сериализатор OData, чтобы игнорировать нулевые значения при сериализации данных. Я создал эти 2 для достижения этого:
public class SmartODataSerializerProvider : DefaultODataSerializerProvider
{
private readonly SmartODataEntityTypeSerializer _entityTypeSerializer;
public SmartODataSerializerProvider(IServiceProvider rootContainer)
: base(rootContainer)
{
_entityTypeSerializer = new SmartODataEntityTypeSerializer(this);
}
public override ODataEdmTypeSerializer GetEdmTypeSerializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
{
// Support for Entity types AND Complex types
if (edmType.Definition.TypeKind == EdmTypeKind.Entity || edmType.Definition.TypeKind == EdmTypeKind.Complex)
return _entityTypeSerializer;
else
return base.GetEdmTypeSerializer(edmType);
}
}
И
public class SmartODataEntityTypeSerializer : ODataResourceSerializer
{
public SmartODataEntityTypeSerializer(ODataSerializerProvider provider)
: base(provider) { }
/// <summary>
/// Only return properties that are not null
/// </summary>
/// <param name="structuralProperty">The EDM structural property being written.</param>
/// <param name="resourceContext">The context for the entity instance being written.</param>
/// <returns>The property be written by the serilizer, a null response will effectively skip this property.</returns>
public override Microsoft.OData.ODataProperty CreateStructuralProperty(Microsoft.OData.Edm.IEdmStructuralProperty structuralProperty, ResourceContext resourceContext)
{
var property = base.CreateStructuralProperty(structuralProperty, resourceContext);
return property.Value != null ? property : null;
}
}
Они были предоставлены в другом вопросе переполнения стека. Однако проблема возникает, когда я пытаюсь использовать этот сериализатор. У меня уже есть конечная точка odata, которая работает (она просто сериализует все с нулем), и когда я применяю к ней следующую конфигурацию, я продолжаю получать «404 Not Found» на том же EP, который работает без него.
app.UseEndpoints(endpoints =>
{
endpoints.MapODataRoute("odata", "odata", a =>
{
a.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(IEdmModel), sp => GetEdmModel(app.ApplicationServices));
a.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(ODataSerializerProvider), sp => new SmartODataSerializerProvider(sp));
});
endpoints.EnableDependencyInjection();
//endpoints.MapODataRoute("odata", "odata", GetEdmModel(app.ApplicationServices));
endpoints.MapControllers();
});
Это настройки конечных точек. Я закомментировал строку, которая заставляет его работать, но без пользовательских форматеров. Вот функция IEdmModel, используемая в настройке:
private static IEdmModel GetEdmModel(IServiceProvider services)
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder(services);
builder.Namespace = "RS";
builder.EntitySet<PropertyIndexODataModel>("Properties");
builder.EntitySet<ReportResultModel>("Reports");
var function = builder.EntityType<ReportResultModel>().Collection.Function("Generate");
function.Parameter<int>("listId");
function.CollectionParameter<string>("functionsToRun");
function.ReturnsCollectionFromEntitySet<ReportResultModel>("Reports");
return builder.GetEdmModel();
}
Поэтому, когда я применяю этот odataroute, я продолжаю получать 404. Когда я удаляю его и go возвращается к 'endpoints.MapODataRoute ("odata", " odata ", GetEdmModel (app.ApplicationServices)); ' это работает без проблем.
Это кажется очень тривиальной вещью, но я искал везде и все еще не мог заставить ее работать. Я использую OData 7.4 и netcore 3.1. Заранее спасибо!