J'essaye d'écrire ce contrôleur qui accepte une requête POST.
J'ai besoin de ce contrôleur pour ajouter un nouveau livre, et aussi ajouter ce nouveau livre bookId à un autre objet appelé StoreList.
J'essaye donc de passer la nouvelle bookList, et la storeList qui a besoin le bookId lui a été ajouté.
{ "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7", "bookTitle": "Is this a test 2?" }, { "storeId": "0001f801-6909-4b6e-8652-e1b49745280f", "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7" }
Voici mon point de terminaison d'API:
Et ce sont les deux objets que je passe dans le BODY de la requête (la nouvelle bookList et la storeList existante):
// POST: api/BookList [HttpPost] public async Task<ActionResult<BookList>> PostBookList(BookList bookList, StoreList storeList) { _context.BookList.Add(bookList); await _context.SaveChangesAsync(); _context.Entry(storeList).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!StoreListExists(storeId)) { return NotFound(); } else { throw; } } return CreatedAtAction("GetBookList", new { id = bookList.BookId }, bookList); }
Mais quand J'essaye de «frapper» ce point de terminaison, j'obtiens cette erreur:
System.InvalidOperationException HResult = 0x80131509 Message = Action 'DocumentStorageAPI.Controllers.Book.BookListController.PostBookList (DocumentStorageAPI) 'a plus d'un paramètre qui était spécifié ou déduit comme lié à partir du corps de la requête. Seulement un le paramètre par action peut être lié à body. Inspectez les éléments suivants paramètres, et utilisez 'FromQueryAttribute' pour spécifier lié à partir de la requête, 'FromRouteAttribute' pour spécifier la liaison depuis la route, et 'FromBodyAttribute' pour les paramètres à lier à partir du corps: BookList bookList StoreList storeList
Comment puis-je faire en sorte que mon contrôleur me permette d'ajouter une nouvelle liste de livres et de mettre à jour la liste de magasins nécessaire?
Merci!
3 Réponses :
Le corps de la requête doit être un seul objet et la méthode PostBookList
ne doit avoir qu'un seul paramètre (avec l'attribut [FromBody]
). Si vous avez besoin des deux classes à utiliser dans la méthode, créez une nouvelle classe comme celle-ci:
{ "bookList": { "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7", "bookTitle": "Is this a test 2?" }, "storeList": { "storeId": "0001f801-6909-4b6e-8652-e1b49745280f", "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7" } }
changez la méthode PostBookList
en
public async Task<ActionResult<BookList>> PostBookList([FromBody]PostBookListRequest request) { // Your logic here }
Oh ok, mais comment pourrais-je créer le nouveau livre et également mettre à jour l'objet de magasin? Le contrôleur saurait-il comment gérer un objet comme celui que vous avez publié ci-dessus? Merci!
Comment avez-vous défini vos modèles? Quelles sont les propriétés d'une BookList? Et StoreList? Sont des collections ou juste des entités? Je pense que la partie Liste dans le nom prête à confusion.
Les noms prêtent à confusion car ce n'est pas vraiment une librairie mais une mémoire. :) Ce sont tous deux des modèles séparés et la seule chose qu'ils partagent est le bookId. Un storeId a un champ bookId qui peut être nul ou faire référence à l'un des livres de la bookList. Un magasin ne peut avoir qu'un seul livre et une question ne peut faire partie que d'un seul magasin.
Vous pouvez utiliser le corps comme ceci:
[HttpPost] public async Task<ActionResult> PostBookList(BookListBinding binding) { var bookList = new BookList { Id = binding.BookId, Title = binding.Title }); var storeList = new StoreList { Id = binding.StoreId, BookId = binding.BookId } // you work with _context return CreatedAtAction("GetBookList", new { id = binding.BookId }, bookList); }
Dans Controller, vous avez besoin d'une classe supplémentaire BookListBinding avec ces 3 champs, que vous utiliserez pour vous créer 2 objets, par exemple.
{ "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7", "title": "Is this a test 2?", "storeId" "0001f801-6909-4b6e-8652-e1b49745280f" }
Pourquoi avez-vous besoin de changer StoreList? Qu'est-ce que c'est?
Vous devez créer un nouveau modèle comme so-
{ "BookToAdd": { "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7", "bookTitle": "Is this a test 2?" }, "BookStoreList": { "storeId": "0001f801-6909-4b6e-8652-e1b49745280f", "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7" } }
Vous devez ajouter la même chose à la définition du contrôleur, comme ceci-
public class Book { public Guid BookId { get; set; } public string BookTitle { get; set; } } public class StoreList { public Guid StoreId { get; set; } public Guid BookId { get; set; } }
Vous devez également créer les modèles individuels pour Book et StoreList comme ci-dessous-
[HttpPost] public async Task<ActionResult<BookStore>> PostBookList(AddBookToStoreModel model)
Le Json que vous publiez sur le contrôleur ressemblera à ci-dessous-
public class AddBookToStoreModel { public Book BookToAdd { get; set; } public StoreList BookStoreList { get; set; } }
J'espère que cela fonctionne pour vous.