使用 OData 响应 Owin Self-Host 忽略 Web Api 中的 Null 属性/值
Posted
技术标签:
【中文标题】使用 OData 响应 Owin Self-Host 忽略 Web Api 中的 Null 属性/值【英文标题】:Ignore Null properties/values in Web Api with OData response Owin Self-Host 【发布时间】:2021-01-20 14:40:56 【问题描述】:我想通过 OData 响应 Owin Self-Host Startup 省略 Web Api 中的 Null 属性/值,以减少内容大小。
我有 112 个控制器从单个抽象 ApiController 类继承,因此使用 CustomDirectRouteProvider。 (不重要)
我正在运行 Framework 4.8,而不是 CORE。
我需要帮助实施与 How to Ignore Null values while serializing OData response 类似的解决方案
我已经阅读了几乎所有关于该主题的帖子,“Stas Natalenko”解决方案似乎适用于 OData v3 及更早版本,但我不确定如何在自托管上为 Odata v4 实施“Chris Schaller”解决方案。
这是我的启动课:
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);
;
【问题讨论】:
这是我人生中关于 *** 的第一个问题。这些年来我一直很干净facepalm 你使用什么版本的Microsoft.AspNet.WebApi.OData
(Nuget)?
也许是一个长镜头,但是这些设置是否可以在 MvcJsonOptions 中被覆盖? builder.Services.Configure在处理了两个晚上的可能答案之后,我想我找到了一个可能的解决方案,但是,资源有你提到的答案,个人 依赖注入 注册序列化程序的部分是最多的困难,但我必须感谢这个问题,它很有帮助:How to register an OData Serializer Provider with AspNet.OData v6
最后我分享一个解决方案可以代表什么:
按照 Microsoft 文档 创建项目:
https://docs.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint
1. 使用 WebApi 模板创建一个 ASP .NET 4.7.2 项目
2. 在其版本7.5.0
中使用Microsoft.AspNet.OData
包:
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. 在 Models 中,我将解决方案复制到您正在回答的问题就足够了(将 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"
;
我希望这会有所帮助。
【讨论】:
我将您的答案标记为已接受的答案,即使我尚未对其进行测试。手动奖励赏金为时已晚,但我认为它可能会在几天后自动分配...... 在我的情况下不起作用,ODataController 一直返回 406 我会再试一次,把所有东西都去掉,把所有东西都降到最低限度,顺便说一句,你没有使用 OWIN 自托管,但你确实给了我一些很好的见解。 直到今天,我一直困扰着你没有及时得到你的赏金。朱利安总有一天我会补偿你的! 放松,没问题的兄弟:)以上是关于使用 OData 响应 Owin Self-Host 忽略 Web Api 中的 Null 属性/值的主要内容,如果未能解决你的问题,请参考以下文章
我们可以使用OData客户端为syncfusion网格创建我们的请求但是使用正常响应(Reqular WebAPI)
如何使用命令(API)和查询(odata)控制器将位置标头传递给响应