I'm working with a small application just to study .NET Core and C#. I have a model called Movie and one of its fields is a byte array to store an image. I want to know how is it possible to use JsonPatchDocument to update that field.
The Movie model:
public class Movie
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id_movie { get; set; }
[Required]
public string name_movie { get; set; }
public byte[]? img_movie { get; set; }
public string? desc_movie { get; set; }
public int duration_movie { get; set; }
public type_class_movie class_movie { get; set; }
public DateTime? created_at_movie { get; set; }
public DateTime? updated_at_movie { get; set; }
public int id_category_movie { get; set; }
[ForeignKey("id_category_movie")]
public Category? Category { get; set; }
}
public enum type_class_movie { Siete, Trece, Diesciseis, Dieciocho }
The MoviesController:
[HttpPatch("update_movie/{id_movie:int}", Name = "UpdateMovie")]
public IActionResult UpdateMovie(int id_movie, [FromForm] Movie movie, IFormFile imagen)
{
try
{
if (!_mRepo.MovieExistsById(id_movie))
{
var errorResponse = new
{
StatusCode = 400,
Message = "Movie doesn't exists"
};
return StatusCode(400, errorResponse);
}
using (var memoryStream = new MemoryStream())
{
await imagen.CopyToAsync(memoryStream);
movie.img_movie = memoryStream.ToArray();
}
if (!_mRepo.UpdateMovie(entity))
{
var errorResponse = new
{
StatusCode = 500,
Message = "An error ocurred while processing the request"
};
return StatusCode(500, errorResponse);
}
return StatusCode(200, new { updt_cat = entity });
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
var errorResponse = new
{
StatusCode = "Error",
Message = "An error occurred while processing the request."
};
return StatusCode(500, errorResponse);
}
}
I like the way the JsonPatchDocument partial update works, but I don't know how to use it to get a partial update of a form that may include an image, any help is appreciated.
UPDATE: This is a screenshot of patchDocument
values:
Screenshot of request in Potman:
Sure it is possible. Do you follow this tutorial? https://trycatchdebug.net/news/1211513/jsonpatchdocument-and-iformfile-in-c Based on this document,I think you need to do following modification:
[HttpPatch("update_movie/{id_movie:int}", Name = "UpdateMovie")]
//change mehtod to async
public async Task<IActionResult> UpdateMovie(int id_movie, [FromForm] JsonPatchDocument<Movie> patchDocument, IFormFile imagen)
{
try
{
var movie = await _mRepoawait.MovieFindById(id_movie); // "MovieFindById implement from _dbcontext.Movies.FindAsync(id);
if (movie == null)
{
var errorResponse = new
{
StatusCode = 400,
Message = "Movie doesn't exists"
};
return StatusCode(400, errorResponse);
}
patchDocument.ApplyTo(movie); //use "ApplyTo" to update the "movie" model
using (var memoryStream = new MemoryStream())
{
await imagen.CopyToAsync(memoryStream);
movie.img_movie = memoryStream.ToArray();
}
if (!_mRepo.UpdateMovie(movie)) //"UpdateMovie" should have implement _dbcontext.SaveChangesAsync();
{
var errorResponse = new
{
StatusCode = 500,
Message = "An error ocurred while processing the request"
};
return StatusCode(500, errorResponse);
}
return StatusCode(200, new { updt_cat = movie });
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
var errorResponse = new
{
StatusCode = "Error",
Message = "An error occurred while processing the request."
};
return StatusCode(500, errorResponse);
}
}
Packages you need to install:
Microsoft.AspNetCore.JsonPatch
Microsoft.AspNetCore.Mvc.NewtonsoftJson
And if your controller has the [ApiController]
attribute, the multipart/formdata won't work. You will need to change the program.cs like following:
builder.Services.AddControllers().AddNewtonsoftJson().ConfigureApiBehaviorOptions(o => {
o.SuppressInferBindingSourcesForParameters = true;
});
Then you could use postman to test your endpoint like this: (change movie name and image)
Reference: https://learn.microsoft.com/en-us/aspnet/core/web-api/jsonpatch?view=aspnetcore-8.0