简体   繁体   English

如何使用 C# 将 JSON 发布到服务器?

[英]How to post JSON to a server using C#?

Here's the code I'm using:这是我正在使用的代码:

// create a request
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(url); request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";


// turn our request string into a byte stream
byte[] postBytes = Encoding.UTF8.GetBytes(json);

// this is important - make sure you specify type this way
request.ContentType = "application/json; charset=UTF-8";
request.Accept = "application/json";
request.ContentLength = postBytes.Length;
request.CookieContainer = Cookies;
request.UserAgent = currentUserAgent;
Stream requestStream = request.GetRequestStream();

// now send it
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();

// grab te response and print it out to the console along with the status code
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string result;
using (StreamReader rdr = new StreamReader(response.GetResponseStream()))
{
    result = rdr.ReadToEnd();
}

return result;

When I'm running this, I'm always getting 500 internal server error.当我运行它时,我总是收到 500 内部服务器错误。

What am I doing wrong?我究竟做错了什么?

The way I do it and is working is:我这样做和工作的方式是:

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    string json = "{\"user\":\"test\"," +
                  "\"password\":\"bla\"}";

    streamWriter.Write(json);
}

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
}

I wrote a library to perform this task in a simpler way, it is here: https://github.com/ademargomes/JsonRequest我写了一个库以更简单的方式执行此任务,它在这里: https ://github.com/ademargomes/JsonRequest

Ademar's solution can be improved by leveraging JavaScriptSerializer 's Serialize method to provide implicit conversion of the object to JSON. Ademar 的解决方案可以通过利用JavaScriptSerializerSerialize方法来提供对象到 JSON 的隐式转换来改进。

Additionally, it is possible to leverage the using statement's default functionality in order to omit explicitly calling Flush and Close .此外,可以利用using语句的默认功能来省略显式调用FlushClose

var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
    string json = new JavaScriptSerializer().Serialize(new
                {
                    user = "Foo",
                    password = "Baz"
                });

    streamWriter.Write(json);
}

var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
    var result = streamReader.ReadToEnd();
}

The HttpClient type is a newer implementation than the WebClient and HttpWebRequest . HttpClient类型是比WebClientHttpWebRequest更新的实现。 Both the WebClient and WebRequest have been marked as obsolete. WebClientWebRequest都已被标记为过时。 [1] [1]

You can simply use the following lines.您可以简单地使用以下几行。

string myJson = "{'Username': 'myusername','Password':'pass'}";
using (var client = new HttpClient())
{
    var response = await client.PostAsync(
        "http://yourUrl", 
         new StringContent(myJson, Encoding.UTF8, "application/json"));
}

When you need your HttpClient more than once it's recommended to only create one instance and reuse it or use the new HttpClientFactory .当您多次需要HttpClient时,建议只创建一个实例并重用它或使用新的HttpClientFactory [2] [2]

For FTP, since HttpClient doesn't support it, we recommend using a third-party library.对于 FTP,由于 HttpClient 不支持,我们建议使用第三方库。

@docs.microsoft.com [3] @docs.microsoft.com [3]


Since dotnet core 3.1 you can use the JsonSerializer from System.Text.Json to create your json string.从 dotnet core 3.1 开始,您可以使用System.Text.Json中的JsonSerializer创建您的 json 字符串。

string myJson = JsonSerializer.Serialize(credentialsObj);

Further to Sean's post, it isn't necessary to nest the using statements.在 Sean 的帖子之后,没有必要嵌套 using 语句。 By using the StreamWriter it will be flushed and closed at the end of the block so no need to explicitly call the Flush() and Close() methods:通过using StreamWriter 它将在块的末尾刷新和关闭,因此无需显式调用Flush()Close()方法:

var request = (HttpWebRequest)WebRequest.Create("http://url");
request.ContentType = "application/json";
request.Method = "POST";

using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
    string json = new JavaScriptSerializer().Serialize(new
                {
                    user = "Foo",
                    password = "Baz"
                });

    streamWriter.Write(json);
}

var response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
        var result = streamReader.ReadToEnd();
}

If you need to call is asynchronously then use如果您需要异步调用,请使用

var request = HttpWebRequest.Create("http://www.maplegraphservices.com/tokkri/webservices/updateProfile.php?oldEmailID=" + App.currentUser.email) as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = "text/json";
            request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);

