magicalKhachapuri
magicalKhachapuri

Reputation: 623

Web API not receiving the json of serialized object

client side code:

        public async Task<ActionResult> Login(UserLoginModel user)
    {
        UserModel data = new UserModel
        {
            Username = user.Username,
            Password = user.Password.GenerateHash()
        };

        var serializedData = JsonConvert.SerializeObject(data);

        var url = "http://localhost:55042/api/Login";

        var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
        httpWebRequest.ContentType = "application/json";
        httpWebRequest.Method = "POST";
        httpWebRequest.Accept = "application/json";

        using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            streamWriter.Write(serializedData);
            streamWriter.Flush();
            streamWriter.Close();
        }

        bool deserializedResult = false;
        using (var response = httpWebRequest.GetResponse() as HttpWebResponse)
        {
            if (httpWebRequest.HaveResponse && response != null) {
                using (var streamReader = new StreamReader(response.GetResponseStream())) {
                    var result = streamReader.ReadToEnd();
                    deserializedResult = JsonConvert.DeserializeObject<bool>(result);
                }
            }
        }

        return deserializedResult ? View() : throw new NotImplementedException();
    }

Web API:

    [HttpPost]
    [Route("api/Login")]
    public IHttpActionResult ValidateLogin([FromBody]UserModel user)
    {
        var result = _service.FetchUser(user);

        return Json(result);
    }

UserModel

[Serializable]
public class UserModel
{
    public int? ID { get; set; }

    public string Username { get; set; }

    public string Password { get; set; }

    public string Firstname { get; set; }

    public string Lastname { get; set; }

    public string Email { get; set; }

    public string NumberI { get; set; }

    public string NumberII { get; set; }

    public DateTime? CreateDate { get; set; }
}

No data arrives in ValidateLogin, even when I pass parameters with the postman.

I have searched a lot, found no solution at all, tried all the code snippets, understood them then came back and so on, I'm stuck, what is wrong?

Upvotes: 2

Views: 3144

Answers (1)

Alexander
Alexander

Reputation: 9642

Solution 1

Just remove [Serializable] attribute from UserModel and everything will work fine.

Solution 2

When serializing data on client use json serialization behavior as Web API does

var serializedData = JsonConvert.SerializeObject(data, new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver
    {
        IgnoreSerializableAttribute = false
    }
});

Now Web API will correctly deserialize passed model.

This happens because starting from some version Json.NET considers if object is marked as Serializable. By default without that attribute all public members (properties and fields) are serialized. Serialization of the following class

public class UserModel
{
    public string Username { get; set; }

    public string Password { get; set; }
}

gives the following result

{
  "Username": "name",
  "Password": "pass"
}

But when class is marked by [Serializable] attribute and IgnoreSerializableAttribute setting is false all private and public fields are serialized and result is the following

{
  "<Username>k__BackingField": "name",
  "<Password>k__BackingField": "pass"
}

By default serializer ignores [Serializable] attribute but in Web API the IgnoreSerializableAttribute is set to false. So now it's easy to see why server couldn't properly deserialize given model in your case.

Upvotes: 8

Related Questions