简体   繁体   中英

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}"

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();

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.

[HttpPost("{coverPagePath}")] 
public void Post([FromRoute] string coverPagePath, [FromBody] UserCoverpage value)
{
   var args = new[] { WebUtility.UrlDecode(coverPagePath).Replace("\\", "/") };
   userCoverpageService.Create(value, args);
}
...
//test:
var json = item.SerializeToJson(true);
HttpContent payload = new StringContent(json, Encoding.UTF8, "application/json");

// act
var response = await httpClient.PostAsync($"/api/UserCoverpage/{coverPagePath}", payload); 
var data = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
output.WriteLine(data);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM