CodeMode.ResponseModel 1.0.0

dotnet add package CodeMode.ResponseModel --version 1.0.0
                    
NuGet\Install-Package CodeMode.ResponseModel -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CodeMode.ResponseModel" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CodeMode.ResponseModel" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="CodeMode.ResponseModel" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CodeMode.ResponseModel --version 1.0.0
                    
#r "nuget: CodeMode.ResponseModel, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CodeMode.ResponseModel@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CodeMode.ResponseModel&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=CodeMode.ResponseModel&version=1.0.0
                    
Install as a Cake Tool

CodeMode.ResponseModel

NuGet License .NET

A comprehensive and feature-rich response model package for .NET applications. Provides standardized API response handling with generic/non-generic support, HTTP status code mapping, fluent API, metadata support, validation errors, pagination, extension methods, and automatic timestamp tracking.

🚀 Features

  • Generic & Non-Generic Responses - Support for both Response and Response<T>
  • HTTP Status Code Mapping - Automatic mapping to standard HTTP status codes
  • Fluent API - Chainable methods for elegant response building
  • Metadata Support - Attach additional data using dictionary-based metadata
  • Timestamp Tracking - Automatic UTC timestamp for all responses
  • Validation Errors - Built-in support for validation error handling
  • Custom Errors - Flexible custom error model
  • Pagination Support - PagedResponse<T> for paginated data
  • Extension Methods - Rich set of extension methods for functional programming
  • Exception Details - Debug mode support for exception details
  • Result Pattern - IsSuccess and IsFailure properties
  • Type Safety - Strongly typed responses with full IntelliSense support

📦 Installation

NuGet Package Manager

Install-Package CodeMode.ResponseModel

.NET CLI

dotnet add package CodeMode.ResponseModel

PackageReference

<PackageReference Include="CodeMode.ResponseModel" Version="2.0.0" />

🎯 Quick Start

Basic Usage

using CodeMode.ResponseModel.Concreate.ResponceModel;

// Success response
var response = Response<User>.Success(user, "User created successfully");

// Error response
var response = Response<User>.Error("User not found");

// Not found response
var response = Response<User>.NotFound("User with ID 123 not found");

// Validation error
var errors = new List<CustomValidationError>
{
    new CustomValidationError("Email", "Email is required"),
    new CustomValidationError("Password", "Password must be at least 8 characters")
};
var response = Response<User>.ValidationError(errors);

Fluent API

var response = Response<User>.Success(user)
    .WithMessage("User created successfully")
    .WithMetadata("requestId", Guid.NewGuid())
    .WithMetadata("executionTime", "150ms")
    .WithMetadata("server", "API-01");

ASP.NET Core Integration

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IUserService _userService;

    [HttpPost]
    public IActionResult CreateUser(CreateUserDto dto)
    {
        var response = _userService.CreateUser(dto);
        return StatusCode(response.HttpStatusCode, response);
    }

    [HttpGet("{id}")]
    public IActionResult GetUser(int id)
    {
        var response = _userService.GetUser(id);
        
        if (response.IsSuccess)
            return Ok(response);
        
        return StatusCode(response.HttpStatusCode, response);
    }
}

📖 Documentation

Response Types

1. Success Responses
// With data and message
var response = Response<User>.Success(user, "Operation completed successfully");

// With metadata
var response = Response<User>.Success(user, "User created", new Dictionary<string, object>
{
    ["userId"] = user.Id,
    ["createdAt"] = DateTime.UtcNow
});
2. Error Responses
// Bad Request (400)
Response<User>.BadRequest("Invalid input data");

// Unauthorized (401)
Response<User>.Unauthorized("Invalid credentials");

// Forbidden (403)
Response<User>.Forbidden("You don't have permission to access this resource");

// Not Found (404)
Response<User>.NotFound("User not found");

// Conflict (409)
Response<User>.Conflict("User already exists");

// Validation Error (422)
Response<User>.ValidationError(validationErrors);

// Internal Server Error (500)
Response<User>.Error("An unexpected error occurred");
Response<User>.InternalServerError("Database connection failed");
3. Validation Errors
var validationErrors = new List<CustomValidationError>
{
    new CustomValidationError("Email", "Email is required"),
    new CustomValidationError("Email", "Email format is invalid"),
    new CustomValidationError("Password", "Password must be at least 8 characters"),
    new CustomValidationError("Password", "Password must contain at least one uppercase letter")
};

