Implementation
        You will be writing action methods in each of your API
          controllers to handle any of the HTTP request verbs that are
          important for your application. 
        
        Controller
        An API controller should inherit from ControllerBase and have the [ApiController]
          attribute. 
           
        Controller Methods
        There will be one method for each HTTP verb. You can write the
        method using an ActionMethod
        or IActionMethod
        return type, but just return a POCO object and MVC will figure
        out the correct format for the returned data--including the HTTP
        status code. In addition, you can explicitly declare the status
        code.
        
        Each action method should have the route annotation below so
        that the method names don't need to be included in the URL
        [Route("api/[controller]")]
          URL will be: http://localhost:5000/api/Book/
              
            
        Status Codes
        Each of the methods returns an IActionResult which allows the use
        of StatusCode
        helper methods. HTTP Status codes, along with the available
        status code helper methods are shown below:
        
          - 200: Ok
 
          - 204: NoContent
 
          - 400: BadRequest
 
          - 401: Unauthorized
 
          - 404: NotFound
 
          - 409: Conflict
 
          - 415: UnsupportedMediaType
 
          - 422: UnprocessableEntity
 
          - 500: InternalServerError
 
        
        Examples
          HTTP requests and a controller methods are shown below
        for different HTTP request methods (verbs).
        
          - GET
            Use this to get all items or a specified item.
             
          
            - URL to get all book items:
              http://localhost:5000/api/Book
                (See the code
                  below.)
                 
            - URL to get
                  a book item by ID:
              http://localhost:5000/api/Book/3
              
              (No code shown for this.) 
              
               [HttpGet]
                public IActionResult GetBooks() {
                   var books = bookRepo.GetAllBooks();
                   if (books.Count == 0) {
                      return NotFound();
                   }
                   else {
                      return Ok(books);
                   }
                }  
          
        
        
          - POST
              Use
              this to add an item.
               
          
            - URL:
              http://localhost:5000/api/Book 
            - Header:
               
                content-type:application/json 
            - Body:
                 
              
              { 
               
                     "title": "Tom Sawyer",
               
                     "date": "1/1/1876",
               
                     "author": "Mark Twain",
               
                     "birthdate": "11/30/1835"
               
                  } 
              
              [HttpPost]
                public IActionResult AddBook(string title, string date,
                string author, string birthdate) {
                    Book book = new Book { Title = title,
                Date = DateTime.Parse(date) };
                    if (author != null) {
                       
                book.Authors.Add(new Author { Name = author, Birthday =
                DateTime.Parse(birthdate)});
                       
                bookRepo.AddBook(book);
                        return
                Ok(book);
                    }
                    else {
                        return
                BadRequest();  
                    }
                }Note: The method above receives parameters that
              have been parsed from the POST request body.
              Alternatively, the controller action method could use the [FromBody] 
                model binding behavior attribute which tells MVC
              to  bind data from the request body to an object of
              the specified type--see Appel (2018).
              
             
          
        
        
          -  PUT
            Use this to
                  replace an item specified by an ID, or create a new
                  item with this ID if the specified ID does not exist.
                 
          
            - URL 
                  http://localhost:5000/api/Book/5 
            - Header:
               
                  content-type:application/json 
            - Body:
               {
                 
                    "title": "Oliver Twist",
                 
                    "date": "3/1/1839",
                 
                    "name": "Charles Dickens",
                 
                    "birthday": "6/8/1870"
              }
              
              [HttpPut("{id} ")]
                public IActionResult Replace(int id, string title,
                string date, string author, string birthdate) {
                    Book book = new Book { Title = title,
                Date = DateTime.Parse(date) };
                    book.BookID = id;
                    if (author != null) {
                       
                book.Authors.Add(new Author { Name = author, Birthday =
                DateTime.Parse(birthdate) });
                       
                bookRepo.Edit(book);
                        return
                Ok(book);
                    }
                    else {
                        return
                BadRequest();  // 
                    }
                }
               
             
          
          -  PATCH
              Use
              this to update an item by changing a single field.
           
          
            - URL
               http://localhost:5000/api/Book/5  
               
            - Request header:
              Content-Type:application/json
               
            - Request body:
               {
                        "op": "replace",
                        "path": "title",
                        "value": "David Copperfield"
                    }
              
              [HttpPatch("{id} ")]      //
                TODO: Add support for more ops: remove, copy, move, test
                public IActionResult UpdateBook(int id, string op,
                string path, string value) {
                    Book book = bookRepo.GetBookById(id);
                    switch(path) {
                        case "title
                ":
                        book.Title =
                value;
                           
                break;
                        case "date ":
                           
                book.Date = Convert.ToDateTime(value);
                           
                break;
                        case "author
                ":
                           
                book.Authors[0].Name = value;   // TODO:
                manage author collection
                           
                break;
                        case
                "birthdate ":
                           
                book.Authors[0].Birthday = Convert.ToDateTime(value);
                           
                break;
                        default:
                           
                return BadRequest();
                    }
                    bookRepo.Edit(book);
                    return Ok(book);
                }
              
             
          
          - DELETE
              Use this to delete
                  an
                  item by its
                    ID. 
          
            - URL
               
                    http://localhost:5000/api/Book/5
                
              [HttpDelete("{id} ")]
                public IActionResult DeleteBook(int id) {
                    Book book = bookRepo.GetBookById(id);
                    if (book != null) {
                       
                bookRepo.Delete(id);
                        return Ok();
                    }
                    else {
                        return
                NotFound();
                    }
                }
                
          
        
         Notes
        
          - In ASP.NET Core version 2.0, use of the [ApiController]
            annotation was deprecated, but in 2.1 and later it is again
            required on a controller class that will provide API
            endpoints. 
 
          - Your controller can be a subclass of Controller, but it is
            better to make it a subclass of ControllerBase (Controller
            is a sub-class of ControllerBase) since Controller contains
            View related members that you don't need.
 
        
        
        Testing
        One way to test a web API is to use a tool like Postman. This will let you write an HTTP
          request, send it to an API endpoint, and view the response.
          You can save the request for use again later.
        Steps to create a request in Postman:
        
        
          - Click + to create a new request tab.
 
          - Select a request method (verb) from the drop-down list;
            for example:
            POST
           
          - Enter the URL of the web API; for example:
            http://localhost:5000/api/Book 
          - Select Headers and enter the header. If your request has a
            JSON body, then enter:
            Content-Type:application/json 
          - Select Body and
                enter the request body; for example:
            { 
                 
                       "title": "Tom Sawyer",
                 
                       "date": "1/1/1876",
                 
                       "author": "Mark Twain",
                 
                       "birthdate": "11/30/1835"
                 
                    }  
        
        
        
        Examples
        
          - Source code on GitHub: ProfBird/BookInfo-Core-2-WebAPI
 
          - Web service running online:  BookInfo Service
 
        
        
        
          References
          
            -  Freeman, Adam. (2017). Ch. 20, "Web API, " in Pro ASP.NET Core MVC 2. 
 
            -  Appel, Rachel. (2019). "Model Binding in ASP.NET Core",
              in ASP.NET
                Core Documentation. Microsoft. 
 
            - Anderson, Rick & Wasson Mike. (2019). "Tutorial: Create a web API with ASP.NET
                Core MVC," in ASP.NET
                Core Documentation. Microsoft. 
 
            - Addie, Scott. (2020). "Controller action return types in
                ASP.NET Core Web API," in ASP.NET
                Core Documentation. Microsoft. 
 
            - "StatusCodeResult Class," in ASP.NET
                Core Documentation. Microsoft. 
 
            - Crockford, Douglas. (2018). "Introducing JSON" in How JavaScript Works. 
 
            -  Spasojevic, Marinko. (2021). "Using
                HttpClient to Send HTTP PATCH Requests in ASP.NET Core".
              Code-Maze.
              This article has a good explanation of the HTTP PATCH
              request.