1
votes

J'essaye d'écrire une requête POST à ​​mon API afin qu'elle puisse agir sur deux objets séparés (une insertion et une mise à jour)

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:

https: // localhost: 44362 / api / BookList /

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!


0 commentaires

3 Réponses :


1
votes

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
}


3 commentaires

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.



1
votes

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?


0 commentaires

1
votes

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.


0 commentaires