Sto cercando di allegare un file a un articolo durante il salvataggio del mio articolo attraverso un servizio Web.
Ecco come viene definito il mio articolo :
public class Article : BaseEntity
{
public string Title
{
get; set;
}
public File MainPictureFile
{
get; set;
}
(....)
}
Il modello di file è definito in questo modo:
public class File
{
public Guid ID { get; set; }
public string Name
{
get; set;
}
public File()
{
ID = Guid.NewGuid();
}
}
Ecco come viene codificato il mio servizio Web:
[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesDefaultResponseType]
public async Task<ActionResult<Article>> PutArticle([FromBody] Article article)
{
_dbContext.Entry(article).State = EntityState.Modified;
try
{
await _dbContext.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ArticleExists(article.ID))
{
return NotFound();
}
{
throw;
}
}
return Ok(article);
}
Quindi sto inviando un JSON con un file già creato prima. Voglio solo collegarlo. Quindi sto usando una richiesta PUT Http con una struttura come questa:
{"id":"39e01ca9-f398-4359-8834-6a8e8400dfeb", "title":"Title", "mainPictureFile":{"id":"503047a3-4244-4299-bc18-1a42b564c2ed","name":"bat.jpg"},"position":0}
Tutti gli altri campi funzionano perfettamente. Manca solo il file mainPicture.
Cosa mi manca?
Per completezza, cercherò di spiegare più di una semplice risposta.
Come hai confermato, utilizzando _dbContext.Entry(article.MailPictureFile).State = EntityState.Modified;
funzionerà, perché stai dicendo al DbContext di iniziare a tracciare quell'oggetto all'interno Article
.
Se stavi recuperando quell'oggetto Article
da ef nel senso di un aggiornamento tradizionale e non direttamente dal tuo servizio web, non avresti avuto bisogno di dire ad Ef di iniziare a seguirlo.
Un altro modo per evitare che ciò accada per errore consiste nell'utilizzare il concetto di DTO (oggetto di trasferimento dati) che quindi mappare all'oggetto che hai recuperato dal tuo database, come il concetto di ViewModels utilizzato nel MVC tradizionale. In questo modo EF lo sta già monitorando. Ottieni anche il vantaggio aggiuntivo delle convalide e l'utilizzo di ModelState in questo modo.
Come dice Ivan Stoev nei commenti usando _dbContext.Update(article);
funzionerà anche che è più bello perché è una linea vs potenzialmente una linea per oggetto secondario secondo il mio suggerimento originale.