C# 忽略Web Api中的空属性/值,并在自身主机中使用OData响应
我希望在自主机启动中使用OData响应省略Web Api中的Null属性/值,以减小内容大小 我有112个控制器继承自一个抽象的ApiController类,因此使用了CustomDirectRouteProvider。(不重要) 我运行的是Framework4.8,而不是CORE 我需要帮助实现一个类似的解决方案 我已经阅读了几乎所有关于这个主题的帖子,“Stas Natalenko”解决方案对于OData v3和更老的版本似乎很好,但我不确定如何在self-host上实现OData v4的“Chris Schaller”解决方案 这是我的创业课程:C# 忽略Web Api中的空属性/值,并在自身主机中使用OData响应,c#,.net,asp.net-web-api,odata,owin,C#,.net,Asp.net Web Api,Odata,Owin,我希望在自主机启动中使用OData响应省略Web Api中的Null属性/值,以减小内容大小 我有112个控制器继承自一个抽象的ApiController类,因此使用了CustomDirectRouteProvider。(不重要) 我运行的是Framework4.8,而不是CORE 我需要帮助实现一个类似的解决方案 我已经阅读了几乎所有关于这个主题的帖子,“Stas Natalenko”解决方案对于OData v3和更老的版本似乎很好,但我不确定如何在self-host上实现OData v4的“
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);
};
}
}
公共类CustomDirectRouteProvider:DefaultDirectRouteProvider
{
受保护的覆盖System.Collections.Generic.IReadOnlyList
GetActionRouteFactorys(HttpActionDescriptor actionDescriptor)
{
//继承基类控制器动作上修饰的路由属性
返回actionDescriptor.GetCustomAttributes
(继承:正确);
}
}
公营创业
{
公共静态无效配置(IAppBuilder appBuilder)
{
使用(var config=new HttpConfiguration())
{
config.EnableSwagger(c=>c.SingleApiVersion(“v1”、“MyAPI”))
.EnableSwaggerUi();
config.maphttpAttribute路由(新的CustomDirectRouteProvider());
config.EnableCors();
config.Routes.MapHttpRoute(
名称:“DefaultApi”,
routeTemplate:“{controller}/{id}”,
默认值:新建{id=RouteParameter.Optional}
);
config.AddODataQueryFilter();
config.Formatters.Clear();
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null)
.EnableDependencyInjection();
config.Formatters.Add(新的System.Net.Http.Formatting.JsonMediaTypeFormatter
{
UseDataContractJsonSerializer=false,
SerializerSettings=新JsonSerializerSettings
{
ContractResolver=new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
ReferenceLoopHandling=ReferenceLoopHandling.Ignore,
DateFormatHandling=DateFormatHandling.IsoDateFormat,
DateParseHandling=DateParseHandling.DateTimeOffset,
DateTimeZoneHandling=DateTimeZoneHandling.RoundtripKind,
格式化=格式化。无,
NullValueHandling=NullValueHandling.Ignore
}
});
config.Formatters.Add(新的System.Net.Http.Formatting.BsonMediaTypeFormatter());
appBuilder.UseWebApi(配置);
};
}
}
经过两个晚上的讨论,我想我已经找到了一个可能的解决方案,但是,资源已经找到了您提到的答案,就我个人而言,依赖注入的一部分注册序列化程序是最困难的,但我必须承认这个问题,它很有帮助:
最后,我分享解决方案可以代表什么:
按照创建项目的Microsoft文档:
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);
}
}
最后,Api的输出:
输入:
公共静态列表项=新列表()
{
新项目{Id=1,Name=“name1”,OptionalField=“Value Present”},
新项目{Id=3,Name=“name2”}
};
并具有以下价值:
输入:
公共静态列表项=新列表()
{
新项目{Id=1,Name=“name1”,OptionalField=“Value Present”},
新项目{Id=3,Name=“name2”,OptionalField=“Value Present2”}
};
我希望这能有所帮助。这是我有生以来第一个关于StackOverFlow的问题。这些年来,我一直很干净,你使用的是什么版本的Microsoft.AspNet.WebApi.OData(Nuget)?也许还有很长的路要走,但是这些设置有可能在MvcJsonOptions中被覆盖吗?builder.Services.Configure(opts=>opts.SerializerSettings.NullValueHandling…@Julián最新稳定版本7+不使用MVC,只有WebApi。要使其正常工作,必须使用“app.UseMVC”或者其他什么,然后从mvc控制器而不是api控制器继承。我将您的答案标记为已接受的答案,尽管我尚未测试。手动授予奖金为时已晚,但我认为它可能会在几天内自动分配…在我的情况下不起作用,ODataController不断返回406我将尝试剥离所有内容让一切尽可能简单,顺便说一句,你没有使用OWIN Self host,但你确实给了我一些很好的见解。
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();
}
}
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" }
};