var response = Response<User>.ValidationError(validationErrors);
4. Custom Errors
var customErrors = new List<CustomError>
{
    new CustomError("DB_CONNECTION_FAILED", "Unable to connect to database"),
    new CustomError("CACHE_UNAVAILABLE", "Redis cache is not responding")
};

var response = Response.Error(customErrors);

Pagination Support

public PagedResponse<List<User>> GetUsers(int pageIndex, int pageSize)
{
    var users = _userRepository.GetUsers(pageIndex, pageSize);
    var totalCount = _userRepository.GetTotalCount();

    return PagedResponse<List<User>>
        .Create(users, pageIndex, pageSize, totalCount)
        .WithMessage("Users retrieved successfully")
        .WithMetadata("cacheHit", true);
}

// Response includes:
// - Data (List<User>)
// - PageIndex (current page)
// - PageSize (items per page)
// - TotalCount (total items)
// - TotalPages (calculated)
// - HasPreviousPage (boolean)
// - HasNextPage (boolean)

Fluent API Methods

var response = Response<User>.Success(user)
    .WithMessage("Custom message")
    .WithMetadata("key", "value")
    .WithMetadata(new Dictionary<string, object>
    {
        ["requestId"] = Guid.NewGuid(),
        ["timestamp"] = DateTime.UtcNow
    })
    .WithData(updatedUser);

#if DEBUG
response.WithException(exception);
#endif

Extension Methods

OnSuccess & OnFailure
response
    .OnSuccess(user => 
    {
        _logger.LogInformation($"User {user.Name} created successfully");
        _eventBus.Publish(new UserCreatedEvent(user));
    })
    .OnFailure(resp => 
    {
        _logger.LogError($"Failed to create user: {resp.Message}");
    });
Map - Transform Response Data
Response<UserDto> dtoResponse = userResponse.Map(user => new UserDto
{
    Id = user.Id,
    Name = user.Name,
    Email = user.Email
});
Bind - Monad Pattern
public Response<Order> CreateOrder(int userId)
{
    return GetUser(userId)
        .Bind(user => ValidateUser(user))
        .Bind(user => CreateOrderForUser(user));
}
Validation Helpers
if (response.HasValidationErrors())
{
    var firstError = response.GetFirstValidationError();
    Console.WriteLine($"Validation failed: {firstError}");
}

if (response.HasErrors())
{
    var firstError = response.GetFirstError();
    Console.WriteLine($"Error: {firstError}");
}
Metadata Helpers
if (response.HasMetadata("requestId"))
{
    var requestId = response.GetMetadata<Guid>("requestId");
    _logger.LogInformation($"Request ID: {requestId}");
}
Combine Responses
var combinedResponse = firstResponse.Combine(secondResponse);
// Returns first failure, or first success if both succeed

Response Properties

public class Response<T>
{
    // Data
    public T Data { get; set; }
    
    // Status
    public ResponseStatusCode ResponseStatusCode { get; set; }
    public int HttpStatusCode { get; }  // Auto-mapped (200, 400, 401, 404, etc.)
    public bool IsSuccess { get; }      // True if ResponseStatusCode == Success
    public bool IsFailure { get; }      // !IsSuccess
    
    // Message & Errors
    public string Message { get; set; }
    public IEnumerable<CustomValidationError> ValidationErrors { get; set; }
    public IEnumerable<CustomError> Errors { get; set; }
    
    // Metadata & Tracking
    public Dictionary<string, object> Metadata { get; set; }
    public DateTime Timestamp { get; set; }  // UTC, auto-set
    
    // Debug Info (only in DEBUG builds)
    #if DEBUG
    public string ExceptionMessage { get; set; }
    public string StackTrace { get; set; }
    #endif
}

HTTP Status Code Mapping

ResponseStatusCode HTTP Status Code Description
Success 200 Request succeeded
BadRequest 400 Invalid request data
Unauthorized 401 Authentication required
Forbidden 403 Insufficient permissions
NotFound 404 Resource not found
Conflict 409 Resource conflict
ValidationError 422 Validation failed
Error 500 Internal server error
InternalServerError 500 Internal server error

