ASP.NET Core OData 9 正式发布

news/2024/10/9 12:06:53/文章来源:https://www.cnblogs.com/yswenli/p/18453938

我们很高兴地宣布,ASP.NET Core OData 9 已正式发布,并在 NuGet 上提供:

  • Microsoft.AspNetCore.OData 9.0.0

此版本的主要亮点是将 OData .NET 依赖项更新到 8.x 主版本。 通过更新依赖项,我们能够利用 Microsoft.OData.Core 8.x 和 Microsoft.OData.Edm 8.x 版本中引入的改进和新功能。

ASP.NET Core OData 9 版本将仅支持 .NET 8 或更高版本。

OData .NET 8 官方发布公告解决了该版本中引入的主要更改。建议阅读这篇文章以熟悉这些变化。

在本文中,我们将探讨其中一些更改如何影响 ASP.NET Core OData 库,以及如何在可能的情况下切换旧行为。

请求和响应负载中的字符编码

在 OData .NET 8 中,我们引入了一个新的 JSON 编写器,它在后台使用 .NET Utf8JsonWriter 来编写请求和响应有效负载。新的 JSON 编写器速度明显更快,并且是 ASP.NET Core OData 9 中的默认编写器。

您可能会观察到输出负载上的字符编码存在差异。我们将在以下各节中介绍这些差异。

编码的字符子集

在其默认配置中,新的 JSON 编写器不会像旧版 (OData .NET 7) 那样对大量字符进行编码。

默认情况下,旧版 JSON 编写器对所有整数值小于 32 且大于 127 的字符进行编码,基本上都是非 ASCII 字符。这计算出大约 65440 个字符!可以通过将 option 传递给默认的 JSON 编写器工厂构造函数来覆盖旧版 JSON 编写器的默认配置。使用这种替代配置,将对大大减少的字符子集进行编码。ODataStringEscapeOption.EscapeOnlyControls

新的 JSON 编写器使用默认情况下配置了 encoder 选项的基础。编码的结果字符集要小得多。Utf8JsonWriterJavaScriptEncoder.UnsafeRelaxedJsonEscaping

下面是一个插图 – 以 OData 服务的代码示例形式,演示了使用新的 JSON 编写器时输出有效负载的外观:

// Model
namespace Ver900Sample.Models
{public class Order{public int Id { get; set; }public decimal Amount { get; set; }public string Note { get; set; }}
}// Controller
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Results;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using Ver900Sample.Models;namespace Ver900Sample.Controllers
{public class OrdersController : ODataController{private static readonly List<Order> orders = new List<Order>{new Order { Id = 1, Amount = 130m, Note = "a - z, α - Ω" },new Order { Id = 2, Amount = 170.50m, Note = "😀 🐂 🐕" }};[EnableQuery]public SingleResult<Order> Get(int key){return SingleResult.Create(orders.AsQueryable().Where(d => d.Id == key));}}
}// Service configuration
using Ver900Sample.Models;
using Microsoft.AspNetCore.OData;
using Microsoft.OData.ModelBuilder;var builder = WebApplication.CreateBuilder(args);var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Order>("Orders");builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(model: modelBuilder.GetEdmModel()));var app = builder.Build();app.UseRouting();
app.MapControllers();app.Run();

您可以使用该工具查询此服务的订单 1 – 浏览器可能不是此图的好选择,因为它会智能解码编码的字符。curl

curl http://localhost:5090/Orders(1)

注意:5090 是计算机分配的随机端口,因计算机而异。

以下是您将观察到的结果:

{"@odata.context": "http://localhost:5090/$metadata#Orders/$entity","Id": 1,"Amount": 130,"Note": "a - z, α - Ω"
}

在上述情况下,新的 JSON 编写器不会对 和非 ASCII 字符进行编码。αΩ

如果在您的方案中保留旧版 JSON 编写器的行为很重要,则可以通过使用依赖项注入将新的 JSON 编写器替换为旧版 JSON 编写器来实现此目的。您可以通过修改上述代码片段中的方法调用来执行此操作,如下所示:AddOData

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddScoped<Microsoft.OData.Json.IJsonWriterFactory>(sp => new Microsoft.OData.Json.ODataJsonWriterFactory());}));

