【问题标题】:OData batch requests with XMLHTMLRequest使用 XMLHTMLRequest 的 OData 批处理请求
【发布时间】:2014-04-22 18:39:21
【问题描述】:

我正在尝试编写一个 javascript OData 使用者,它将一次将我的多个实体用于 POST(因此我可以一次提交一个实体和关联的子项)到我的 WebApi 服务器。但是我得到一个恼人的错误:

ExceptionMessage: "The message header 'POST /odata/MyEntity HTTP/1.1' is invalid. The header value must be of the format '<header name>: <header value>'."
ExceptionType: "Microsoft.Data.OData.ODataException"
Message: "An error has occurred."
StackTrace: "   at Microsoft.Data.OData.ODataBatchReaderStream.ValidateHeaderLine(String headerLine, String& headerName, String& headerValue)
↵   at Microsoft.Data.OData.ODataBatchReaderStream.ReadHeaders()
↵   at Microsoft.Data.OData.ODataBatchReaderStream.ProcessPartHeader()
↵   at Microsoft.Data.OData.ODataBatchReader.SkipToNextPartAndReadHeaders()
↵   at Microsoft.Data.OData.ODataBatchReader.ReadImplementation()
↵   at Microsoft.Data.OData.ODataBatchReader.ReadSynchronously()
↵   at Microsoft.Data.OData.ODataBatchReader.InterceptException[T](Func`1 action)
↵   at Microsoft.Data.OData.ODataBatchReader.Read()
↵   at System.Web.Http.OData.Batch.DefaultODataBatchHandler.<ParseBatchRequestsAsync>d__e.MoveNext()
↵--- End of stack trace from previous location where exception was thrown ---
↵   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
↵   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
↵   at System.Web.Http.OData.Batch.DefaultODataBatchHandler.<ProcessBatchAsync>d__0.MoveNext()
↵--- End of stack trace from previous location where exception was thrown ---
↵   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
↵   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
↵   at System.Web.Http.Batch.HttpBatchHandler.<SendAsync>d__0.MoveNext()"

我的构建函数如下:

var oReq = new XMLHttpRequest();
oReq.onload = function () {
    if (oReq.status == 404) {
        defer.reject(oReq.statusText);
    } else {
        var response = JSON.parse(oReq.response);
        if (response['odata.error']) {
            defer.reject(oReq['odata.error']);
        } else if (response.Message) {
            defer.reject(response.Message);
        } else {
            defer.resolve(response);
        }
    }
};
oReq.onerror = function () {
    defer.reject(oReq.statusText);
};
oReq.open("POST", "/odata/$batch", true);
var batch = "batch_" + newGuid();
oReq.setRequestHeader("Content-type", 'multipart/mixed; boundary="' + batch + '"');

var body = "--" + batch + "\r\n";
ko.utils.arrayForEach(entities, function (entity) {
    body = body + [
        'Content-Type: application/http; msgtype=request',
        '',
        'POST ' + url + ' HTTP/1.1',
        'Content-Type: application/json; charset=utf-8',
        '',
        ko.toJSON(entity),
        "--" + batch
    ].join('\r\n')
});

oReq.send(body + "--");

我没有正确格式化请求吗?我一直在尝试效仿:

http://blogs.msdn.com/b/webdev/archive/2013/11/01/introducing-batch-support-in-web-api-and-web-api-odata.aspx

谢谢。

【问题讨论】:

  • 您有示例 http 请求吗?可能是服务器问题,也可能是无效请求引起的。

标签: javascript asp.net-web-api odata


【解决方案1】:

我已经完成了这项工作。我阅读了别人的代码 (https://github.com/volpav/batchjs) 并自己实现了(因为我不想使用 JQuery)。

export interface ODataChangeRequest {
    requestUri: string;
    method: string;
    data: string;
    resolve: (response?: Object) => void;
    reject: (response?: Object) => void;
}


export function packBatch(requests: ODataChangeRequest[], boundary: string): string {
    var body = [];

    body.push('--' + boundary);
    var changeSet = 'changeset_' + newGuid();
    body.push('Content-type: multipart/mixed; boundary=' + changeSet, '');

    ko.utils.arrayForEach(requests, (d) => {
        var t = d.method.toUpperCase();

        body.push('--' + changeSet);
        body.push('Content-Type: application/http', 'Content-Transfer-Encoding: binary', '');

        body.push(t + ' ' + d.requestUri + ' ' + httpVersion);
        body.push('Host: ' + location.host);

        if (d.data) {
            body.push('Content-Type: application/json; charset=utf-8');
            body.push('', d.data, '');
        }
    });

    body.push('--' + changeSet + '--', '');

    body.push('--' + boundary + '--', '');

    return body.join('\r\n');
}

export function unpackBatch(requests: ODataChangeRequest[], xhr: XMLHttpRequest): boolean {
    var lines = xhr.responseText.split('\r\n'),
        i = 0,
        data = [],
        feedingData = false,
        statusCode = null,
        allSuccessful = true;

    ko.utils.arrayForEach(lines, (l) => {
        if (!l.length) {
            return;
        }

        var currentRequest = requests[i];
        if (!currentRequest) {
            return;
        }

        var httpIndex = l.indexOf(httpVersion);
        if (httpIndex != -1) {
            // Hadn't gotten data for previous request. Close
            if (statusCode) {
                if (statusCode == '200') {
                    currentRequest.resolve();
                } else {
                    currentRequest.reject();
                }
            }

            var startIndex = httpIndex + httpVersion.length + 1;
            statusCode = l.substring(startIndex, startIndex + 3);
            if (statusCode != '200') {
                allSuccessful = false;
            }
        }

        if (statusCode) {
            if (l == "{") {
                feedingData = true;
            }
            if (feedingData) {
                data.push(l);
                if (l == "}") {
                    var dataObj = data.length ? JSON.parse(data.join(" ")) : null;
                    if (statusCode == '200') {
                        currentRequest.resolve(dataObj);
                    } else {
                        currentRequest.reject(dataObj);
                    }

                    i++;
                    data = [];
                    feedingData = false;
                    statusCode = null;
                }
            }
        }
    });

    return allSuccessful;
}

【讨论】:

  • 嘿,这看起来很棒。它支持 OData v4,还是专为 v3 设计的?谢谢!
  • @RobertMcLaws 我为 OData v3 设计了它,但后来转移到 OData v4 没有问题 iirc。
【解决方案2】:

我认为您可以先使用“添加引用”创建一个 odata clint。并使用 Fiddler 检查客户端发送的请求的有效负载。而且,您可以在 AJAX 中做同样的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 2023-02-09
    • 2021-03-03
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多