C # kullanarak bir sunucuya JSON göndermek nasıl?


269

İşte kullanıyorum kodu:

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

Bunu çalıştırdığımda, her zaman 500 dahili sunucu hatası alıyorum.

Neyi yanlış yapıyorum?


1
İlk olarak, gönderdiğiniz verilerin sunucunun beklediğinden emin olun.
LB

aslında, geçersiz veri gönderiyorum gibi görünüyor ...
Arsen Zahray

Çalışma kolaylığı için görsel stüdyonuza da json kütüphanesi ekleyebilirsiniz
Alireza Tabatabaeian

@Arsen - Sunucu hatalı biçimlendirilmiş verilerle kilitlenmemelidir. Hata raporu gönderin.
jww

Yanıtlar:


396

Benim yaptığım ve çalıştığım yol:

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

Bu görevi daha basit bir şekilde gerçekleştirmek için bir kütüphane yazdım, burada: https://github.com/ademargomes/JsonRequest

Umarım yardımcı olur.


3
Bence json string satırı şöyle olmalı: string json = "{\" user \ ": \" test \ "," + "\" password \ ": \" bla \ "}"; Eğer bir \ eksik gibi görünüyor
Rüya Lane

3
Her zaman "application / json" kullanın (başka bir nedenden dolayı metin / json gerekli değilse , örneğin: entwicklungsgedanken.de/2008/06/06/… ). Kredilendirme şuraya gider: stackoverflow.com/questions/477816/… .
Yaniv

34
StreamWriter.Flush (); ve streamWriter.Close (); bir kullanım bloğunun içinde olduğunuz için gerekli değildir. Kullanım bloğunun sonunda, akış yazar yine de kapanacaktır.
Ruchira

1
JSON'u manuel olarak oluşturmayın. JSON enjeksiyonuna izin veren hatalar yapmak kolaydır.
Florian Winter

5
@ user3772108 Bkz. stackoverflow.com/a/16380064/2279059 . Newtonsoft JSON.Net gibi bir JSON kütüphanesi kullanın ve bir nesneden JSON dizesini oluşturun veya serileştirme kullanın. Bu basitlik için ihmal edildiğini anlıyorum (basitlik kazancı en az olmasına rağmen), ancak yapılandırılmış veri dizelerini (JSON, XML, ...) biçimlendirmek, önemsiz senaryolarda bile bunu yapmak ve insanları bu kodu kopyalamaya teşvik etmek için çok tehlikelidir. .
Florian Kış

149

Ademar çözeltisi kaldıraç iyileştirilebilir JavaScriptSerializersitesindeki SerializeJSON nesnenin örtülü dönüşümünü sağlamak için yöntem.

Buna ek olarak, kaldıraç mümkündür usingçağıran açıkça ihmal amacıyla ifadenin varsayılan işlevselliğini Flushve Close.

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

1
Bu ve yukarıdaki kod arasındaki fark nedir, bir şey eksik mi?
JMK

16
Bu, el yapımı yerine geçerli JSON oluşturmak için JavaScriptSerializer'ın Serialize yöntemini kullanır.
Sean Anderson

Aşağıdaki Jean F'nin cevabına bakın - bir yorum olmalı. İçerik türünün application/jsondoğru olmasına dikkat edin .
Lucas

@SeanAnderson "Uzak sunucuya bağlanılamıyor" hatasını almaya devam ediyorum.
ralphgabb

3
@LuzanBaral sadece bir montaja ihtiyacınız var: System.Web.Extensions
Norbrecht

60

HttpClientTipi daha yeni bir uygulamasıdır WebClientve HttpWebRequest.

Aşağıdaki satırları kullanabilirsiniz.

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

resim açıklamasını buraya girin

Bir HttpClientkereden fazla ihtiyacınız olduğunda, yalnızca bir örnek oluşturmanız ve yeniden kullanmanız veya yenisini kullanmanız önerilir HttpClientFactory.


5
HttpClient ile ilgili küçük bir not, genel fikir birliği, onu atmamanız gerektiğidir. Nesne iş parçacığı açısından güvenlidir ve yeniden kullanılması amaçlanmıştır. stackoverflow.com/questions/15705092/…
Jean F.

1
@JeanF. Hey Giriş için teşekkürler. Daha önce de belirttiğim gibi, yalnızca bir örnek oluşturmalı veya HttpClientFactory. Bağlantılı sayıdaki tüm cevapları okumadım ama fabrikadan bahsetmediği için güncellenmesi gerektiğini düşünüyorum.
NtFreX

33

Sean'ın gönderisine ek olarak, kullanım ifadelerini yuvalamak gerekli değildir. usingStreamWriter tarafından bloğun sonunda yıkanır ve kapatılır, böylece Flush()ve Close()yöntemlerini açıkça çağırmanıza gerek kalmaz :

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