注意:该类是以前在 OData .NET 7 中命名的类。我们认为名称中包含“Default”会使歧义永久存在,因为它不是 OData .NET 8 中的默认 JSON 编写器工厂。ODataJsonWriterFactoryDefaultJsonWriterFactory

如果您在上述更改后查询订单 1,响应有效负载将如下所示:

{"@odata.context": "http://localhost:5090/$metadata#Orders/$entity","Id": 1,"Amount": 130,"Note": "a - z, \u03b1 - \u03a9"
}

在上述情况下,将对非 ASCII 字符进行编码。

还支持更严格的 JavaScript 编码器。您可以配置您的服务以使用该编码器,如下所示:Utf8JsonWriter

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddScoped<Microsoft.OData.Json.IJsonWriterFactory>(sp => new Microsoft.OData.Json.ODataUtf8JsonWriterFactory(System.Text.Encodings.Web.JavaScriptEncoder.Default));}));

如果您在上述更改后查询订单 1,响应有效负载将如下所示:

{"@odata.context": "http://localhost:5090/$metadata#Orders/$entity","Id": 1,"Amount": 130,"Note": "a - z, \u03B1 - \u03A9"
}

上述响应有效负载看起来类似于旧版 JSON 编写器的输出。

但是,请务必注意,使用更严格的 JavaScript 编码器配置的编码器并不是旧版 JSON 编写器在编码字符方面的镜像。Utf8JsonWriter

要关闭循环,下面介绍如何将服务配置为使用具有不太严格编码选项的旧版 JSON 编写器:

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddScoped<Microsoft.OData.Json.IJsonWriterFactory>(sp => new Microsoft.OData.Json.ODataJsonWriterFactory(Microsoft.OData.Json.ODataStringEscapeOption.EscapeOnlyControls));}));

选择配置选项是因为它是 ASP.NET Core 8.0 中配置的默认选项。JavaScriptEncoder.UnsafeRelaxedJsonEscaping

Unicode 码位的大写字母

新的 JSON 编写器在编码输出中使用大写字母,而旧版 JSON 编写器使用小写字母。这两个输出都是合法的,客户端反序列化任何一种格式都应该没有问题。

使用上一节中的示例服务并配置了新的 JSON 编写器,您可以按如下方式查询订单 2:

curl http://localhost:5090/Orders(2)

以下是您将观察到的结果:

{"@odata.context": "http://localhost:5090/$metadata#Orders/$entity","Id": 2,"Amount": 170.50,"Note": "\uD83D\uDE00 \uD83D\uDC02 \uD83D\uDC15"
}

请注意,Unicode 字符的编码值为大写。

如果您在配置了旧版 JSON 编写器的情况下查询相同的顺序 2,则响应有效负载如下所示:

{"@odata.context": "http://localhost:5090/$metadata#Orders/$entity","Id": 2,"Amount": 170.50,"Note": "\ud83d\ude00 \ud83d\udc02 \ud83d\udc15"
}

如果所描述的字符编码更改在您的方案中是一个交易破坏者,请将新的 JSON 编写器替换为旧版 JSON 编写器,如图所示。

对依赖项注入的更改

我们进行了重大更改,以适应 OData .NET 8 中的依赖关系注入重构。我们摆脱了非标准的依赖注入工件(例如),转而使用 .NET 框架依赖注入抽象。IContainerBuilder