private void GetRequestStreamCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
        // End the stream request operation

        Stream postStream = request.EndGetRequestStream(asynchronousResult);


        // Create the post data
        string postData = JsonConvert.SerializeObject(edit).ToString();

        byte[] byteArray = Encoding.UTF8.GetBytes(postData);


        postStream.Write(byteArray, 0, byteArray.Length);
        postStream.Close();

        //Start the web request
        request.BeginGetResponse(new AsyncCallback(GetResponceStreamCallback), request);
    }

    void GetResponceStreamCallback(IAsyncResult callbackResult)
    {
        HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
        using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
        {
            string result = httpWebStreamReader.ReadToEnd();
            stat.Text = result;
        }

    }

I recently came up with a much simpler way to post a JSON, with the additional step of converting from a model in my app.我最近想出了一种更简单的方法来发布 JSON,并增加了从我的应用程序中的模型转换的额外步骤。 Note that you have to make the model [JsonObject] for your controller to get the values and do the conversion.请注意,您必须为控制器创建模型[JsonObject]才能获取值并进行转换。

Request:要求:

 var model = new MyModel(); 

 using (var client = new HttpClient())
 {
     var uri = new Uri("XXXXXXXXX"); 
     var json = new JavaScriptSerializer().Serialize(model);
     var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
     var response = await client.PutAsync(uri,stringContent).Result;
     // ...
  }

Model:模型:

[JsonObject]
[Serializable]
public class MyModel
{
    public Decimal Value { get; set; }
    public string Project { get; set; }
    public string FilePath { get; set; }
    public string FileName { get; set; }
}

Server side:服务器端:

[HttpPut]     
public async Task<HttpResponseMessage> PutApi([FromBody]MyModel model)
{
    // ...
}

Take care of the Content-Type you are using :注意您正在使用的 Content-Type :

application/json

Sources :资料来源:

RFC4627 RFC4627

Other post 其他帖子

WARNING!警告! I have a very strong view on this subject.我对这个问题有非常强烈的看法。

.NET's existing web clients are not developer friendly! .NET 现有的 Web 客户端对开发人员不友好! WebRequest & WebClient are prime examples of "how to frustrate a developer". WebRequestWebClient是“如何挫败开发人员”的主要例子。 They are verbose & complicated to work with;它们很冗长且使用起来很复杂; when all you want to do is a simple Post request in C#.当您只想在 C# 中执行一个简单的 Post 请求时。 HttpClient goes some way in addressing these issues, but it still falls short. HttpClient在解决这些问题方面做了一些工作,但仍然不足。 On top of that Microsoft's documentation is bad … really bad;最重要的是,微软的文档很糟糕……真的很糟糕; unless you want to sift through pages and pages of technical blurb.除非您想筛选一页又一页的技术简介。

Open-source to the rescue.开源来救援。 There are three excellent open-source, free NuGet libraries as alternatives.有三个优秀的开源免费 NuGet 库可供选择。 Thank goodness!谢天谢地! These are all well supported, documented and yes, easy - correction…super easy - to work with.这些都得到了很好的支持,记录在案,是的,很容易 - 更正......超级容易 - 使用。

  • ServiceStack.Text - fast, light and resilient. ServiceStack.Text - 快速、轻便且有弹性。
  • RestSharp - simple REST and HTTP API Client RestSharp - 简单的 REST 和 HTTP API 客户端
  • Flurl - a fluent, portable, testable HTTP client library Flurl - 一个流畅、可移植、可测试的 HTTP 客户端库

There is not much between them, but I would give ServiceStack.Text the slight edge …它们之间没有太多区别,但我会给 ServiceStack.Text 一点优势……

  • Github stars are roughly the same. Github stars大致相同。
  • Open Issues & importantly how quickly any issues closed down?未解决的问题以及重要的是,任何问题关闭的速度有多快? ServiceStack takes the award here for the fastest issue resolution & no open issues. ServiceStack 在这里获得了最快的问题解决和没有未解决问题的奖项。
  • Documentation?文档? All have great documentation;都有很好的文档; however, ServiceStack takes it to the next level & is known for its 'Golden standard' for documentation.然而,ServiceStack 将其提升到了一个新的水平,并以其文档的“黄金标准”而闻名。

