簡體   English   中英

如何使用 C# 將 JSON 發布到服務器?

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

這是我正在使用的代碼:

// 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;

當我運行它時,我總是收到 500 內部服務器錯誤。

我究竟做錯了什么?

我這樣做和工作的方式是:

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();
}

我寫了一個庫以更簡單的方式執行此任務,它在這里: https ://github.com/ademargomes/JsonRequest

Ademar 的解決方案可以通過利用JavaScriptSerializerSerialize方法來提供對象到 JSON 的隱式轉換來改進。

此外,可以利用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();
}

HttpClient類型是比WebClientHttpWebRequest更新的實現。 WebClientWebRequest都已被標記為過時。 [1]

您可以簡單地使用以下幾行。

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"));
}

當您多次需要HttpClient時,建議只創建一個實例並重用它或使用新的HttpClientFactory [2]

對於 FTP,由於 HttpClient 不支持,我們建議使用第三方庫。

@docs.microsoft.com [3]


從 dotnet core 3.1 開始,您可以使用System.Text.Json中的JsonSerializer創建您的 json 字符串。

string myJson = JsonSerializer.Serialize(credentialsObj);

在 Sean 的帖子之后,沒有必要嵌套 using 語句。 通過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();
}

如果您需要異步調用,請使用

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;
        }

    }

我最近想出了一種更簡單的方法來發布 JSON,並增加了從我的應用程序中的模型轉換的額外步驟。 請注意,您必須為控制器創建模型[JsonObject]才能獲取值並進行轉換。

要求:

 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;
     // ...
  }

模型:

[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; }
}

服務器端:

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

注意您正在使用的 Content-Type :

application/json

資料來源:

RFC4627

其他帖子

警告! 我對這個問題有非常強烈的看法。

.NET 現有的 Web 客戶端對開發人員不友好! WebRequestWebClient是“如何挫敗開發人員”的主要例子。 它們很冗長且使用起來很復雜; 當您只想在 C# 中執行一個簡單的 Post 請求時。 HttpClient在解決這些問題方面做了一些工作,但仍然不足。 最重要的是,微軟的文檔很糟糕……真的很糟糕; 除非您想篩選一頁又一頁的技術簡介。

開源來救援。 有三個優秀的開源免費 NuGet 庫可供選擇。 謝天謝地! 這些都得到了很好的支持,記錄在案,是的,很容易 - 更正......超級容易 - 使用。

  • ServiceStack.Text - 快速、輕便且有彈性。
  • RestSharp - 簡單的 REST 和 HTTP API 客戶端
  • Flurl - 一個流暢、可移植、可測試的 HTTP 客戶端庫

它們之間沒有太多區別,但我會給 ServiceStack.Text 一點優勢……

  • Github stars大致相同。
  • 未解決的問題以及重要的是,任何問題關閉的速度有多快? ServiceStack 在這里獲得了最快的問題解決和沒有未解決問題的獎項。
  • 文檔? 都有很好的文檔; 然而,ServiceStack 將其提升到了一個新的水平,並以其文檔的“黃金標准”而聞名。

好的 - 那么 JSON 格式的 Post 請求在 ServiceStack.Text 中是什么樣的?

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

那是一行代碼。 簡潔輕松! 將上述內容與 .NET 的 Http 庫進行比較。

未提及此選項

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);
}

實現此目的的一些不同且干凈的方法是使用 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;
     }
}

我終於通過包含.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");
}

我發現這是發布讀取 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);
}

我正在使用 Microsoft 的System.Text.Json對 JSON 進行序列化和反序列化。 請參閱NuGet

我就是這樣做的

//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;

點網核心解決方案

首先使用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;
        }

    }

此方法返回string 如果要將string結果反序列化為JSON ,只需在方法末尾添加以下行:

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

哪個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