具体而言,对 OData 核心库中方法的更改使配置 、 和如下所示成为可能:AddODataDefaultServicesODataReaderSettingsODataMessageWriterSettingsODataUriParserSettings

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddDefaultODataServices(odataVersion: Microsoft.OData.ODataVersion.V4,configureReaderAction: (messageReaderSettings) =>{// Relevant changes to the ODataMessageReaderSettings instance here},configureWriterAction: (messageWriterSettings) =>{// Relevant changes to the ODataMessageWriterSettings instance here},configureUriParserAction: (uriParserSettings) =>{// // Relevant changes to the ODataUriParserSettings instance here});}));

这为开发人员在操作这些特定设置时提供了更大的灵活性。

该参数还使注入任何所需的依赖项变得简单明了:IServiceCollection

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddSingleton<Microsoft.OData.ODataPayloadValueConverter>(sp => new CustomODataPayloadValueConverter());}));// ...public class CustomODataPayloadValueConverter : Microsoft.OData.ODataPayloadValueConverter
{public override object ConvertToPayloadValue(object value, IEdmTypeReference edmTypeReference){if (edmTypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.DateTimeOffset){var dateTimeOffset = (DateTimeOffset)value;return dateTimeOffset.ToString("yyyy-MM-dd'T'HH:mm:ss.fffffffzzz");}return base.ConvertToPayloadValue(value, edmTypeReference);}
}

向后兼容性标志

OData .NET 8 的一个主要目标是确保迁移到新版本的客户能够输出与在 OData .NET 7 中相同的响应负载。在进行更改以更好地与 OData 标准保持一致的地方,添加了兼容性标志,以便能够切换旧行为。

我们为与 OData 标准保持一致而进行的更改的一个示例是,在服务元数据负载中编写十进制属性的属性,以及为空间属性编写属性。ScaleSRID

如果您查询上一节中示例服务的服务元数据终端节点 (http://localhost:5090/$metadata),您将获得以下有效负载:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"><edmx:DataServices><Schema Namespace="Ver900Sample.Models" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityType Name="Order"><Key><PropertyRef Name="Id" /></Key><Property Name="Id" Type="Edm.Int32" Nullable="false" /><Property Name="Amount" Type="Edm.Decimal" Nullable="false" Scale="variable" /><Property Name="Note" Type="Edm.String" Nullable="false" /></EntityType></Schema><Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm"><EntityContainer Name="Container"><EntitySet Name="Orders" EntityType="Ver900Sample.Models.Order" /></EntityContainer></Schema></edmx:DataServices>
</edmx:Edmx>

在 OData .NET 7 中,该属性将写为 – 带有大写的“V”。与 OData 标准的这种偏差在 OData .NET 8 中已修复。该属性现在写入 ,如上面的有效负载所示。ScaleScale="Variable"Scale Scale="variable"

如果在您的方案中维护 OData .NET 7 行为很重要,您可以通过切换功能标志来实现这一点,如下所示:

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddDefaultODataServices(odataVersion: Microsoft.OData.ODataVersion.V4,configureReaderAction: null,configureWriterAction: (messageWriterSettings) =>{messageWriterSettings.LibraryCompatibility |= Microsoft.OData.ODataLibraryCompatibility.UseLegacyVariableCasing;},configureUriParserAction: null);}));

切换标志后,将写入该属性,以便与 OData .NET 7 兼容。ODataLibraryCompability.UseLegacyVariableCasingScaleScale="Variable"

您可以根据需要组合任意数量的兼容性标志来实现所需的行为。

若要切换所有兼容性标志以实现 OData .NET 7 兼容性,可以使用方便的标志,如下所示:ODataLibraryCompatibility.Version7

builder.Services.AddControllers().AddOData(options => options.EnableQueryFeatures().AddRouteComponents(routePrefix: string.Empty,model: modelBuilder.GetEdmModel(),configureServices: (services) =>{services.AddDefaultODataServices(odataVersion: Microsoft.OData.ODataVersion.V4,configureReaderAction: null,configureWriterAction: (messageWriterSettings) =>{messageWriterSettings.LibraryCompatibility |= Microsoft.OData.ODataLibraryCompatibility.Version7;},configureUriParserAction: null);}));

 

结论

我们邀请您试用 ASP.NET Core OData 9 并与我们分享您的反馈。感谢您对 OData 生态系统的持续支持和贡献。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/810466.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

回溯法

算法导论 这个文档是学习“算法设计与分析”课程时做的笔记,文档中包含的内容包括课堂上的一些比较重要的知识、例题以及课后作业的题解。主要的参考资料是 Introduction to algorithms-3rd(Thomas H.)(对应的中文版《算法导论第三版》),除了这本书,还有的参考资料就是 Al…

