Outline

Solution: Building Out the API Endpoints

In the Conduit.Api project, create the following Controllers.

In the body of the each controller add the following code (we'll fill in the details later):

try
{
    return Ok();
}
catch (Exception ex)
{
    Logger.LogError(ex.Message, ex);
    return StatusCode(500, ex.Message);
}

Add the ArticlesController with the following API Structure (scroll to the right to the full table):

API                                     | Description                   | Request Body                                         | Query Parameters                                           | Response Body
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GET /api/articles                       | List Articles                 |                                                      | Filter by tag: ?tag=AngularJS                              | An array of articles     
Method Name: GetArticles                | Returns most recent articles  |                                                      | Filter by author: ?author=jake                             | along with the count of  
                                        | Authentication optional       |                                                      | Favorited by user: ?favorited=jake                         | articles                 
                                        | Global by default             |                                                      | Limit number of articles (default is 20): ?limit=20        |                          
                                        | Will return multiple articles |                                                      | Offset/skip number of articles (default is 0): ?offset=0   |                          
                                        | Ordered by most recent first  |                                                      |                                                            |                          
                                        | Provide tag, author or        |                                                      |                                                            |                          
                                        | favorited query parameter     |                                                      |                                                            |                          
                                        | to filter results             |                                                      |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GET /api/articles/feed                  | Feed Articles                 |                                                      | Limit number of articles (default is 20): ?limit=20        | An array of articles     
Method Name: GetArticleFeed             | Will return multiple articles |                                                      | Offset/skip number of articles (default is 0): ?offset=0   | along with the count of  
                                        | Authentication required       |                                                      |                                                            | articles                 
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GET /api/articles/:slug                 | Get Article                   |                                                      |                                                            | A single Article         
Method Name: GetArticleBySlug           | No Authentication required    |                                                      |                                                            |                          
                                        | Will return single article    |                                                      |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POST /api/articles                      | Create Article                | {                                                    |                                                            |                          
Method Name: CreateArticle              | Authentication required       |    "article": {                                      |                                                            |                          
                                        | Will return single article    |       "title": "How to train your dragon",           |                                                            |                          
                                        | Required fields:              |       "description": "Ever wonder how?",             |                                                            |                          
                                        | - title                       |       "body": "You have to believe",                 |                                                            |                          
                                        | - description                 |       "tagList": ["reactjs", "angularjs", "dragons"] |                                                            |                          
                                        | - body                        |    }                                                 |                                                            |                          
                                        |                               | }                                                    |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
PUT /api/articles/:slug                 | Update Article                | {                                                    |                                                            | Returns the              
Method Name: UpdateArticle              | Authentication required       |    "article": {                                      |                                                            | updated Article          
                                        | The slug also gets updated    |       "title": "How to train your dragon",           |                                                            |                          
                                        | when the title is changed     |    }                                                 |                                                            |                          
                                        | Required fields:              | }                                                    |                                                            |                          
                                        | - title                       |                                                      |                                                            |                          
                                        | - description                 |                                                      |                                                            |                          
                                        | - body                        |                                                      |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DELETE /api/articles/:slug              | Delete Article                |                                                      |                                                            |                                                    
Method Name: DeleteArticle              | Authentication required       |                                                      |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POST /api/articles/:slug/comments       | Add Comments to an Article    | {                                                    |                                                            | Returns the              
Method Name: AddCommentToArticle        | Authentication required       |    "comment": {                                      |                                                            | created Comment           
                                        | Required Field: body          |       "body": "His name was my name too.",           |                                                            |                          
                                        |                               |    }                                                 |                                                            |                          
                                        |                               | }                                                    |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GET /api/articles/:slug/comments        | Get Comments from an Article  |                                                      |                                                            | returns the              
Method Name: GetCommentsFromArticle     | Authentication optional       |                                                      |                                                            | created Comment          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DELETE /api/articles/:slug/comments/:id | Delete Comment                |                                                      |                                                            |                          
Method Name: DeleteCommentsFromArticle  | Authentication required       |                                                      |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POST /api/articles/:slug/favorite       | Favorite Article              |                                                      |                                                            | returns the Article      
Method Name: FavoriteArticle            | Authentication required       |                                                      |                                                            |                          
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
DELETE /api/articles/:slug/favorite     | Unfavorite Article            |                                                      |                                                            | returns the Article      
Method Name: UnfavoriteArticle          | Authentication required       |                                                      |                                                            |                          

Here's the code for the ArticlesController.cs file:

using Conduit.Models.Requests;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;

namespace Conduit.Api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ArticlesController : ControllerBase
    {
        private ILogger<ArticlesController> Logger;

        [HttpGet]
        public IActionResult GetArticlesAsync(
            [FromQuery] string tag,
            [FromQuery] string author,
            [FromQuery] string favorited,
            [FromQuery] int limit = 20,
            [FromQuery] int offset = 0
            )
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpGet("feed")]
        public IActionResult GetArticleFeedAsync([FromQuery] int limit = 20, int offset = 0)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpGet("{slug}")]
        public IActionResult GetArticleBySlugAsync([FromRoute] string slug)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpPost]
        [Authorize]
        public IActionResult CreateArticleAsync([FromBody] ArticleRequest<ArticleCreateRequest> req)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpPut("{slug}")]
        [Authorize]
        public IActionResult UpdateArticleAsync(
            [FromRoute] string slug,
            [FromBody] ArticleRequest<ArticleUpdateRequest> req
            )
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpDelete("{slug}")]
        [Authorize]
        public IActionResult DeleteArticleAsync([FromRoute] string slug)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpPost("{slug}/comments")]
        [Authorize]
        public IActionResult AddCommentToArticleAsync(
            [FromRoute] string slug,
            [FromBody] CommentRequest<CommentAddRequest> req)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpGet("{slug}/comments")]
        public IActionResult GetCommentsFromArticleAsync([FromRoute] string slug)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpDelete("{slug}/comments/{id:int}")]
        [Authorize]
        public IActionResult DeleteCommentsFromArticleAsync(
            [FromRoute] string slug,
            [FromRoute] int id)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpPost("{slug}/favorite")]
        [Authorize]
        public IActionResult favoriteArticleAsync([FromRoute] string slug)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        [HttpDelete("{slug}/favorite")]
        [Authorize]
        public IActionResult UnfavoriteArticleAsync([FromRoute] string slug)
        {
            try
            {
                return Ok();
            }
            catch (Exception e)
            {
                Logger.LogError(e.Message, e);
                return StatusCode(500, e);
            }
        }

        public ArticlesController(ILogger<ArticlesController> logger)
        {
            Logger = logger;
        }
    }
}
 

I finished! On to the next chapter