Ok - so what does a Post Request in JSON look like within ServiceStack.Text?好的 - 那么 JSON 格式的 Post 请求在 ServiceStack.Text 中是什么样的?

var response = "http://example.org/login"
    .PostJsonToUrl(new Login { Username="admin", Password="mypassword" });

That is one line of code.那是一行代码。 Concise & easy!简洁轻松! Compare the above to .NET's Http libraries.将上述内容与 .NET 的 Http 库进行比较。

This option is not mentioned:未提及此选项

using (var client = new HttpClient())
{
    client.BaseAddress = new Uri("http://localhost:9000/");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var foo = new User
    {
        user = "Foo",
        password = "Baz"
    }

    await client.PostAsJsonAsync("users/add", foo);
}

Some different and clean way to achieve this is by using HttpClient like this:实现此目的的一些不同且干净的方法是使用 HttpClient ,如下所示:

public async Task<HttpResponseMessage> PostResult(string url, ResultObject resultObject)
{
    using (var client = new HttpClient())
    {
        HttpResponseMessage response = new HttpResponseMessage();
        try
        {
            response = await client.PostAsJsonAsync(url, resultObject);
        }
        catch (Exception ex)
        {
            throw ex
        }
        return response;
     }
}

I finally invoked in sync mode by including the .Result我终于通过包含.Result在同步模式下调用

HttpResponseMessage response = null;
try
{
    using (var client = new HttpClient())
    {
       response = client.PostAsync(
        "http://localhost:8000/....",
         new StringContent(myJson,Encoding.UTF8,"application/json")).Result;
    if (response.IsSuccessStatusCode)
        {
            MessageBox.Show("OK");              
        }
        else
        {
            MessageBox.Show("NOK");
        }
    }
}
catch (Exception ex)
{
    MessageBox.Show("ERROR");
}

I find this to be the friendliest and most concise way to post an read JSON data:我发现这是发布读取 JSON 数据的最友好和最简洁的方式:

var url = @"http://www.myapi.com/";
var request = new Request { Greeting = "Hello world!" };
var json = JsonSerializer.Serialize<Request>(request);
using (WebClient client = new WebClient())
{
    var jsonResponse = client.UploadString(url, json);
    var response = JsonSerializer.Deserialize<Response>(jsonResponse);
}

I'm using Microsoft's System.Text.Json for serializing and deserializing JSON.我正在使用 Microsoft 的System.Text.Json对 JSON 进行序列化和反序列化。 See NuGet .请参阅NuGet

This is how I do it我就是这样做的

//URL
var url = "http://www.myapi.com/";

//Request
using var request = new HttpRequestMessage(HttpMethod.Post, url);

//Headers
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Cache-Control", "no-cache");

//Payload
var payload = JsonConvert.SerializeObject(
    new
    {
        Text = "Hello world"
    });
request.Content = new StringContent(payload, Encoding.UTF8, "application/json");

//Send
var response = await _httpClient.SendAsync(request);

//Handle response
if (response.IsSuccessStatusCode)
    return;

Dot net core solution点网核心解决方案

first using Newtonsoft.Json then write a method like this:首先使用Newtonsoft.Json然后编写这样的方法:

    public static string? LoginToken()
    {
        var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://url");
        httpWebRequest.ContentType = "application/json";
        httpWebRequest.Method = "POST";

        using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
           //  write your json content here
            string json = JsonConvert.SerializeObject(new
            {
                userName = ApiOptions.Username,
                password = ApiOptions.Password
            }
            );


            streamWriter.Write(json);
        }

        var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            var result = streamReader.ReadToEnd();
            return result;
        }

    }

This method return string .此方法返回string if you want to deserialize the string result to JSON , simply add this line at the end of the method:如果要将string结果反序列化为JSON ,只需在方法末尾添加以下行:

var result = streamReader.ReadToEnd();               
var json_result = JsonConvert.DeserializeObject<LoginTokenResponse>(result); // + add this code
        

Which LoginTokenResponse is the custom class you want to Deserialize the string result哪个LoginTokenResponse是您要反序列化字符串结果的自定义类

var data = Encoding.ASCII.GetBytes(json);

byte[] postBytes = Encoding.UTF8.GetBytes(json);

使用 ASCII 而不是 UFT8

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM