Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I PostAsync() with multiple simple types?

How do I PostAsync() with multiple simple types as parameters, I have the action controller below:

[HttpPost]
[Route("users/verifyLoginCredentials/{username}/{password}")]
public IHttpActionResult VerifyLoginCredentials([FromUri]string username, string password)
{

   //Do Stuff......
   return Ok("Login Successful");

}

I am trying to invoke it from a .Net Framerwork 4.5 Client application as below:

static async Task<Uri> CreateProductAsync(string username, string password)
{


     HttpClient client = new HttpClient();
     client.BaseAddress = new Uri(uri);
     client.DefaultRequestHeaders.Accept.Clear();
     client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
     client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

     var value = new Dictionary<string, string>
     {
        { "username", "test123" }
     };

     var content = new FormUrlEncodedContent(value);
     var result = await client.PostAsync("users/verifyLoginCredentials/{username}/{password}", content);
     string resultContent = await result.Content.ReadAsStringAsync();

     result.EnsureSuccessStatusCode();

     // return URI of the created resource.
     return result.Headers.Location;
}

I have tried mutiple ways so far and have done a lot of reading, most recently here.

I understand that it is easier to deal with complex types than it is to deal with simple types and that by default complex types are encoded into the request body/content while simple types are encoded into the URI.

I have tried to post data by sending key/value pairs encoded using FormUrlEncodedContent(string) by sending Json through StringContent(), I have tried with both single and multiple parameters but I understand the limitation is only with complex types now.

I have read many MSDN posts and tutorials, maybe I am missing a crucial piece of information.

The controller action above does get executed but with both paramerters having a string value of "{username}" and "{password}"

like image 868
Aboudi Avatar asked Oct 18 '25 04:10

Aboudi


2 Answers

When you write

[Route("users/verifyLoginCredentials/{username}/{password}")]

You are saying "match the username and password parameters, in the specified order, from the Uri", so whatever you send through the body of the POST will be ignored.

You are explicitly passing {username} and {password} as parameters:

var result = await client.PostAsync("users/verifyLoginCredentials/{username}/{password}", content);

You should be doing this instead:

var message = new HttpRequestMessage(HttpMethod.Post, "users/verifyLoginCredentials/username/test123");
var result = await client.SendAsync(message);
string resultContent = await result.Content.ReadAsStringAsync();

If you want to post the data as the body instead of part of the URL, use this:

[Route("users/VerifyLoginCredentials")]
public IHttpActionResult VerifyLoginCredentials(string username, string password)

 var value = new Dictionary<string, string>
 {
    { "username", "yourUsername" },
    { "passwird", "test123" }
 };

 var content = new FormUrlEncodedContent(value);
 var result = await client.PostAsync("users/verifyLoginCredentials/", content);
 string resultContent = await result.Content.ReadAsStringAsync();
like image 145
Camilo Terevinto Avatar answered Oct 19 '25 17:10

Camilo Terevinto


The simplest way would be to create a model which contains everything you need.

An example would be:

public class LoginModel 
{
    [Required]
    public string Username { get;set }

    [Required]
    public string Password { get;set }
}

you can now do:

[HttpPost]
[Route("users/verifyLoginCredentials")]
public IHttpActionResult VerifyLoginCredentials([FromBody]LoginModel model)
{
   //validate your model    
   if ( model == null || !ModelState.IsValid )     
   {
       return BadRequest();
   }

   //stuff
   return Ok();
}

To use it you would do something like this:

var model = new LoginModel { Username = "abc", Password="abc" } ;

using (var client = new HttpClient())
{               
    var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");               

    var result = await client.PostAsync("your url", content);
    return await result.Content.ReadAsStringAsync();
}

Do not send passwords in the URI as anyone can intercept the request and see what the password is.

Any data which needs to remain secret you send it in the body of the request and make sure the request is over https as that encodes the headers and the post body so no one can look at the data.

like image 23
Andrei Dragotoniu Avatar answered Oct 19 '25 16:10

Andrei Dragotoniu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!