2

Je crée un projet MVC Core 1.0.1 qui inclura à la fois API et Web. J'ai donc créé mes modèles et maintenant je veux créer des opérations CRUD au sein d'un seul contrôleur au lieu d'échafauder chaque modèle. J'ai créé un ApiController qui ressemble à ceciUn contrôleur Web API pour contrôler tous les modèles

[Consumes("application/json")] 
[Produces("application/json")] 
[Route("/api/{resource}")] 
public class ApiController : Controller 
{ 
    private readonly MasterContext _context; 

    public ApiController(MasterContext context) 
    { 
     _context = context; 
    } 

    [HttpPost] 
    public IActionResult Create(string resource, [FromBody] object body) 
    { 
     //_context.Add(); 
     return Ok("ok api Create"); 

    } 

    [HttpGet("{id?}")] 
    public IActionResult Read(string resource, int? id) 
    { 
     return Ok("ok api get Read"); 
    } 
    [HttpPatch("{id}")] 
    public IActionResult Update(string resource, [FromBody] object body) 
    { 
     //_context.Update(); 
     return Ok("ok api Update"); 
    } 
    [HttpDelete("{id}")] 
    public IActionResult Delete(string resource, [FromBody] object body) 
    { 
     return Ok("ok api Delete"); 
    } 
} 

De cette façon, j'ai une méthode pour chaque méthode HTTP que j'ai besoin (Post, Get, Patch, Supprimer), dans la ressource que j'ai le modèle comme une chaîne et dans le corps j'ai le corps de la requête en tant qu'objet. Avant de travailler avec le framework d'entité pour effectuer l'opération demandée, je dois trouver le modèle en fonction de la ressource et convertir le corps de l'objet en cette classe.

Des suggestions comment faire cela? Un collègue a fait cela en utilisant Python, cela peut-il être fait en utilisant C# et quel inconvénient aura le résultat? Par exemple, je présume que la validation du modèle sera difficile à réaliser.

Répondre

1

Oui, c'est possible. Disons que nous avons cette DbContext:

public partial class FooContext : DbContext 
{ 
    //has "MyAssembly.Blog" type 
    public virtual DbSet<Blog> Blog { get; set; } 
}   

Pour enregistrer une nouvelle entité dans la base de données, nous devons trouver Blog premier type. Avoir le type, il est facile de désérialiser objet et enregistrez-le:

//you called POST /blog 
string resource = "blog"; 
string body = "{...}"; 

var context = new FooContext(); 

IEntityType entityType = context.Model 
    .GetEntityTypes() 
    .First(x => x.Name.EndsWith($".{resource}", StringComparison.OrdinalIgnoreCase)); 

//This type should be "MyAssembly.Blog" - exact entity CLR type. 
//Another option to get this CLR type is assembly scan. 
Type type = entityType.ClrType; 

//having type, it is possible to create instance 
object entity = JsonConvert.DeserializeObject("body", type); 
//var entity = Activator.CreateInstance(type); 

context.Entry(entity).State = EntityState.Added; 
context.SaveChanges(); 

Pour lire une entité par ID de base de données, utilisez non générique DbContext.Find

var entityFromDb = context.Find(type, id); 

post-scriptum Je pense qu'un générique ApiController est généralement une mauvaise idée. C'est encombrant et cela apporte une énorme complexité inutile mais de petits bénéfices.

+0

Merci pour la réponse. Context.Find n'existe pas pour moi, avez-vous créé cette méthode? Des astuces pour créer find by id? –

+0

@DimitrisLaliotis, 'Find' est une méthode intégrée. https://github.com/aspnet/EntityFramework/blob/dev/src/EFCore/DbContext.cs#L1138 Assurez-vous de disposer des derniers packages EF Core. –