随机算法

算法导论 这个文档是学习“算法设计与分析”课程时做的笔记,文档中包含的内容包括课堂上的一些比较重要的知识、例题以及课后作业的题解。主要的参考资料是 Introduction to algorithms-3rd(Thomas H.)(对应的中文版《算法导论第三版》),除了这本书,还有的参考资料就是 Al…

分治法

算法导论 这个文档是学习“算法设计与分析”课程时做的笔记,文档中包含的内容包括课堂上的一些比较重要的知识、例题以及课后作业的题解。主要的参考资料是 Introduction to algorithms-3rd(Thomas H.)(对应的中文版《算法导论第三版》),除了这本书,还有的参考资料就是 Al…

贪心法

算法导论 这个文档是学习“算法设计与分析”课程时做的笔记,文档中包含的内容包括课堂上的一些比较重要的知识、例题以及课后作业的题解。主要的参考资料是 Introduction to algorithms-3rd(Thomas H.)(对应的中文版《算法导论第三版》),除了这本书,还有的参考资料就是 Al…

Nuxt.js 应用中的 page:finish 钩子详解

title: Nuxt.js 应用中的 page:finish 钩子详解 date: 2024/10/9 updated: 2024/10/9 author: cmdragon excerpt: page:finish 是 Nuxt.js 中用于处理页面加载完成事件的钩子,特别是与 Suspense机制相关。这个钩子允许开发者在页面加载完成后执行自定义操作,以优化用户体验…

智驾仿真测试实战之自动泊车HiL仿真测试

1.引言汽车进入智能化时代,自动泊车功能已成为标配。在研发测试阶段,实车测试面临测试场景覆盖度不足、效率低下和成本高昂等挑战。为解决这些问题,本文提出一种自动泊车HiL仿真测试系统方案,可大幅度提升测试效率及测试场景覆盖度、缩短测试周期、加速产品迭代升级。2.自动…

直接跳转接入在线客服系统

PC网站或H5网站可以通过多种方式接入客服系统,直接访问或跳转聊天链接,是最简单的一种方式 很多人说,我这里的需求是根据xxxx规则进入某个客服(巴拉巴拉一大堆) 这个是前端自行处理的,你们随意任何规则,最终跳到我们这边指定的聊天连接上就行了 至于你们的规则是什么,我…

如何自己动手实现一个图片解答小助手

本文介绍了如何自己动手实现一个图片解答小助手。有一张图片如下所示:Kimi上有一个功能,就是解析图片内容,给出回答:这样可以用于拍照向AI提问的场景,我自己也有这方面的需求,因此动手实践了一下。 自己动手实现的效果如下所示:那么自己如何实现呢? 可以通过添加一个OC…

轻量虚拟机 multipass

multipass listmultipass info multipass shell 后续就可以 shell了

传奇霸业网页游戏单机版安装教程+GM后台+无需虚拟机

今天给大家带来一款单机游戏的架设:传奇霸业网页游戏。 另外:本人承接各种游戏架设(单机+联网) 本人为了学习和研究软件内含的设计思想和原理,带了架设教程仅供娱乐。教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了。如果你是小白也没问题,跟着教…

go抽象封装是一种简化认知的手段

通过 Kubernetes 看 Go 接口设计之道 原创 蔡蔡蔡菜 蔡蔡蔡云原生Go2024年10月01日 08:30 广东解耦依赖底层 在 Kubernetes 中能看到非常多通过接口对具体实现的封装。 Kubelet 实现了非常多复杂的功能,我们可以看到它实现了各种各样的接口,上层代码在使用的时候并不会直接实…

5.4 5.5

5.4 求解下列非线性规划:点击查看代码 import numpy as np from scipy.optimize import minimize def objective(x): return -np.sum(np.sqrt(x) * np.arange(1, 101)) def constraint1(x): return x[1] - 10 def constraint2(x): return 20 - (x[1] + 2*x[2]) def c…