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

      

+3


source to share


4 answers


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

      

+2


source


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

      

+1


source


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.

+1


source


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


    }

      

0


source







All Articles