2

Now, I have a user object which has three required attributes: {FirstName, LastName, CreatedTime }.

Now I developed an API to create a user. I want to use POST /api/users.

I should pass in Jason data and it contains the data I want to post.

If I pass in {FirstName=abc, LastName=abc, CreatedTime=sometime}, it works, but if i miss any attribute, such like only passing in {firstname=abc}, it will throw exception.

I pasted my method below.

    [Route("api/users")]
    public User CreateUser(User user)
    {
        if (!ModelState.IsValid)
            throw  new HttpResponseException(HttpStatusCode.BadRequest);

        user.FirstName = String.IsNullOrEmpty(user.FirstName) ? "Undefined" : user.FirstName;
        user.LastName = String.IsNullOrEmpty(user.LastName) ? "Undefined" : user.LastName;
        user.UserName = String.IsNullOrEmpty(user.UserName) ? "Undefined" : user.UserName;
        user.ModifiedAt = DateTime.Now;
        user.CreatedAt = DateTime.Now;
        _context.Users.Add(user);
        _context.SaveChanges();

        return user;
    }

My question is: Is there any way that I can pass in partial properties of user? Such like {firstname=abc}.

This technique can also be used as PUT (update user method).

Thanks in advance.

Will
  • 133
  • 3
  • 15
  • Is your `User` object being used for any other API where all the properties are required? – Dishant Sep 07 '18 at 05:11
  • @Dishant Nope, this is the only api I have in this project. – Will Sep 07 '18 at 05:37
  • 1
    Than in that case solution mentioned by @Mohammad Nikravesh will work for you. – Dishant Sep 07 '18 at 05:47
  • 1
    @Dishant That works, thanks. However, if I used JsonIgnore, it will ignore all the occurrence of this property. If I call /api/users/1, it also hide the property. Is there any way that it just ignore the input but not output? – Will Sep 07 '18 at 05:53
  • @WilliamShu I got what you want, You may have to override defaultcontractresolver, take look at this https://stackoverflow.com/a/20963058/4189817 – Mohammad Nikravesh Sep 07 '18 at 07:02

2 Answers2

2

1) When inserting your record just mark your CreatedAt and ModifiedAt property to [JsonIgnore] attribute

[Required] 
[JsonIgnore] 
public DateTime CreatedAt { get; set; } 

[Required] 
[JsonIgnore] 
public DateTime ModifiedAt { get; set; } 

2) When you try to get your data your api method will be

[HttpGet]
[Route("ById/{id=id}")]
public IHttpActionResult GetUser(int? id)
{
    if (id == null)
        return NotFound();

    User user = _context.Users.SingleOrDefault(c => c.UserId == id.Value);

    if (user == null)
        return BadRequest("User not exist in our database");

    var returnedData = new { FirstName = user.FirstName, LastName = user.LastName, UserName = user.UserName, CreatedAt = DateTime.Now, ModifiedAt = DateTime.Now };
    return Ok(returnedData);
}

We just use to return Anonymous Type that is customizable to return data.

Try once may it help you

er-sho
  • 9,581
  • 2
  • 13
  • 26
0

It depends to your properties datatype, if they are nullable so you can just leave them empty or null in your sending message but if they are not nullable you have to provide value otherwise you will get noting in the destination (your wep-api action). So now if you want to avoid passing value even for non-nullable properties you can use [JsonIgnore] attribute (Belongs to Newtonsoft.Json) on your properties. Like this:

using Newtonsoft.Json;

public class User
{
   //...
   [JsonIgnore]
   public DateTime CreatedAt  { get; set; }
   //...
}
Mohammad Nikravesh
  • 947
  • 1
  • 8
  • 27
  • 1
    That works! But is there any way that I can still get the data from api? Such like, if I call /api/users/1 and it will return all the properties this user has, include the json ignored ones. – Will Sep 07 '18 at 05:51
  • You can change the parameter type from "User user" to "object user" then you have your full JSON object as the input arguments and then you can serialize it manually – Mohammad Nikravesh Sep 07 '18 at 06:57