Creating Consistent ASP.NET Core Web API Responses with AutoMapper and DTOs

Introduction

Developing a robust ASP.NET Core Web API hinges on the subtle yet pivotal details of response structuring. Leveraging AutoMapper in tandem with well-designed Data Transfer Objects (DTOs) not only ensures the separation of concerns but also orchestrates a symphony of consistent and predictable API responses. These intricacies extend beyond mere data mapping; they epitomize a strategic approach in harmonizing the internal model intricacies with the API's outward-facing facade.

Unveiling the elegance of these detailed mappings and the orchestration of a uniform response structure not only enhances the developer's workflow but also augments client-side integration, presenting an intuitive and standardized communication channel. Addressing these finer points not only establishes a foundation for resilient error handling but also fuels the API's scalability and ease of maintenance, fostering an environment where agility meets reliability.

Step 1. Model Classes

// Sardar Mudassar Ali Khan
public class CSharpCornerArticle
{
    public int ArticleId { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public DateTime PublishedDate { get; set; }
    public string Content { get; set; }
}

Create DTO Class

// Sardar Mudassar Ali Khan
public class CSharpCornerArticleDto
{
    public int ArticleId { get; set; }
    public string Title { get; set; }
    public string Author { get; set; }
    public DateTime PublishedDate { get; set; }
    public string Content { get; set; }
}

API Response Class

public class ApiResponse<T>
{
    public int StatusCode { get; set; }
    public string Message { get; set; }
    public T Data { get; set; }
}

Step 2. Repository and Mock Data

// Sardar Mudassar Ali Khan
// Creating the IArticleRepository for articles 
public interface IArticleRepository
{
    CSharpCornerArticle GetArticleById(int id);
}
//Sardar Mudassar Ali Khan
//Implementation of article Repository 
public class ArticleRepository : IArticleRepository
{
    private readonly List<CSharpCornerArticle> _articles = new List<CSharpCornerArticle>
    {
        new CSharpCornerArticle
        {
            ArticleId = 1,
            Title = "Article One",
            Author = "Alice",
            PublishedDate = DateTime.UtcNow,
            Content = "Content of Article One"
        },
        new CSharpCornerArticle
        {
            ArticleId = 2,
            Title = "Article Two",
            Author = "Bob",
            PublishedDate = DateTime.UtcNow,
            Content = "Content of Article Two"
        },
    };

    public CSharpCornerArticle GetArticleById(int id)
    {
        return _articles.FirstOrDefault(a => a.ArticleId == id);
    }
}

Step 3. AutoMapper Configuration

public void ConfigureServices(IServiceCollection services)
{
    services.AddAutoMapper(typeof(Startup)); // Add AutoMapper
    services.AddScoped<IArticleRepository, ArticleRepository>();
}

Step 4. Controller Implementation

//Sardar Mudassar Ali Khan
//Implementation of ArticleController 
using AutoMapper;

[Route("api/articles")]
[ApiController]
public class ArticleController : ControllerBase
{
    private readonly IArticleRepository _articleRepository;
    private readonly IMapper _mapper;

    public ArticleController(IArticleRepository articleRepository, IMapper mapper)
    {
        _articleRepository = articleRepository;
        _mapper = mapper;
    }

    [HttpGet("{id}")]
    public IActionResult GetArticle(int id)
    {
        var articleFromRepo = _articleRepository.GetArticleById(id);

        if (articleFromRepo == null)
        {
            return NotFound(new ApiResponse<CSharpCornerArticleDto>
            {
                StatusCode = 404,
                Message = "Article not found",
                Data = null
            });
        }

        var mappedArticle = _mapper.Map<CSharpCornerArticleDto>(articleFromRepo);

        return Ok(new ApiResponse<CSharpCornerArticleDto>
        {
            StatusCode = 200,
            Message = "Article found",
            Data = mappedArticle
        });
    }
}

Conclusion

Crafting a robust and user-friendly ASP.NET Core Web API demands meticulous attention to response structuring and data handling. Leveraging AutoMapper alongside well-designed Data Transfer Objects (DTOs) not only facilitates seamless communication between the API and clients but also ensures consistency, predictability, and maintainability in the response structure. By decoupling internal models, mapping strategies, and embracing standardized response formats, developers can foster a more agile, scalable, and error-resilient API ecosystem. This approach not only enhances developer experience but also empowers client integration, setting the stage for a robust.