JSON 使用 FromBody 在 WebAPI 中建模的对象和简单类型

JSON Object and Simple Type to Model in WebAPI using FromBody

我正在创建一个 Web Api 方法,它应该接受一个 JSON 对象和一个简单类型。但是所有参数总是null

我的json长得像

{
"oldCredentials" : {
    "UserName" : "user",
    "PasswordHash" : "myCHqkiIAnybMPLzz3pg+GLQ8kM=",
    "Nonce" : "/SeVX599/KjPX/J+JvX3/xE/44g=",
    "Language" : null,
    "SaveCredentials" : false
},
"newPassword" : "asdf"}

我的代码如下:

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

多个 [FromBody] 在 Api 中不起作用。检查这个 Microsoft Official blog

现在您可以这样做,创建一个 complex object,其中应包含您的旧凭据和新密码。例如 LoginData class 在我下面的例子中。 myLoginRequest 是另一个对象 class,它指向 deserialized 您的 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

根据 Parameter Binding in ASP.NET Web API、"At most one parameter is allowed to read from the message body"。表示只有一个参数可以包含[FromBody]。所以在这种情况下是行不通的。创建一个复杂对象并向其添加所需的属性。您可以将 newPassword 添加到您的复杂对象以使其工作。

当前JSON您正在向以下类

发送地图
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]在动作参数中只能使用一次

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


    }