1

通过使用 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(动作动作);

4

1 回答 1

2

在发送请求之前添加以下代码应该可以工作:

context.SendingRequest2+= (sender, eventArgs) =>
{
    eventArgs.RequestMessage.SetHeader("If-None-Match", "xxxxxxx");
};

,其中context是 的DataServiceContext派生类的实例的名称。

于 2014-10-09T08:51:19.430 回答