C# 从 Web API 方法获取原始 POST 数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13226817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 07:48:40  来源:igfitidea点击:

Getting raw POST data from Web API method

c#asp.net-web-api

提问by Joe Albahari

I have the following Web API method in an ApiController class:

我在 ApiController 类中有以下 Web API 方法:

public HttpResponseMessage Post([FromBody]byte[] incomingData)
{
  ...
}

I want incomingDatato be the raw content of the POST. But it seems that the Web API stack attempts to parse the incoming data with the JSON formatter, and this causes the following code on the client side to fail:

我想incomingData成为 POST 的原始内容。但似乎 Web API 堆栈尝试使用 JSON 格式化程序解析传入数据,这会导致客户端的以下代码失败:

new WebClient().UploadData("http://localhost:15134/api/Foo", new byte[] { 1, 2, 3 });

Is there a simple workaround for this?

有一个简单的解决方法吗?

采纳答案by Joe Albahari

For anyone else running into this problem, the solution is to define the POST method with no parameters, and access the raw data via Request.Content:

对于遇到此问题的任何其他人,解决方案是定义不带参数的 POST 方法,并通过Request.Content以下方式访问原始数据:

public HttpResponseMessage Post()
{
  Request.Content.ReadAsByteArrayAsync()...
  ...

回答by Jason Goemaat

In MVC 6 Request doesn't seem to have a 'Content' property. Here's what I ended up doing:

在 MVC 6 请求中似乎没有“内容”属性。这是我最终做的:

[HttpPost]
public async Task<string> Post()
{
    string content = await new StreamReader(Request.Body).ReadToEndAsync();
    return "SUCCESS";
}

回答by Christoph Herold

If you need the raw input in addition to the model parameter for easier access, you can use the following:

如果除了模型参数之外还需要原始输入以便于访问,可以使用以下命令:

using (var contentStream = await this.Request.Content.ReadAsStreamAsync())
{
    contentStream.Seek(0, SeekOrigin.Begin);
    using (var sr = new StreamReader(contentStream))
    {
        string rawContent = sr.ReadToEnd();
        // use raw content here
    }
}

The secret is using stream.Seek(0, SeekOrigin.Begin)to reset the stream before trying to read the data.

秘密是stream.Seek(0, SeekOrigin.Begin)在尝试读取数据之前使用重置流。

回答by Rocklan

The other answers suggest removing the input parameter, but that will break all of your existing code. To answer the question properly, an easier solution is to create a function that looks like this (Thanks to Christoph below for this code):

其他答案建议删除输入参数,但这会破坏您现有的所有代码。要正确回答问题,更简单的解决方案是创建一个如下所示的函数(感谢下面的 Christoph 提供此代码):

private async Task<String> getRawPostData()
{
    using (var contentStream = await this.Request.Content.ReadAsStreamAsync())
    {
        contentStream.Seek(0, SeekOrigin.Begin);
        using (var sr = new StreamReader(contentStream))
        {
            return sr.ReadToEnd();
        }
    }
}

and then get the raw posted data inside your web api call like so:

然后在您的 web api 调用中获取原始发布的数据,如下所示:

public HttpResponseMessage Post ([FromBody]byte[] incomingData)
{
    string rawData = getRawPostData().Result;

    // log it or whatever

    return Request.CreateResponse(HttpStatusCode.OK);
}

回答by William T. Mallard

I took LachlanB's answer and put it in a utility class with a single static method that I can use in all my controllers.

我接受了 LachlanB 的回答,并将它放在一个实用程序类中,其中包含一个我可以在所有控制器中使用的静态方法。

public class RawContentReader
{
    public static async Task<string> Read(HttpRequestMessage req)
    {
        using (var contentStream = await req.Content.ReadAsStreamAsync())
        {
            contentStream.Seek(0, SeekOrigin.Begin);
            using (var sr = new StreamReader(contentStream))
            {
                return sr.ReadToEnd();
            }
        }
    }
}

Then I can call it from any of my ApiController's methods this way:

然后我可以通过这种方式从我的任何 ApiController 方法中调用它:

string raw = await RawContentReader.Read(this.Request);