Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TryUpdateModel for JSON when using Web API

We have TryUpdateModel under System.Web.ModelBinding to update the model partially by the available data in the source.

How do I use this pattern in Web API? Say my JSON result only contain 9 of the total 10 fields, do I have to set the field value one by one?

like image 442
Yiping Avatar asked May 17 '26 15:05

Yiping


1 Answers

I am assuming: Typed models and entity framework. I am getting my head around this myself, but as I understand if you under post values to your API then they will be initialized to their default values (e.g. null for string) or if you have included validation attributes then the API may fail the Model Validation step.

I had an issue where a created and updated timestamp was overridden in new and update commands. The ? operator helped the create, but update was off, then I found the DatabaseGenerated attribute which is what I needed.

    [Column("db_created")]
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime? Created { get; set; }

If it is that you do not want to overwrite some fields with their default values then you'll need to do a manual map with the current instance. So fetch that and update the values you have changed. NOTE: You'll need to update the new object fetched from the database as EF is now tracking that instance when you save changes.

For example:

    // PUT: api/Customer/5
    [ResponseType(typeof(void))]
    public async Task<IHttpActionResult> PutCustomer(int id, Customer updatedCustomer)
    {
        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        if (id != updatedCustomer.ID)
            return BadRequest();

        var currentCustomer = await db.Customers.FindAsync(id);
        updatedCustomer.Created = currentCustomer.Created;
        currentCustomer.Name = updatedCustomer.Name;
        currentCustomer.Description = updatedCustomer.Description;
        //This is nullable in the model e.g. public DateTime? Updated;
        currentCustomer.Updated = null;
        db.Entry(currentCustomer).State = EntityState.Modified;

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!CustomerExists(id))
                return NotFound();
            else
                throw;
        }
        return StatusCode(HttpStatusCode.NoContent);
    }
like image 176
Nicholas Avatar answered May 19 '26 14:05

Nicholas