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

use*_*394 40 c# asp.net asp.net-mvc post asp.net-web-api

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

但我无法接收字符串,无论是null还是找不到post方法(404错误)

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

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();
Run Code Online (Sandbox Code Playgroud)

ASP.NET Web Api控制器:

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

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

即使"没有"[授权]设置它也有同样的奇怪行为. - >所以它与用户身份验证无关.

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

Dar*_*rov 58

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

所以,让我们付诸实践.以下是一个简单的Web API控制器的外观:

public class TestController : ApiController
{
    public string Post([FromBody] string value)
    {
        return value;
    }
}
Run Code Online (Sandbox Code Playgroud)

和消费者:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

毫无疑问,您会注意到[FromBody]Web API控制器属性的装饰以及=客户端POST数据的前缀.我建议您阅读Web API如何进行参数绑定以更好地理解概念.

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

如果在阅读了我链接到的资料后,你就像我一样对自己说,WTF男人,我需要做的就是将一个字符串发送到服务器端端点,我需要做所有这些吗?没门.然后结帐ServiceStack.您将有一个很好的基础来与Web API进行比较.我不知道微软在设计Web API时会考虑什么,但是说实话,我们应该为我们的HTML(想想Razor)和REST提供单独的基本控制器吗?这不可能是严重的.

  • @DarrelMiller应用程序开发人员可能会使用的所有内容都有常量.如果您指的是所有HTTP谓词的哈希集,那么这是框架用来确定符号是否为HTTP方法的最佳存储. (3认同)
  • 非常有趣,如果我使用您的客户端代码,它的工作原理.它适用于var data ="= ..."; 如果我删除"="它不起作用. (2认同)
  • @ user1011394,是的,这是一个WTF!Checkout [ServiceStack](http://www.servicestack.net/).你会爱上它的. (2认同)
  • @DarrelMiller ServiceStack做得非常好(不确定是什么让你想到的话),你可以[自定义HTTP响应](https://github.com/ServiceStack/ServiceStack/wiki/Customize-HTTP-Responses)你喜欢什么,[返回你想要的任何响应](https://github.com/ServiceStack/ServiceStack/wiki/Service-return-types)及其[HTML支持应该在Web Fx中实现](http:// razor.servicestack.net)即HTML只是另一种Content-Type.不共享基类不是好设计,它是一种自我强加的人为限制.SS使用相同的接口执行HTML +自主机. (2认同)
  • @DarrelMiller只是没有人认为不同,ServiceStack还包括类型[HttpMethods](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/ServiceClient.Web/HttpMethod.cs)和[HttpHeaders ](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack.Common/Web/HttpHeaders.cs)可以替代字符串替代那些喜欢使用类型化常量的字符串. (2认同)

Dar*_*ler 35

如果您接受使用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)};

        }

    }
Run Code Online (Sandbox Code Playgroud)

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

您可以使用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);

    }
Run Code Online (Sandbox Code Playgroud)

  • "接受你正在使用HTTP的事实"喜欢它.:) (2认同)