使用 OData 响应 Owin Self-Host 忽略 Web Api 中的 Null properties/values
Ignore Null properties/values in Web Api with OData response Owin Self-Host
我想在 Web Api 中使用 OData 响应 Owin Self-Host Startup 省略 Null properties/values,以减少内容大小。
我有 112 个控制器继承自单个抽象 Api控制器 class,因此使用 CustomDirectRouteProvider。 (不重要)
我是 运行 Framework 4.8,不是核心。
我需要帮助实施与 How to Ignore Null values while serializing OData response
类似的解决方案
我已经阅读了几乎所有关于该主题的帖子,'Stas Natalenko' 解决方案似乎适用于 OData v3 及更早版本,但我不确定如何为 Odata v4 实施 'Chris Schaller' 解决方案自托管。
这是我的启动 class:
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
protected override System.Collections.Generic.IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
// inherit route attributes decorated on base class controller's actions
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
(inherit: true);
}
}
public class Startup
{
public static void Configuration(IAppBuilder appBuilder)
{
using (var config = new HttpConfiguration())
{
config.EnableSwagger(c => c.SingleApiVersion("v1", "MyAPI"))
.EnableSwaggerUi();
config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.AddODataQueryFilter();
config.Formatters.Clear();
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null)
.EnableDependencyInjection();
config.Formatters.Add(new System.Net.Http.Formatting.JsonMediaTypeFormatter
{
UseDataContractJsonSerializer = false,
SerializerSettings = new JsonSerializerSettings
{
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = DateParseHandling.DateTimeOffset,
DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind,
Formatting = Formatting.None,
NullValueHandling = NullValueHandling.Ignore
}
});
config.Formatters.Add(new System.Net.Http.Formatting.BsonMediaTypeFormatter());
appBuilder.UseWebApi(config);
};
}
}
在处理了两个晚上可能的答案后我想我找到了一个可能的解决方案,但是,资源有你提到的答案,个人 Dependency Injection 的部分要注册序列化程序是最困难的,但我必须感谢这个问题,它很有帮助:How to register an OData Serializer Provider with AspNet.OData v6
最后我分享一个解决方案可以代表什么:
按照 Microsoft 文档 创建项目:
1. 使用 Web[= 创建了一个 ASP .NET 4.7.2 项目85=]模板
2. 使用 Microsoft.AspNet.OData
包的版本 7.5.0
:
3.控制器是这样的:
public class ItemsController : ODataController
{
public static List<Item> items = new List<Item>()
{
new Item { Id = 1, Name = "name1", OptionalField = "Value Present" },
new Item { Id = 3, Name = "name2" }
};
[EnableQuery]
public IQueryable<Item> Get()
{
return items.AsQueryable();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
根据文档,此版本的 OData
继承自 ODataController
,而 [Queryable]
代表过时标记,这就是我使用 [EnableQuery]
的原因
4. 在模型中,复制您正在回答的问题的解决方案就足够了(复制并粘贴 IngoreNullEntityPropertiesSerializerProvider
和 IngoreNullEntityPropertiesSerializer
类 在新文件夹中:
最困难的部分是在 WebApiConfig.cs
中配置序列化程序:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Configuración y servicios de API web
// Rutas de API web
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MapODataServiceRoute("ODataRoute", null, b => b
.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(IEdmModel), s => GetEdmModel())
.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(IEnumerable<IODataRoutingConvention>), s => ODataRoutingConventions.CreateDefaultWithAttributeRouting("ODataRoute", config))
.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(ODataSerializerProvider), sp => new IngoreNullEntityPropertiesSerializerProvider(sp))
);
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Item>("Items");
return builder.GetEdmModel();
}
}
最后Api的输出:
输入:
public static List<Item> items = new List<Item>()
{
new Item { Id = 1, Name = "name1", OptionalField = "Value Present" },
new Item { Id = 3, Name = "name2" }
};
并具有值:
输入:
public static List<Item> items = new List<Item>()
{
new Item { Id = 1, Name = "name1", OptionalField = "Value Present" },
new Item { Id = 3, Name = "name2", OptionalField = "Value Present2" }
};
希望对您有所帮助。
我想在 Web Api 中使用 OData 响应 Owin Self-Host Startup 省略 Null properties/values,以减少内容大小。
我有 112 个控制器继承自单个抽象 Api控制器 class,因此使用 CustomDirectRouteProvider。 (不重要)
我是 运行 Framework 4.8,不是核心。
我需要帮助实施与 How to Ignore Null values while serializing OData response
类似的解决方案我已经阅读了几乎所有关于该主题的帖子,'Stas Natalenko' 解决方案似乎适用于 OData v3 及更早版本,但我不确定如何为 Odata v4 实施 'Chris Schaller' 解决方案自托管。
这是我的启动 class:
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
protected override System.Collections.Generic.IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
// inherit route attributes decorated on base class controller's actions
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
(inherit: true);
}
}
public class Startup
{
public static void Configuration(IAppBuilder appBuilder)
{
using (var config = new HttpConfiguration())
{
config.EnableSwagger(c => c.SingleApiVersion("v1", "MyAPI"))
.EnableSwaggerUi();
config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.AddODataQueryFilter();
config.Formatters.Clear();
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null)
.EnableDependencyInjection();
config.Formatters.Add(new System.Net.Http.Formatting.JsonMediaTypeFormatter
{
UseDataContractJsonSerializer = false,
SerializerSettings = new JsonSerializerSettings
{
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
DateParseHandling = DateParseHandling.DateTimeOffset,
DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind,
Formatting = Formatting.None,
NullValueHandling = NullValueHandling.Ignore
}
});
config.Formatters.Add(new System.Net.Http.Formatting.BsonMediaTypeFormatter());
appBuilder.UseWebApi(config);
};
}
}
在处理了两个晚上可能的答案后我想我找到了一个可能的解决方案,但是,资源有你提到的答案,个人 Dependency Injection 的部分要注册序列化程序是最困难的,但我必须感谢这个问题,它很有帮助:How to register an OData Serializer Provider with AspNet.OData v6
最后我分享一个解决方案可以代表什么:
按照 Microsoft 文档 创建项目:
1. 使用 Web[= 创建了一个 ASP .NET 4.7.2 项目85=]模板
2. 使用 Microsoft.AspNet.OData
包的版本 7.5.0
:
3.控制器是这样的:
public class ItemsController : ODataController
{
public static List<Item> items = new List<Item>()
{
new Item { Id = 1, Name = "name1", OptionalField = "Value Present" },
new Item { Id = 3, Name = "name2" }
};
[EnableQuery]
public IQueryable<Item> Get()
{
return items.AsQueryable();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
根据文档,此版本的 OData
继承自 ODataController
,而 [Queryable]
代表过时标记,这就是我使用 [EnableQuery]
4. 在模型中,复制您正在回答的问题的解决方案就足够了(复制并粘贴 IngoreNullEntityPropertiesSerializerProvider
和 IngoreNullEntityPropertiesSerializer
类 在新文件夹中:
最困难的部分是在 WebApiConfig.cs
中配置序列化程序:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Configuración y servicios de API web
// Rutas de API web
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MapODataServiceRoute("ODataRoute", null, b => b
.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(IEdmModel), s => GetEdmModel())
.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(IEnumerable<IODataRoutingConvention>), s => ODataRoutingConventions.CreateDefaultWithAttributeRouting("ODataRoute", config))
.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(ODataSerializerProvider), sp => new IngoreNullEntityPropertiesSerializerProvider(sp))
);
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Item>("Items");
return builder.GetEdmModel();
}
}
最后Api的输出:
输入:
public static List<Item> items = new List<Item>()
{
new Item { Id = 1, Name = "name1", OptionalField = "Value Present" },
new Item { Id = 3, Name = "name2" }
};
并具有值:
输入:
public static List<Item> items = new List<Item>()
{
new Item { Id = 1, Name = "name1", OptionalField = "Value Present" },
new Item { Id = 3, Name = "name2", OptionalField = "Value Present2" }
};
希望对您有所帮助。