Result Wrapper Package: Simplifying API Responses

Introduction

The ResultWrapper package is a powerful tool that simplifies the handling of API responses in your .NET applications. It provides a set of static methods within the ResultWrapper class, enabling you to effortlessly create and manage success and failure scenarios. This package encapsulates various data elements, including payloads, errors, success and error messages, status codes, and pagination information. By doing so, it offers a standardized approach to handling and representing the results of various operations, ensuring a consistent and robust API response.

One of the primary objectives of the ResultWrapper package is to standardize API responses. This standardization allows for seamless integration with other APIs and ensures that the response format remains predictable and manageable across different parts of your application.

Why Use ResultWrapper?
 

1. Strongly Typed and Loosely Typed Payloads

One of the key benefits of using the ResultWrapper package is the ability to work with both strongly typed and loosely typed payloads. When you use this package, the response will include only the properties you have explicitly defined, eliminating the inclusion of extraneous keys or data in the response. This strict adherence to data structure simplifies data exchange between different parts of your application.

2. Standardized API Responses

By using ResultWrapper, you adopt a standardized approach to creating API responses. This consistency not only improves code readability but also streamlines communication between different components of your application. Whether you're working on a small project or a large-scale application, having a consistent API response format simplifies development and maintenance.

Installation

To integrate the ResultWrapper package into your .NET project, follow these simple steps:

Open the NuGet Package Manager Console in Visual Studio.

Use the following command to install the package:

`dotnet add package RW`

Alternatively, you can use the NuGet Package Manager UI by searching for "RW" and installing it from there.

Usage

The ResultWrapper class offers a wide range of overloaded methods to handle different success and failure scenarios. These methods are categorized into two main groups: generic and non-generic overloads. You can choose the approach that best suits your specific requirements.

Success and Failure Overloads

// To return empty success result.
return ResultWrapper.Success<MyPayload>();

// To return empty failure result.
return ResultWrapper.Failure<MyErrors>();

// Return success result with payload only.
var payload = new MyPayload();
return ResultWrapper.Success<MyPayload>(payload);

// Return success result with errors only. 
// Note: (Normally this method used to return failure response in fluent validations or global exception handling middleware)
var errors = new MyErrors();
return ResultWrapper.Failure<MyErrors>(errors);

// Return success result with message and status
return ResultWrapper.Success<MyPayload>("Success message", 200);

// Return failure result with message and status
return ResultWrapper.Failure<MyErrors>("Error message", 500);

// Return success result with a payload, message, and status code.
var payload = new MyPayload();
return ResultWrapper.Success<MyPayload>(payload, "Success message", 200);

// Return failure result with a errors, message, and status code.
// Note: (Normally this method used to return failure response in fluent validations or global exception handling middleware)
var errors = new MyErrors();
var result = ResultWrapper.Failure<MyErrors>(errors, "Error message", 500);

// Return success result with a payload, pagination information, message, and status code.
var payload = new MyPayload();
var paginationInfo = new Pagination();
return ResultWrapper.Success(payload, paginationInfo, "Success message", 200);

Example of Generic IResultWrapper<T>

Note: The result wrapper will return a payload of type WeatherForecastInfo[] when using a generic approach. However, when a non-generic approach is used, the payload will be of type object.

// How to use Generic IResultWrapper<T>
// Example:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{

	[HttpGet(Name = "GetWeatherForecast")]
	public ActionResult Get()
	{
		var result = Weather.GetWeatherInfo();

		/*
		// These are the properties available in IResultWrapper
		var payload = result.Payload; // To get the payload
		bool isSuccess = result.IsSuccess; // To check whether a success case is returned or a failure
		string message = result.Message; // Get the failure or success message if you have passed it as an argument
		int statusCode = result.Code; // Get the failure or success codes if you have passed them as arguments
		var errors = result.Errors; // To get a list of errors
		*/

		if (result.IsSuccess)
		{
			return Ok(result);
		}
		return BadRequest();
	}
}

public static class Weather
{
	public static IResultWrapper<WeatherForecast[]> GetWeatherInfo()
	{
		var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };

		var weatherForecasts = Enumerable.Range(1, 5).Select(index =>
				new WeatherForecast
				{
					Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
					Summary = summaries[Random.Shared.Next(summaries.Length)],
					TemperatureC = Random.Shared.Next(-20, 55),
				})
				.ToArray();

		if (weatherForecasts != null)
		{
			return ResultWrapper.Success<WeatherForecast[]>(weatherForecasts, "Hello", 300);
		}
		return ResultWrapper.Failure<WeatherForecast[]>("Not Found", 404);
	}
}

Example of Non-Generic IResultWrapper


// How to use Non Generic IResultWrapper
// Example:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{

	[HttpGet(Name = "GetWeatherForecast")]
	public ActionResult Get()
	{
		var result = Weather.GetWeatherInfo();

		/*
		// These are the properties available in IResultWrapper
		var payload = result.Payload; // To get the payload
		bool isSuccess = result.IsSuccess; // To check whether a success case is returned or a failure
		string message = result.Message; // Get the failure or success message if you have passed it as an argument
		int statusCode = result.Code; // Get the failure or success codes if you have passed them as arguments
		var errors = result.Errors; // To get a list of errors
		*/

		// Note: If you are using non generic IResult Wrapper, you can still convert loosly typed payload to strongly typed payload by using ConvertToType method
		
		// WeatherForecast[]? weatherForecasts = result.Payload?.ConvertToType<WeatherForecast[]>();

		if (result.IsSuccess)
		{
			return Ok(result);
		}
		return BadRequest();
	}
}

public static class Weather
{
	public static IResultWrapper GetWeatherInfo()
	{
		var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };

		var weatherForecasts = Enumerable.Range(1, 5).Select(index =>
				new WeatherForecast
				{
					Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
					Summary = summaries[Random.Shared.Next(summaries.Length)],
					TemperatureC = Random.Shared.Next(-20, 55),
				})
				.ToArray();

		if (weatherForecasts != null)
		{
			return ResultWrapper.Success(weatherForecasts, "Hello", 300);
		}
		return ResultWrapper.Failure("Not Found", 404);
	}
}

Conclusion

The ResultWrapper package offers a streamlined solution for creating and managing API responses in .NET applications. It simplifies the process of handling success and failure scenarios while providing a consistent and standardized approach to API response formatting. By adopting this package, you can enhance the maintainability, readability, and reliability of your codebase, making it a valuable addition to your development toolkit.

Disclaimer: I am the author of this package.


Similar Articles