web-dev-qa-db-fra.com

Comment définir une grande chaîne à l'intérieur de HttpContent lors de l'utilisation de HttpClient?

J'ai donc créé un HttpClient et je publie des données en utilisant HttpClient.PostAsync().

J'ai défini le HttpContent en utilisant

HttpContent content = new FormUrlEncodedContent(post_parameters); où post_parameters est une liste de paires de valeurs clés List<KeyValuePair<string, string>>

Le problème est que lorsque le HttpContent a une grande valeur (une image convertie en base64 à transmettre) j'obtiens une URL est une erreur trop longue. Cela a du sens - car l'URL ne peut pas dépasser 32 000 caractères. Mais comment puis-je ajouter les données dans le HttpContent sinon?

Veuillez aider.

32
Muraad

Je l'ai découvert avec l'aide de mon ami. Ce que vous voudriez faire est d'éviter d'utiliser FormUrlEncodedContent (), car il a des restrictions sur la taille de l'uri. Au lieu de cela, vous pouvez effectuer les opérations suivantes:

    var jsonString = JsonConvert.SerializeObject(post_parameters);
    var content = new StringContent(jsonString, Encoding.UTF8, "application/json");

Ici, nous n'avons pas besoin d'utiliser HttpContent pour publier sur le serveur, StringContent fait le travail!

55
Muraad

FormUrlEncodedContent utilise en interne Uri.EscapeDataString: par réflexion, je peux voir que cette méthode a des constantes limitant la taille de la longueur de la requête.

Une solution possible consiste à créer une nouvelle implémentation de FormUrlEncodedContent en utilisant System.Net.WebUtility.UrlEncode (.net 4.5) pour contourner cette limitation.

public class MyFormUrlEncodedContent : ByteArrayContent
{
    public MyFormUrlEncodedContent(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
        : base(MyFormUrlEncodedContent.GetContentByteArray(nameValueCollection))
    {
        base.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
    }
    private static byte[] GetContentByteArray(IEnumerable<KeyValuePair<string, string>> nameValueCollection)
    {
        if (nameValueCollection == null)
        {
            throw new ArgumentNullException("nameValueCollection");
        }
        StringBuilder stringBuilder = new StringBuilder();
        foreach (KeyValuePair<string, string> current in nameValueCollection)
        {
            if (stringBuilder.Length > 0)
            {
                stringBuilder.Append('&');
            }

            stringBuilder.Append(MyFormUrlEncodedContent.Encode(current.Key));
            stringBuilder.Append('=');
            stringBuilder.Append(MyFormUrlEncodedContent.Encode(current.Value));
        }
        return Encoding.Default.GetBytes(stringBuilder.ToString());
    }
    private static string Encode(string data)
    {
        if (string.IsNullOrEmpty(data))
        {
            return string.Empty;
        }
        return System.Net.WebUtility.UrlEncode(data).Replace("%20", "+");
    }
}

Pour envoyer du contenu volumineux, il est préférable d'utiliser StreamContent .

28
Cybermaxs

Ce code fonctionne pour moi, fondamentalement, vous envoyez des données de publication "application/x-www-form-urlencoded" dans le contenu de la chaîne sur le client http, j'espère que cela peut aider toute personne ayant le même problème que moi

void sendDocument()
    {
        string url = "www.mysite.com/page.php";
        StringBuilder postData = new StringBuilder();
        postData.Append(String.Format("{0}={1}&", HttpUtility.HtmlEncode("prop"), HttpUtility.HtmlEncode("value")));
        postData.Append(String.Format("{0}={1}", HttpUtility.HtmlEncode("prop2"), HttpUtility.HtmlEncode("value2")));
        StringContent myStringContent = new StringContent(postData.ToString(), Encoding.UTF8, "application/x-www-form-urlencoded");
        HttpClient client = new HttpClient();
        HttpResponseMessage message = client.PostAsync(url, myStringContent).GetAwaiter().GetResult();
        string responseContent = message.Content.ReadAsStringAsync().GetAwaiter().GetResult();
    }
3
Chris