3

I am trying to post to a .net controller using HttpClient, but the controller is never being hit....

Here is how I am trying to post:

NameValueCollection data = new NameValueCollection();
data.Add("someField", "someValue");

using (HttpClient client = new HttpClient())
{
    HttpResponseMessage response = await client.PostAsync(url,
        new FormUrlEncodedContent(data.Cast<string>()
            .SelectMany(key => data.GetValues(key), (key, value) => new { key, value })
            .ToDictionary(p => p.key, p => p.value))
    );
}

And then my controller:

[HttpPost("MyController")]
public void MyControllerMethod(string someField)
{
    // never being hit....
}

I can change it slightly and the method gets hit.... But in the following scenario, someField is null and it shouldn't be:

NameValueCollection data = new NameValueCollection();
data.Add("someField", "someValue");

var dictionary = data.Cast<string>()
    .SelectMany(key => data.GetValues(key), (key, value) => new { key, value })
    .ToDictionary(p => p.key, p => p.value);

var json = JsonConvert.SerializeObject(dictionary);
StringContent stringContect = new StringContent(json);

using (HttpClient client = new HttpClient())
{
    HttpResponseMessage response = await client.PostAsync(url, stringContect);
}

But like I said, in that scenario, the param someField isn't mapping the way I expect it to and is showing as NULL instead of "someValue"....

Any ideas?

Thanks!

2
  • FormUrlEncodedContent wants an IEnumerable<Keypair<string,string>>. You're using an NameValueCollection which supports duplicate keys, but your .ToDictionary would break if there were any. IMHO If you don't need to support multiple keys with the same name, just use a Dictionary<string,string> in the first place. Commented Apr 26, 2022 at 7:09
  • Hi @Mike Luken, any update? Commented Apr 27, 2022 at 8:05

2 Answers 2

2

You should make model class, which will include all keys from form, like that:

public class FormModel // Or any name
{
    public string SomeField { get; set; }

    // Any fields
}

And then bind data from request to argument of controller method with FromFormAttribute, like that:

[HttpPost("MyController")]
public void MyControllerMethod([FromForm] FormModel model)
{
    var someField = model.SomeField;

    // Your logic
}

Read more about model binding here.

Sign up to request clarification or add additional context in comments.

Comments

2

Two ways to post single string parameter by using HttpClient below:

1.From Body

var json = JsonConvert.SerializeObject("someValue");
StringContent stringContect = new StringContent(json, Encoding.UTF8, "application/json");

using (HttpClient client = new HttpClient())
{
    HttpResponseMessage response = await client.PostAsync("https://localhost:portNum/xxx", 
                                                    stringContect);
}

Controller:

[HttpPost]
public async Task<ActionResult> Post([FromBody]string someField)
{
    //...
}

2.From Form

var formContent = new FormUrlEncodedContent(new[]
{
    new KeyValuePair<string, string>("someField", "someValue"),
});

using (HttpClient client = new HttpClient())
{
    HttpResponseMessage response = await client.PostAsync("https://localhost:portNum/xxx", 
                                                      formContent);
}

Controller:

[HttpPost]
public async Task<ActionResult> Index([FromForm]string someField)
{
    //...           
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.