1
şimdi bu cevap ve Sean Anderson'ın yanıtı, Sean'ın görevini düzenlediği gibi tamamen aynı.
faza

Hey bu çok harika.Teşekkürler.Ama json'umuzda alt düğümlerimiz varsa verileri nasıl aktaracağız?
user2728409

1
Serileştirici json'daki alt düğümleri işleyebilir - sadece geçerli bir json nesnesi sağlamanız gerekir.
David Clarke

14

Eğer zaman uyumsuz olarak aramanız gerekiyorsa

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

    }

3
Bu çözümü gönderdiğiniz için teşekkür ederiz Vivek. Senaryomuzda bu yazıda başka bir çözüm denedik ve System.Threating istisnalar, benim ne zaman senkron mesajlar engelleme iş parçacıkları olduğunu varsayıyorum nedeniyle, bizim uygulamada yara. Kodunuz sorunumuzu çözdü.
Ken Palmer

Büyük olasılıkla bayta dönüştürmeniz gerekmediğini unutmayın. Yapabilmeniz gerekir postStream.Write(postData);- ve API'ye bağlı olarak, request.ContentType = "application/json";bunun yerine kullanmak zorunda kalabilirsiniz text/json.
vapcguy


11

Kısa bir süre önce, bir JSON yayınlamak için çok daha basit bir yol buldum. Değerleri almak ve dönüşümü yapmak için kumandanızın modelini [JsonObject] yapmanız gerektiğini unutmayın.

İstek:

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

Sunucu tarafı:

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

6

Bu seçenek belirtilmemiştir:

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

2
Net 4.5.2'den beri bu seçenek artık kullanılamamaktadır. buraya bakın stackoverflow.com/a/40525794/2161568
Downhillski

Yukarıdaki yoruma göre aşağı oy - bu mevcut olmadığından, muhtemelen cevabı kaldırmalıdır.
NovaDev

1
Herkesin .net'in en son sürümlerini kullanmadığı için bu cevabı küçümsemek için iyi bir neden değildir ve bu geçerli bir cevaptır.
Ellisan

4

Bunu başarmanın farklı ve temiz bir yolu HttpClient'i şu şekilde kullanmaktır:

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

4
Ancak PostAsJsonAsync, .NET 4.5.2'den beri artık kullanılamıyor. PostAsyncBunun yerine kullanın . Daha burada
Zachary Keener

HttpClient genellikle böyle bir usingifadede kullanılmamalıdır
p3tch

Bence IDisposablebir sebeple arayüzü uyguluyor
Dima Daron

4

UYARI! Bu konuda çok güçlü bir görüşüm var.

.NET'in mevcut web istemcileri geliştirici dostu değildir! WebRequest ve WebClient , "geliştiriciyi nasıl sinirlendireceğinizin" başlıca örnekleridir. Onlar ayrıntılı ve çalışmak için karmaşık; tüm yapmak istediğiniz zaman C # basit bir Mesaj isteği. HttpClient bu sorunları ele almanın bir yoludur, ancak yine de yetersiz kalmaktadır. Üstelik Microsoft'un belgeleri kötü… gerçekten kötü; teknik bulanıklaştırma sayfalarında ve sayfalarında gezinmek istemiyorsanız.

Kurtarmaya açık kaynak. Alternatif olarak üç mükemmel açık kaynaklı, ücretsiz NuGet kütüphanesi vardır. Çok şükür! Bunların hepsi iyi desteklenmiş, belgelenmiş ve evet, kolay düzeltme… süper kolay - çalışmak.

  • ServiceStack.Text - hızlı, hafif ve esnek.
  • RestSharp - basit REST ve HTTP API İstemcisi
  • Flurl - akıcı, taşınabilir, test edilebilir bir HTTP istemci kütüphanesi

Aralarında pek bir şey yok, ama ben ServiceStack.Text hafif kenar vermek istiyorum ...

  • Github yıldızları kabaca aynı.
  • Açık Sayılar ve önemli olan herhangi bir sorunun ne kadar hızlı kapatılması ServiceStack, en hızlı sorun çözümü ve açık sorun olmaması için ödülü burada alır.
  • Belgeler? Hepsinin harika belgeleri var; ancak, ServiceStack bir sonraki seviyeye çıkarır ve dokümantasyon için 'Altın standardı' ile bilinir.

Peki, JSON'da bir Gönderme İsteği ServiceStack.Text içinde neye benziyor?

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

Bu bir kod satırı. Özlü ve kolay! Yukarıdakileri .NET'in Http kütüphaneleriyle karşılaştırın.


3

Sonunda .Result dahil ederek senkronizasyon modunda çağırdım

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

1

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

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

UFT8 yerine ASCII kullanın


2
kulağa kötü bir fikir gibi geliyor, bir şey mi kaçırıyorum?
CyberFox

JSON UTF8 karakterleri içerebilir, bu korkunç bir fikir gibi görünüyor.
Adrian Smith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.