1

I've never had to do this before, because it's always only been an actual form that I've posted as that content type, but recently I had to post three variables like that, and I resorted to a sordid concatenation with & and =:

var content = new StringContent("grant_type=password&username=" + username + "&password=" + password.ToClearString(), Encoding.UTF8,
    "application/x-www-form-urlencoded");

I'm sure there must be a utility method that would do that, and do it better, with any necessary encoding. What would that be?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
ProfK
  • 49,207
  • 121
  • 399
  • 775

3 Answers3

1

If this is a POCO and just using the Newtonsoft library, you can use this as well:

public static class FormUrlEncodedContentExtension
{
    public static FormUrlEncodedContent ToFormUrlEncodedContent(this object obj)
    {
        var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);

        var keyValues = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

        var content = new FormUrlEncodedContent(keyValues);

        return content;
    }

}

And a sample usage would be:

var myObject = new MyObject {Grant_Type = "TypeA", Username = "Hello", Password = "World"};

var request = new HttpRequestMessage(HttpMethod.Post, "/path/to/post/to")
{
    Content = myObject.ToFormUrlEncodedContent()
};
var client = new HttpClient {BaseAddress = new Uri("http://www.mywebsite.com")};
var response = await client.SendAsync(request);
alltej
  • 6,787
  • 10
  • 46
  • 87
0

You should be able to use string interpolation for that. Something like:

var content = new StringContent($"grant_type=password&username={username}&password={password}", Encoding.UTF8, "application/x-www-form-urlencoded");

Or wrap this inside a helper/factory method:

public static class StringContentFactory
{
    public static StringContent Build(string username, string password)
    {
        return new StringContent($"grant_type=password&username={username}&password={password}", Encoding.UTF8, "application/x-www-form-urlencoded");
    }
}
alltej
  • 6,787
  • 10
  • 46
  • 87
  • That means I have to know the name of each property in the object, making the code useful for only one class, and it will have to be rewritten for each object you want to serialise. To be honest, this is a very bad solution. – ProfK Nov 24 '16 at 03:49
  • Sorry, I misunderstood the question. I thought it was something specific for that piece of code provided. So the solution was not really intended to be a generic one that can handle an object of different properties. – alltej Nov 25 '16 at 03:07
  • If it's just that one piece of code, why bother writing a method to encode it? I might as well just use the code as is. A basic tenet of methods is generality. – ProfK Nov 26 '16 at 05:01
0

Use reflection to get the property names and values and then use them to create a System.Net.Http.FormUrlEncodedContent

public static class FormUrlEncodedContentExtension {

    public static FormUrlEncodedContent ToFormUrlEncodedContent(this object obj) {
        var nameValueCollection = obj.GetType()
            .GetProperties()
            .ToDictionary(p => p.Name, p => (p.GetValue(obj) ?? "").ToString());

        var content = new FormUrlEncodedContent(nameValueCollection);

        return content;
    }

}

From there it is a simple matter of calling the extension method on an object to convert it to a FormUrlEncodedContent

var model = new MyModel {
    grant_type = "...",
    username = "...",
    password = "..."
};

var content = model.ToFormUrlEncodedContent();
Nkosi
  • 235,767
  • 35
  • 427
  • 472