I'm trying to write a POST request to my API so that it can act on two separate objects(an insert and an update)

1

I'm trying to write this controller that accepts a POST request.

I need this controller to add a new book, and also add that new books bookId to another object called a StoreList.

So I am trying to pass in the new bookList, and the storeList that needs the bookId added to it.

    // 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);
    }

Here is my API endpoint:

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

And these are the two objects I'm passing in the BODY of the request (the new bookList and the existing storeList):

{
    "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7",
    "bookTitle": "Is this a test 2?"
},
{
    "storeId": "0001f801-6909-4b6e-8652-e1b49745280f",
    "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7"
}

But whenever I try to 'hit' that endpoint, I get this error:

System.InvalidOperationException HResult=0x80131509 Message=Action 'DocumentStorageAPI.Controllers.Book.BookListController.PostBookList (DocumentStorageAPI)' has more than one parameter that was specified or inferred as bound from request body. Only one parameter per action may be bound from body. Inspect the following parameters, and use 'FromQueryAttribute' to specify bound from query, 'FromRouteAttribute' to specify bound from route, and 'FromBodyAttribute' for parameters to be bound from body: BookList bookList StoreList storeList

How can I get my controller to allow me to add a new bookList and update the needed storeList?

Thanks!

asp.net-core
asp.net-core-mvc
asp.net-core-webapi
asked on Stack Overflow Nov 11, 2019 by SkyeBoniwell

3 Answers

1

The body of the request should be just one object and the PostBookList method must have only one parameter (with the [FromBody] attribute). If you need both classes to use within the method create a new class like this:

public class PostBookListRequest
{
    public BookList BookList { get; set; }
    public StoreList StoreList { get; set; }
}

change the PostBookList method to

public async Task<ActionResult<BookList>> PostBookList([FromBody]PostBookListRequest request)
{
    // Your logic here
}

And in the BODY of the request do

{
    "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"
    }
}
answered on Stack Overflow Nov 11, 2019 by joacoleza • edited Nov 11, 2019 by joacoleza
1

You can use body like this:

{
  "bookId": "bc381612-c63b-4438-b35b-161a3a568fc7",
  "title": "Is this a test 2?",
  "storeId" "0001f801-6909-4b6e-8652-e1b49745280f"
}

In Controller you need additional class BookListBinding with this 3 fields, which you will use for create you 2 objects, for example.

[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);
}

Why you need change StoreList? What is it?

answered on Stack Overflow Nov 11, 2019 by Arthur Tagirov
1

You have to create a new model like so-

public class AddBookToStoreModel
    {
        public Book BookToAdd { get; set; }
        public StoreList BookStoreList { get; set; }
    }

You have to add the same to the controller definition, like this-

[HttpPost]
        public async Task<ActionResult<BookStore>> PostBookList(AddBookToStoreModel model)

Also you need to create the individual Models for Book and StoreList like below-

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; }
    }

The Json that you post to the controller will look like below-

{
"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"
}
}

I hope this works for you.

answered on Stack Overflow Nov 11, 2019 by kode_anil

User contributions licensed under CC BY-SA 3.0