JSON object and simple type for model in WebAPI using FromBody
I am creating a Web Api method that needs to accept JSON object and simple type. But all parameters are always null
.
My json looks like
{
"oldCredentials" : {
"UserName" : "user",
"PasswordHash" : "myCHqkiIAnybMPLzz3pg+GLQ8kM=",
"Nonce" : "/SeVX599/KjPX/J+JvX3/xE/44g=",
"Language" : null,
"SaveCredentials" : false
},
"newPassword" : "asdf"}
And my code looks like this:
[HttpPut("UpdatePassword")]
[Route("WebServices/UsersService.svc/rest/users/user")]
public void UpdatePassword([FromBody]LoginData oldCredentials, [FromBody]string newPassword)
{
NonceService.ValidateNonce(oldCredentials.Nonce);
var users = UserStore.Load();
var theUser = GetUser(oldCredentials.UserName, users);
if (!UserStore.AuthenticateUser(oldCredentials, theUser))
{
FailIncorrectPassword();
}
var iv = Encoder.GetRandomNumber(16);
theUser.EncryptedPassword = Encoder.Encrypt(newPassword, iv);
theUser.InitializationVektor = iv;
UserStore.Save(users);
}
source to share
The current JSON you are sending maps to the following classes
public class LoginData {
public string UserName { get; set; }
public string PasswordHash { get; set; }
public string Nonce { get; set; }
public string Language { get; set; }
public bool SaveCredentials { get; set; }
}
public class UpdateModel {
public LoginData oldCredentials { get; set; }
public string newPassword { get; set; }
}
[FromBody] can only be used once in action parameters
[HttpPut("WebServices/UsersService.svc/rest/users/user")]
public void UpdatePassword([FromBody]UpdateModel model) {
LoginData oldCredentials = model.oldCredentials;
string newPassword = model.newPassword;
NonceService.ValidateNonce(oldCredentials.Nonce);
var users = UserStore.Load();
var theUser = GetUser(oldCredentials.UserName, users);
if (!UserStore.AuthenticateUser(oldCredentials, theUser)) {
FailIncorrectPassword();
}
var iv = Encoder.GetRandomNumber(16);
theUser.EncryptedPassword = Encoder.Encrypt(newPassword, iv);
theUser.InitializationVektor = iv;
UserStore.Save(users);
}
source to share
More than one [FromBody] does not work in the Api . Check out Microsoft Official Blog
So now you can do this, create complex object
which should contain both your oldCredentials and newPassword. For example the LoginData class in my example below. And myLoginRequest is another object class that resides in deserialized
your LoginData.
[HttpPut("UpdatePassword")]
[Route("WebServices/UsersService.svc/rest/users/user")]
public void UpdatePassword([FromBody]LoginData MyCredentials)
{
loginRequest request = JsonConvert.DeserializeObject<myLoginRequest>
(json.ToString());
// then you can do the rest
source to share
According to Parameter Binding in ASP.NET Web Interface , "At most one parameter is allowed to be read from the message body." This means that only one parameter can contain [FromBody]. So it won't work in this case. Create one complex object and add the required properties to it. You can add newPassword to your complex object to make it work.
source to share
public class DocumentController : ApiController
{
[HttpPost]
public IHttpActionResult PostDocument([FromBody] Container data)
{
try
{
if (string.IsNullOrWhiteSpace(data.Document)) return ResponseMessage(Request.CreateResponse(HttpStatusCode.NoContent, "No document attached"));
return ResponseMessage(IndexDocument(data, Request));
}
catch (Exception ex)
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.NotAcceptable, ex.Message));
}
}
}
public class InsuranceContainer
{
[JsonProperty("token")]
public string Token { get; set; }
[JsonProperty("document")]
public string Document { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
var fileAsBytes = File.ReadAllBytes(@"C:\temp\tmp62.pdf");
String asBase64String = Convert.ToBase64String(fileAsBytes);
var newModel = new InsuranceContainer
{
Document = asBase64String,
Text = "Test document",
};
string json = JsonConvert.SerializeObject(newModel);
using (var stringContent = new StringContent(json, System.Text.Encoding.UTF8, "application/json"))
using (var client = new HttpClient())
{
var response = await client.PostAsync("https://www.mysite.dk/WebService/api/Document/PostDocument", stringContent);
Console.WriteLine(response.StatusCode);
var message = response.Content.ReadAsStringAsync();
Console.WriteLine(message.Result);
}
source to share