C# POST 字符串到 ASP.NET Web Api 应用程序 - 返回 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13771032/
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 09:45:28  来源:igfitidea点击:

POST string to ASP.NET Web Api application - returns null

c#asp.netasp.net-mvcpostasp.net-web-api

提问by user1011394

Im trying to transmit a string from client to ASP.NET MVC4 application.

我试图将一个字符串从客户端传输到 ASP.NET MVC4 应用程序。

But I can not receive the string, either it is null or the post method can not be found (404 error)

但是收不到字符串,要么是null,要么就是找不到post方法(404错误)

Client Code to transmit the string (Console Application):

传输字符串的客户端代码(控制台应用程序):

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:49032/api/test");
request.Credentials = new NetworkCredential("user", "pw");
request.Method = "POST";
string postData = "Short test...";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;

Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();

WebResponse response = request.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
dataStream = response.GetResponseStream();

StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
reader.Close();
dataStream.Close();
response.Close();
Console.ReadLine();

ASP.NET Web Api Controller:

ASP.NET Web Api 控制器:

public class TestController : ApiController
{
    [Authorize]
    public String Post(byte[] value)
    {
        return value.Length.ToString();
    }
}

In that case I'm able to call the "Post" method, but "value" is NULL. If I change the method signature to (string value) than it will never called.

在这种情况下,我可以调用“Post”方法,但“value”是NULL. 如果我将方法签名更改为(字符串值),它将永远不会被调用。

Even "without" the [Authorize] setting it has the same strange behavior. -> So it has nothing to do with the user authentication.

即使“没有” [Authorize] 设置,它也有同样奇怪的行为。-> 所以它与用户认证无关。

Any ideas what I'm doing wrong? I'm grateful for any help.

任何想法我做错了什么?我很感激任何帮助。

采纳答案by Darin Dimitrov

You seem to have used some [Authorize]attribute on your Web API controller action and I don't see how this is relevant to your question.

您似乎[Authorize]在 Web API 控制器操作上使用了某些属性,但我看不出这与您的问题有何关联。

So, let's get into practice. Here's a how a trivial Web API controller might look like:

所以,让我们开始实践吧。下面是一个简单的 Web API 控制器的样子:

public class TestController : ApiController
{
    public string Post([FromBody] string value)
    {
        return value;
    }
}

and a consumer for that matter:

和一个消费者:

class Program
{
    static void Main()
    {
        using (var client = new WebClient())
        {
            client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
            var data = "=Short test...";
            var result = client.UploadString("http://localhost:52996/api/test", "POST", data);
            Console.WriteLine(result);
        }
    }
}

You will undoubtedly notice the [FromBody]decoration of the Web API controller attribute as well as the =prefix of the POST data om the client side. I would recommend you reading about how does the Web API does parameter bindingto better understand the concepts.

您无疑会注意到[FromBody]Web API 控制器属性的修饰以及=来自客户端的 POST 数据的前缀。我建议您阅读有关Web API 如何进行参数绑定以更好地理解这些概念的信息。

As far as the [Authorize]attribute is concerned, this could be used to protect some actions on your server from being accessible only to authenticated users. Actually it is pretty unclear what you are trying to achieve here.You should have made this more clear in your question by the way. Are you are trying to understand how parameter bind works in ASP.NET Web API (please read the article I've linked to if this is your goal) or are attempting to do some authentication and/or authorization? If the second is your case you might find the following postthat I wrote on this topic interesting to get you started.

[Authorize]属性而言,这可用于保护您的服务器上的某些操作仅对经过身份验证的用户才能访问。实际上,您在这里尝试实现的目标还不清楚。顺便说一下,您应该在问题中更清楚地说明这一点。您是想了解参数绑定在 ASP.NET Web API 中是如何工作的(如果这是您的目标,请阅读我链接到的文章)还是正在尝试进行一些身份验证和/或授权?如果第二种情况是您的情况,您可能会发现following post我在这个主题上写的很有趣,可以帮助您入门。

And if after reading the materials I've linked to, you are like me and say to yourself, WTF man, all I need to do is POST a string to a server side endpoint and I need to do all of this? No way. Then checkout ServiceStack. You will have a good base for comparison with Web API. I don't know what the dudes at Microsoft were thinking about when designing the Web API, but come on, seriously, we should have separate base controllers for our HTML (think Razor) and REST stuff? This cannot be serious.

如果在阅读了我链接到的材料后,您像我一样对自己说,WTF 人,我需要做的就是将字符串 POST 到服务器端端点,我需要做所有这些吗?没门。然后结帐ServiceStack。您将有一个很好的基础来与 Web API 进行比较。我不知道 Microsoft 的那些家伙在设计 Web API 时在想什么,但是说真的,我们应该为我们的 HTML(想想 Razor)和 REST 东西有单独的基本控制器?这不可能是严重的。

回答by Chuck Conway

I use this code to post HttpRequests.

我使用此代码发布 HttpRequests。

/// <summary>
        /// Post this message.
        /// </summary>
        /// <param name="url">URL of the document.</param>
        /// <param name="bytes">The bytes.</param>
        public T Post<T>(string url, byte[] bytes)
    {
        T item;
        var request = WritePost(url, bytes);

        using (var response = request.GetResponse() as HttpWebResponse)
        {
            item = DeserializeResponse<T>(response);
            response.Close();
        }

        return item;
    }

    /// <summary>
    /// Writes the post.
    /// </summary>
    /// <param name="url">The URL.</param>
    /// <param name="bytes">The bytes.</param>
    /// <returns></returns>
    private static HttpWebRequest WritePost(string url, byte[] bytes)
    {
        ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

        HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
        Stream stream = null;
        try
        {
            request.Headers.Clear();
            request.PreAuthenticate = true;
            request.Connection = null;
            request.Expect = null;
            request.KeepAlive = false;
            request.ContentLength = bytes.Length;
            request.Timeout = -1;
            request.Method = "POST";
            stream = request.GetRequestStream();
            stream.Write(bytes, 0, bytes.Length);
        }
        catch (Exception e)
        {
            GetErrorResponse(url, e);
        }
        finally
        {
            if (stream != null)
            {
                stream.Flush();
                stream.Close();
            }
        }
        return request;
    }

In regards to your code, try it without the content.Type (request.ContentType = "application/x-www-form-urlencoded";)

关于您的代码,请在没有 content.Type ( request.ContentType = "application/x-www-form-urlencoded";) 的情况下尝试

update

更新

I believe the problem lies with how you are trying to retrieve the value. When you do a POST and send bytes via the Stream, they will not be passed into the action as a parameter. You'll need to retrieve the bytes via the stream on the server.

我相信问题在于您如何尝试检索该值。当您执行 POST 并通过 Stream 发送字节时,它们不会作为参数传递到操作中。您需要通过服务器上的流检索字节。

On the server, try getting the bytes from stream. The following code is what I use.

在服务器上,尝试从流中获取字节。以下代码是我使用的。

     /// <summary> Gets the body. </summary>
     /// <returns> The body. </returns>
     protected byte[] GetBytes()
     {
       byte[] bytes;
        using (var binaryReader = new BinaryReader(Request.InputStream))
        {
            bytes = binaryReader.ReadBytes(Request.ContentLength);
        }

         return bytes;
     }

回答by Darrel Miller

Web API works very nicely if you accept the fact that you are using HTTP. It's when you start trying to pretend that you are sending objects over the wire that it starts to get messy.

如果您接受使用 HTTP 的事实,Web API 会非常好地工作。当你开始试图假装你正在通过网络发送对象时,它开始变得混乱。

 public class TextController : ApiController
    {
        public HttpResponseMessage Post(HttpRequestMessage request) {

            var someText = request.Content.ReadAsStringAsync().Result;
            return new HttpResponseMessage() {Content = new StringContent(someText)};

        }

    }

This controller will handle a HTTP request, read a string out of the payload and return that string back.

该控制器将处理 HTTP 请求,从有效负载中读取一个字符串并将该字符串返回。

You can use HttpClient to call it by passing an instance of StringContent. StringContent will be default use text/plain as the media type. Which is exactly what you are trying to pass.

您可以使用 HttpClient 通过传递 StringContent 的实例来调用它。StringContent 将默认使用 text/plain 作为媒体类型。这正是你想要通过的。

    [Fact]
    public void PostAString()
    {

        var client = new HttpClient();

        var content = new StringContent("Some text");
        var response = client.PostAsync("http://oak:9999/api/text", content).Result;

        Assert.Equal("Some text",response.Content.ReadAsStringAsync().Result);

    }

回答by Henrik Frystyk Nielsen

Darrel is of course right on with his response. One thing to add is that the reason why attempting to bind to a body containing a single token like "hello".

达雷尔的回答当然是正确的。要添加的一件事是尝试绑定到包含单个令牌(如“hello”)的主体的原因。

is that it isn't quite URL form encoded data. By adding “=” in front like this:

是它不是完全 URL 形式的编码数据。像这样在前面添加“=”:

=hello

it becomes a URL form encoding of a single key value pair with an empty name and value of “hello”.

它成为具有空名称和值“hello”的单个键值对的 URL 形式编码。

However, a better solution is to use application/json when uploading a string:

但是,更好的解决方案是在上传字符串时使用 application/json:

POST /api/sample HTTP/1.1
Content-Type: application/json; charset=utf-8
Host: host:8080
Content-Length: 7

"Hello"

Using HttpClient you can do it as follows:

使用 HttpClient 您可以执行以下操作:

HttpClient client = new HttpClient();
HttpResponseMessage response = await client.PostAsJsonAsync(_baseAddress + "api/json", "Hello");
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);

Henrik

亨里克

回答by Jeson Martajaya

For WebAPI, here is the code to retrieve body text without going through their special [FromBody] binding.

对于 WebAPI,这里是无需通过其特殊的 [FromBody] 绑定即可检索正文文本的代码。

public class YourController : ApiController
{
    [HttpPost]
    public HttpResponseMessage Post()
    {
        string bodyText = this.Request.Content.ReadAsStringAsync().Result;
        //more code here...
    }
}

回答by Bill.Zhuang

i meet this problem, and find this article. http://www.jasonwatmore.com/post/2014/04/18/Post-a-simple-string-value-from-AngularJS-to-NET-Web-API.aspx

我遇到了这个问题,并找到了这篇文章。 http://www.jasonwatmore.com/post/2014/04/18/Post-a-simple-string-value-from-AngularJS-to-NET-Web-API.aspx

The solution I found was to simply wrap the string value in double quotes in your js post

我发现的解决方案是在你的 js 帖子中简单地将字符串值用双引号括起来

works like a charm! FYI

奇迹般有效!供参考

回答by Nea

([FromBody] IDictionary<string,object> data)