Vb.net WEB-API OData$批处理在7月15日夜间版本更新后失败

Vb.net WEB-API OData$批处理在7月15日夜间版本更新后失败,vb.net,asp.net-web-api,odata,Vb.net,Asp.net Web Api,Odata,从六月份到今天,我一直在使用夜间构建。我已经编写了一个批处理程序来解析我的请求,它正在工作。更新后,会为$batch端点的原始POST调用myParseBatchRequestsSync,然后会收到一条消息“批处理请求的媒体类型必须为'multipart/mixed' 然后,当我向处理程序中的ProcessBatchAsync方法添加一个覆盖,并使用6月的夜间构建在我的原始项目中设置一个中断时,我看到这个方法只调用了一次,然后调用解析例程,都成功了 在7月份的版本中执行此操作时,我看到为$bat

从六月份到今天,我一直在使用夜间构建。我已经编写了一个批处理程序来解析我的请求,它正在工作。更新后,会为$batch端点的原始POST调用my
ParseBatchRequestsSync
,然后会收到一条消息“批处理请求的媒体类型必须为'multipart/mixed'

然后,当我向处理程序中的
ProcessBatchAsync
方法添加一个覆盖,并使用6月的夜间构建在我的原始项目中设置一个中断时,我看到这个方法只调用了一次,然后调用解析例程,都成功了

在7月份的版本中执行此操作时,我看到为$batch的原始POST调用了一次
ProcessBatchAsync
,然后是解析,返回子请求。当执行子请求时,我看到另一个对
ProcessBatchAsync
的调用,该调用命中验证例程并失败,因为子请求不是批处理,而是对实体端点的创建/更改请求

以下是我目前能提供的:

我的批处理程序如下所示:

Imports System.Web.Http
Imports System.Web.Http.OData
Imports System.Web.Http.OData.Batch
Imports System.Net.Http
Imports Microsoft.Data.OData

Imports System.Collections.Generic
Imports System.Diagnostics.CodeAnalysis
Imports System.Threading
Imports System.Threading.Tasks
Imports System.Web.Http.Batch


Public Class CustomODataBatchHandler
    Inherits DefaultODataBatchHandler


    Public Sub New(ByVal server As HttpServer)
        MyBase.New(server)
    End Sub


Public Overrides Async Function ParseBatchRequestsAsync(request As HttpRequestMessage, ByVal cancel As CancellationToken) As Threading.Tasks.Task(Of IList(Of ODataBatchRequestItem))


    If request Is Nothing Then Throw New HttpException(400, "Bad Request")

    Dim oDataReaderSettings As ODataMessageReaderSettings = New ODataMessageReaderSettings With {.DisableMessageStreamDisposal = True, .MessageQuotas = MessageQuotas, .BaseUri = GetBaseUri(request)}
    Dim reader As ODataMessageReader = Await request.Content.GetODataMessageReaderAsync(oDataReaderSettings)
    request.RegisterForDispose(reader)

    Dim requests As List(Of ODataBatchRequestItem) = New List(Of ODataBatchRequestItem)
    Dim batchReader As ODataBatchReader = reader.CreateODataBatchReader()
    Dim batchId As Guid = Guid.NewGuid()
    Do While (batchReader.Read())

        If batchReader.State = ODataBatchReaderState.ChangesetStart Then
            Dim changeSetRequests As IList(Of HttpRequestMessage) = Await batchReader.ReadChangeSetRequestAsync(batchId)
            For Each changeSetRequest As HttpRequestMessage In changeSetRequests
                changeSetRequest.CopyBatchRequestProperties(request)
                Dim originalURI As Uri = changeSetRequest.RequestUri
                Dim reg As New System.Text.RegularExpressions.Regex("\/\$[0-9]+\/")
                If originalURI.IsAbsoluteUri And reg.IsMatch(originalURI.ToString) Then
                    'original URI has a content id in it. replce base uri.
                    Dim newURI As New Uri(originalURI.ToString.Replace(Me.GetBaseUri(request).ToString, ""), UriKind.Relative)
                    changeSetRequest.RequestUri = newURI
                End If

            Next

            requests.Add(New ChangeSetRequestItem(changeSetRequests))

        ElseIf batchReader.State = ODataBatchReaderState.Operation Then

            Dim operationRequest As HttpRequestMessage = Await batchReader.ReadOperationRequestAsync(batchId, bufferContentStream:=True)
            operationRequest.CopyBatchRequestProperties(request)
            requests.Add(New OperationRequestItem(operationRequest))
        End If
    Loop

    Return requests
