0

I'm trying to post an user object from a c# client application to a web api which should store a new user into the database. The model is based on the same class. At the moment the client this function for doing the post:

public static async Task CreateNewUser(string userName, string eMail, string password, string name, string firstName)
        {
            User newUser = new User(userName, eMail, password, name, firstName);
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(restAddress);
                try
                {
                    var response = await client.PostAsync(restAddress + "api/Users", newUser);
                    response.EnsureSuccessStatusCode();
                }
                catch (Exception e)
                {

                    ExecutionConsole.WriteError(e.ToString());
                }
            }
        }

And the controller in the Web API has this function:

// POST: api/Users
        [ResponseType(typeof(User))]
        public async Task<IHttpActionResult> PostUser(User user)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            db.Users.Add(user);

            try
            {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateException)
            {
                if (UserExists(user.Username))
                {
                    return Conflict();
                }
                else
                {
                    throw;
                }
            }

            return CreatedAtRoute("DefaultApi", new { id = user.Username }, user);
        }

The API returns 400 (Bad Request). The Web API has this configuration at the moment:

 public void Configuration(IAppBuilder appBuilder)
        {
            HttpConfiguration config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            appBuilder.UseWebApi(config);
        }

EDIT:

The User model:

public class User
            {
                public User(string userName, string email, string password) : this(userName, email, password, null, null)
                {

                }
                public User(string userName, string email, string password, string Name, string firstName)
                {
                    this.Username = userName;
                    this.Email = email;
                    this.Password = password;
                    this.Name = Name;
                    this.firstName = firstName;
                }

                [Key, Required]
                public string Username { get; set; }
                public string Name { get; set; }
                public string firstName { get; set; }
                [Required]
                public string Email { get; set; }
                [Required]
                public string Password { get; set; }
                public virtual ICollection<Playlist> CreatedPlaylists { get; set; }
                public virtual ICollection<Track> SavedTracks { get; set; }

            }

The HTTPRequest (Rest API is the name of my Web API project):

{Method: POST, RequestUri: 'http://localhost:2468/api/Users', Version: 1.1, Content: System.Net.Http.ObjectContent`1[[RestAPI.Model.User, RestAPI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], Headers:
{
  Content-Type: application/json; charset=utf-8
  Content-Length: 143
}}
    Content: {System.Net.Http.ObjectContent<RestAPI.Model.User>}
    Headers: {}
    Method: {POST}
    Properties: Count = 0
    RequestUri: {http://localhost:2468/api/Users}
    Version: {1.1}

The HTTPContent:

{System.Net.Http.ObjectContent<RestAPI.Model.User>}
    Formatter: {System.Net.Http.Formatting.JsonMediaTypeFormatter}
    Headers: {Content-Type: application/json; charset=utf-8
Content-Length: 143
}
    ObjectType: {Name = "User" FullName = "RestAPI.Model.User"}
    Value: {RestAPI.Model.User}

EDIT #2:

The response body:

    Id = 22, 
    Status = RanToCompletion, 
    Method = "{null}", 
    AsyncState: null
    CancellationPending: false
    CreationOptions: None
    Exception: null
    Id: 22
    Result: {Message:"The request is invalid.",
    ModelState:{"user.Username":["Unable to find a constructor to use for type ClAuP.RestAPI.Model.User. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'Username', line 1, position 12."]}}"
    Status: RanToCompletion
7
  • Something is probably wrong with the payload. Can you show the User class and the http request being sent? Commented Sep 19, 2017 at 13:53
  • Do you actually receive user model in controller? Is it null or not? Can you provide body of response with status code 400? Commented Sep 19, 2017 at 14:16
  • @Merchezatter The received model is null. Commented Sep 19, 2017 at 14:23
  • Your User class should be serializable so that it can be converted to string and sent in http. that is how object passed between applications. Look into [Serializable] attribute and specific fields you want to serialize. Commented Sep 19, 2017 at 14:30
  • possible duplication: stackoverflow.com/questions/19610883/… Commented Sep 19, 2017 at 14:31

3 Answers 3

0

The error message is saying you need a default constructor in order to de-serialise the object. Since you've added custom constructors, this means there's no empty default constructor unless you explicitly put it there. So you should just be able to add

public User() { }

to your User class and resolve that error.

Sign up to request clarification or add additional context in comments.

Comments

0

To be able to serialize and deserialize an object, you need an empty constructor.

public class User
{
    // Add this
    public User()
    {
    }

    public User(string userName, string email, string password) : this(userName, email, password, null, null)
    {

    }

    public User(string userName, string email, string password, string Name, string firstName)
    {
        this.Username = userName;
        this.Email = email;
        this.Password = password;
        this.Name = Name;
        this.firstName = firstName;
    } 

    [...]
}

After creating your instance of your User class, it will fill the model via the public properties that is exposed to your model. You have already your public properties, so adding the constructor would fix your problem.

1 Comment

Thanks for the answer. Your solution is the same as above and also right. ;)
0

you must add [FromBody] to your method and verify that the clace you are referring to does not have an inheritance "From Body" forces you to read the whole body and if it does not find the requested attribute, return NULL [ResponseType (typeof (User))] Public asynchronous task

[ResponseType (typeof (User))]
Public asynchronous task <IHttpActionResult> PostUser ([FromBody]User user)

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.