🔧 Advanced Usage

Service Layer Pattern

public interface IUserService
{
    Response<User> GetUser(int id);
    Response<User> CreateUser(CreateUserDto dto);
    PagedResponse<List<User>> GetUsers(int pageIndex, int pageSize);
}

public class UserService : IUserService
{
    private readonly IUserRepository _repository;
    private readonly IValidator<CreateUserDto> _validator;

    public Response<User> CreateUser(CreateUserDto dto)
    {
        // Validate
        var validationResult = _validator.Validate(dto);
        if (!validationResult.IsValid)
        {
            var errors = validationResult.Errors
                .Select(e => new CustomValidationError(e.PropertyName, e.ErrorMessage))
                .ToList();
            return Response<User>.ValidationError(errors);
        }

        try
        {
            // Check for duplicates
            if (_repository.EmailExists(dto.Email))
            {
                return Response<User>.Conflict($"User with email {dto.Email} already exists");
            }

            // Create user
            var user = _repository.Create(dto);
            
            return Response<User>.Success(user, "User created successfully")
                .WithMetadata("userId", user.Id)
                .WithMetadata("createdAt", DateTime.UtcNow);
        }
        catch (Exception ex)
        {
            #if DEBUG
            return Response<User>.Error(ex);
            #else
            return Response<User>.Error("An error occurred while creating the user");
            #endif
        }
    }
}

Middleware Integration

public class ResponseFormatterMiddleware
{
    private readonly RequestDelegate _next;

    public async Task InvokeAsync(HttpContext context)
    {
        var originalBodyStream = context.Response.Body;

        using (var responseBody = new MemoryStream())
        {
            context.Response.Body = responseBody;

            await _next(context);

            context.Response.Body = originalBodyStream;
            responseBody.Seek(0, SeekOrigin.Begin);
            
            var responseText = await new StreamReader(responseBody).ReadToEndAsync();
            
            // Add global metadata
            var response = JsonSerializer.Deserialize<Response>(responseText);
            if (response != null)
            {
                response.Metadata["serverId"] = Environment.MachineName;
                response.Metadata["apiVersion"] = "v1";
                
                var modifiedResponse = JsonSerializer.Serialize(response);
                await context.Response.WriteAsync(modifiedResponse);
            }
        }
    }
}

Unit Testing

[Fact]
public void CreateUser_ValidData_ReturnsSuccess()
{
    // Arrange
    var dto = new CreateUserDto { Name = "Test", Email = "test@test.com" };
    
    // Act
    var response = _userService.CreateUser(dto);
    
    // Assert
    Assert.True(response.IsSuccess);
    Assert.NotNull(response.Data);
    Assert.Equal("User created successfully", response.Message);
    Assert.Equal(200, response.HttpStatusCode);
}

[Fact]
public void CreateUser_DuplicateEmail_ReturnsConflict()
{
    // Arrange
    var dto = new CreateUserDto { Name = "Test", Email = "existing@test.com" };
    
    // Act
    var response = _userService.CreateUser(dto);
    
    // Assert
    Assert.False(response.IsSuccess);
    Assert.True(response.IsFailure);
    Assert.Equal(409, response.HttpStatusCode);
    Assert.Contains("already exists", response.Message);
}

📝 Best Practices

  1. Always use factory methods instead of constructors:

    ✅ Response<User>.Success(user)
    ❌ new Response<User>(ResponseStatusCode.Success, user)
    
  2. Use fluent API for complex responses:

    return Response<User>.Success(user)
        .WithMessage("User created")
        .WithMetadata("requestId", requestId);
    
  3. Check success before accessing data:

    if (response.IsSuccess)
    {
        var user = response.Data;
    }
    
  4. Use extension methods for cleaner code:

    response
        .OnSuccess(user => NotifyUser(user))
        .OnFailure(resp => LogError(resp.Message));
    
  5. Leverage metadata for tracing:

    return Response<User>.Success(user)
        .WithMetadata("requestId", HttpContext.TraceIdentifier)
        .WithMetadata("executionTime", stopwatch.ElapsedMilliseconds);
    

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

📧 Support

If you encounter any issues or have questions, please open an issue on GitHub.


Made with ❤️ by CodeMode Team

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 111 1/27/2026