通过使用 ODataController 类并支持实体框架中的并发检查,我使用 OData v4 协议制作了 WebAPI 2 服务。客户端代码是使用 Odata Client T4 模板生成的。此代码生成从处理实体跟踪的 DataServiceContext 派生的代理类和容器类,解析 Odata URL 中的 LINQ 查询等。当跟踪的实体(包含检查并发性的属性)更新时,调用 SaveChangesAsync 方法的容器类生成 HTTP PATCH包含 If-Match 标头的请求,该标头具有从该实体的上次查询中收到的值,并且工作正常。
Fiddler 捕获的示例请求:
补丁/用户(2) HTTP/1.1
缓存
如果匹配:W/"J1Z1a2FzaWU3Bhc2IjJw=="
但是如果容器对实体进行查询,它会生成正确的 HTTP GET 请求
(来自请求的示例:
GET /Animals(8) HTTP/1.1)
但没有 If-None-Match 标头,即使在最后一个查询中,服务也会发送 etag 值作为响应
(来自响应的示例:
@odata.etag=W/"J0MxRjIn")
是否可以通过设置容器上下文配置请求管道属性或其他方式添加 If-None-Match 标头?只是补充说明 - 如果服务在 GET 请求的 If-None-Match 标头中获取 etag 值,它应该返回状态代码 304 NotModified 以防 etag 值匹配(表示实体未更改),否则服务在响应正文中发送实体属性.
更新:
我尝试通过处理 SendingRequest2 添加 If-None-Match,它使我能够手动添加 If-None-Match 标头,但在这种情况下,当服务接收请求并从中读取 etag 时,如果实体未更改(etag 匹配) ,答案将是状态码 304 - NotModified 和容器(派生 DataServiceContext 类的实例)将无法处理该响应,因为它需要正文消息中的实体,因此它会生成异常。我可以处理异常并使用它来确认实体没有被更改,但这不是优化的编程方式。我需要一种方法来处理请求和响应管道事件。在请求管道中,我将 etag 添加到单个查询请求中,在响应管道中,我将处理收到的状态代码 304 - NotModified。
context.Configuration.RequestPipeline 的列表是:
OnEntityReferenceLink(动作动作);
OnEntryEnding(动作动作);
OnEntryStarting(动作动作);
OnMessageWriterSettingsCreated(Action args);
OnNavigationLinkEnding(动作动作);
OnNavigationLinkStarting(动作动作);
并且 context.Configuration.ResponsePipeline 的列表是:
OnEntityMaterialized(动作动作);
OnEntryEnded(动作动作);
OnEntryStarted(动作动作);
OnFeedEnded(动作动作);
OnFeedStarted(动作动作);
OnMessageReaderSettingsCreated(操作 messageReaderSettingsAction);
OnNavigationLinkEnded(动作动作);
OnNavigationLinkStarted(动作动作);