## REST Controller (CRUD)

The previous example is a rough example on how to use the `rest_controller`, it assumes you pass in the parameters using form data or query parameters. There's another approach, that is more elegant and easier for the developer: create a CRUD interface and pass the data encoded in JSON format.

To make this work, we rework the previous example. The data items `Cart` and `Item` remain the same, they already have a `serialize` method. The real difference is in the JavaScript code, in the previous example all work was done by the server, the JavaScript only called separate methods to fill the items list and the server responded with the new Cart content. In this example however, management of the cart content is done by the JavaScript and the updated cart is then sent using a `PUT` to the server.

The server therefore looks like this:

    class shop_rest_controller : public zeep::http::rest_controller
    {
      public:
        shop_rest_controller()
            : zeep::http::rest_controller("/cart")
        {
            // CRUD example interface

            map_post_request("",        &shop_rest_controller::create_cart, "cart");
            map_get_request("{id}",     &shop_rest_controller::retrieve_cart, "id");
            map_put_request("{id}",     &shop_rest_controller::update_cart, "id", "cart");
            map_delete_request("{id}",  &shop_rest_controller::delete_cart, "id");
        }

        int create_cart(Cart cart)
        {
            int result = cart.id = sNextCartID++;
            m_carts.push_back(std::move(cart));
            return result;
        }

        Cart& retrieve_cart(int cartID)
        {
            auto oi = std::find_if(m_carts.begin(), m_carts.end(), [&](auto& o) { return o.id == cartID; });
            if (oi == m_carts.end())
                throw std::invalid_argument("No such cart");
            return *oi;
        }

        void update_cart(int cartID, const Cart& cart)
        {
            auto oi = std::find_if(m_carts.begin(), m_carts.end(), [&](auto& o) { return o.id == cartID; });
            if (oi == m_carts.end())
                throw std::invalid_argument("No such cart");

            oi->client = cart.client;
            oi->items = cart.items;
        }

        void delete_cart(int cartID)
        {
            m_carts.erase(std::remove_if(m_carts.begin(), m_carts.end(), [cartID](auto& cart) { return cart.id == cartID; }), m_carts.end());
        }

      private:
        static int sNextCartID;
        std::vector<Cart> m_carts;
    };

Some ceveats: this works probably only well if you have a single `JSON` (or compatible) data type as main parameter and optionally one or more path parameters. The request should also have `content-type` equal to `application/json` to work properly.