End Function



End Class
这基本上是源代码到vb.net的转换,并添加了内容id处理的替换,似乎解决了我遇到的相对uri的问题

此处理程序在我的webapiconfig.vb中实现如下: config.Routes.MapODataRoute(“odata”、“odata”、nm.GetEdmModel、新的DefaultODataPathHandler、routingConventions、新的CustomODataBatchHandler(GlobalConfiguration.DefaultServer))

如果我更改请求只是一次提交一个请求,则会调用控制器并完成处理,因此这一定是批处理中的问题,可能是我做错了

更新日期2013年7月16日 更改为DefaultODataBatchHandler并在客户端观察异常情况,我看到请求被拒绝,并显示:“批处理请求必须将‘multipart/mixed’作为媒体类型。”

当我观看WCF dataservices客户端构建请求时,POST to$批处理具有以下标题:

DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Content-Type: multipart/mixed; boundary=batch_7b1d426d-dc36-4a6d-9d3d-be2b64b90d38
Accept: multipart/mixed
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
我尝试将其设置回我的处理程序,可以看到请求被解析并作为更改集返回。然后,在调用控制器之前,相同的媒体类型错误会返回到处理程序中的某个位置

更新2 我获取了
DefaultODataBatchHandler
的源代码,并将其用作自定义批处理程序,而不更改代码。逐步地,我看到$batch的第一篇文章解析得很好,并通过了验证。将子请求的更改集传递给
ExecuteRequestMessagesAsync
然后是
responses.Add(wait-request.SendRequestAsync(Invoker,cancellationToken))
ProcessBatchRequest
再次触发,并尝试处理子请求,而不是允许控制器处理它。这将再次进入验证和解析例程,该例程失败,因为这不再是批处理请求,而且内容类型现在是XML,因为它是实际的实体

为了使用夜间构建,我删除了为MVC、WebAPI、OData等安装的所有内容,然后安装了夜间构建包。我想把它包括在内,以防是其他原因造成的

更新3 我在原始项目中的原始自定义批处理程序中重写了ProcessBatchAsync方法,并且可以确认ProcessBatchAsync ws在工作时只调用了一次。在当前的夜间构建中,似乎为原始请求和子请求调用了ProcessBatchAsync。我无法确认这是否只发生在这个项目中,还是在一个新项目中

更新4 请在此复制:

谢谢


Steve

当您使用DefaultODataBatchHandler时,您看到了什么错误?嗨,Kiran,我重新尝试了DefaultODataBatchHandler。我的控制器没有被调用,但这次我在客户端捕获了异常并查看了内部异常,它声明“批处理请求必须包括multipart/mixed作为mediatype”。我正在使用WCF dataservices客户端,并且在保存更改时设置了批处理选项,因此需要进行更多挖掘,因为我不确定更改了什么。你好,Kiran,我找到了更多信息。我获取了DefaultODataBatchHandler及其所有支持方法的源代码,并从中创建了自己的处理程序。在调用responses.Add(wait request.SendRequestAsync(Invoker,cancellationToken))时,我在ExecuteRequestMessagesAsync方法中发现了这一点;这会将我的子请求发送回批处理程序,然后批处理程序在重新解析批处理时尝试进行验证,这一次失败了,因为我的内容类型现在是实际实体的Atom,并且不再是批处理请求。不确定您是否因此而面临问题:实际上,这就是上面带有正则表达式匹配的代码部分修复的问题。问题是,在内容id匹配之前,URI需要设置为相对的。这样,您就不会在稍后的过程中插入双基uri时得到它。我的问题是ProcessBatchAsync被调用了两次。第一次向$batch端点进行POST时,第二次是调用程序执行时。这就是问题所在,因为请求不是批处理,它无法通过内置验证。