5

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);
}
4
  • Yep, i use postman to test my api. Commented Apr 12, 2017 at 9:40
  • Please check my bellow answer and let me know whether its working or not Commented Apr 12, 2017 at 10:03
  • @Kingpin, clarify if using asp.net-web-api or asp.net-core Commented Apr 12, 2017 at 10:14
  • I am creating an ASP.NET Core Web Application with the Web API Template. Because it is just a rest service. Commented Apr 12, 2017 at 10:21

4 Answers 4

5

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);
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, creating a help-class combing both was the solution. I was used to wcf where it is possible to have more than one paramter.
It is possible. but the way you are sending the data and trying to access in the parameters don't match up. that is why they were always null.
3

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

Comments

2

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.

Comments

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


    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.