Search code examples
c#dotnet-httpclient

c# Build URL encoded query from model object for HttpClient


Need to build URL encoded query from model object for HttpClient

My Model is

class SaveProfileRequest
{
    public string gName { get; set; }
    public string gEmail { get; set; }
    public long gContact { get; set; }
    public string gCompany { get; set; }
    public string gDeviceID { get; set; }
    public string Organization { get; set; }
    public string profileImage { get; set; }
    public string documentImagefront { get; set; }
    public string documentImageback { get; set; }
}

SaveProfileRequest request = new SaveProfileRequest() { gName = name, gEmail = email, gContact = phonenumber, gCompany = company,
            gDeviceID = deviceId, Organization = "", profileImage = "", documentImageback = "", documentImagefront = "" };

string response = await RequestProvider.PostAsync<string, SaveProfileRequest>(uri, request);

I have a working code for content type JSON

content = new StringContent(JsonConvert.SerializeObject(data));

content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

Where data is of type TInput

Tried

content = new StringContent(System.Net.WebUtility.UrlEncode(JsonConvert.SerializeObject(data)));

content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

but didn't workout


Solution

  • JsonConvert produces only json content. For urlencoded query you should construct instance of FormUrlEncodedContent. As constructor parameter it takes collection of KeyValuePair<string, string>. So the main trick is to build this collection for model object.

    You could use reflection for this purpose. But there is a simpler solution based on Json.net. It was described here and following ToKeyValue() extension method is a copy/paste from that blog post:

    public static class ObjectExtensions
    {
        public static IDictionary<string, string> ToKeyValue(this object metaToken)
        {
            if (metaToken == null)
            {
                return null;
            }
    
            JToken token = metaToken as JToken;
            if (token == null)
            {
                return ToKeyValue(JObject.FromObject(metaToken));
            }
    
            if (token.HasValues)
            {
                var contentData = new Dictionary<string, string>();
                foreach (var child in token.Children().ToList())
                {
                    var childContent = child.ToKeyValue();
                    if (childContent != null)
                    {
                        contentData = contentData.Concat(childContent)
                            .ToDictionary(k => k.Key, v => v.Value);
                    }
                }
    
                return contentData;
            }
    
            var jValue = token as JValue;
            if (jValue?.Value == null)
            {
                return null;
            }
    
            var value = jValue?.Type == JTokenType.Date ?
                jValue?.ToString("o", CultureInfo.InvariantCulture) :
                jValue?.ToString(CultureInfo.InvariantCulture);
    
            return new Dictionary<string, string> { { token.Path, value } };
        }
    }
    

    Now you could build the url-encoded content as easy as:

    var keyValues = data.ToKeyValue();
    var content = new FormUrlEncodedContent(keyValues);