简体   繁体   中英

JSON Object and Simple Type to Model in WebAPI using FromBody

I am creating a Web Api method that should accept a JSON Object and a 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:

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

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

More than one [FromBody] does not work in Api. Check this Microsoft Official blog

So now you can do like this, create a complex object which should contain both your oldCredentials and newPassword. For example LoginData class in my example bellow. And myLoginRequest is another object class which is to 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

As per the Parameter Binding in ASP.NET Web API , "At most one parameter is allowed to read from the message body". Means only one parameter can contain [FromBody]. So in this case it will not work. Create one complex object and add required properties to it. You can add newPassword to your complex object to make it work.

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


    }

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