Cayd.AspNetCore.ExecutionResult
1.0.0
dotnet add package Cayd.AspNetCore.ExecutionResult --version 1.0.0
NuGet\Install-Package Cayd.AspNetCore.ExecutionResult -Version 1.0.0
<PackageReference Include="Cayd.AspNetCore.ExecutionResult" Version="1.0.0" />
<PackageVersion Include="Cayd.AspNetCore.ExecutionResult" Version="1.0.0" />
<PackageReference Include="Cayd.AspNetCore.ExecutionResult" />
paket add Cayd.AspNetCore.ExecutionResult --version 1.0.0
#r "nuget: Cayd.AspNetCore.ExecutionResult, 1.0.0"
#:package Cayd.AspNetCore.ExecutionResult@1.0.0
#addin nuget:?package=Cayd.AspNetCore.ExecutionResult&version=1.0.0
#tool nuget:?package=Cayd.AspNetCore.ExecutionResult&version=1.0.0
About
This is a result pattern library for ASP.NET Core that handles success and error flows in services and CQRS-based architectures. It abstracts HTTP status codes into result and error classes such as ExecOk<TValue>
, ExecNoContent<TValue>
, ExecBadRequest
, ExecInternalServerError
etc. and supports implicit default success (200 OK
) and default error (400 Bad Request
) handling.
How to Use
After installing the package, you can use ExecResult<TValue>
for returning types of your services or CQRS handlers.
- Implicit Success and Implicit Error Handling in Services:
using Cayd.AspNetCore.ExecutionResult;
public class MyService : IMyService
{
// ...
public ExecResult<User> GetUser(Guid id)
{
var user = _dbContext.Users.Find(id);
if (user == null)
return ExecErrorDetail("Message here if needed", "Message code here if needed (can be used for translation keys for instance)"); // -> This implicit usage utilizes ExecBadRequest, which returns 'error' with the HTTP status code of 400.
return user; // -> This implicit usage utilizes ExecOk, which returns 'success' with the HTTP status code of 200.
}
}
- Explicit Success and Explicit Error Handling in Services:
using Cayd.AspNetCore.ExecutionResult;
using Cayd.AspNetCore.ExecutionResult.ClientError;
using Cayd.AspNetCore.ExecutionResult.Success;
public class MyService : IMyService
{
// ...
public ExecResult<MyClass> GetData(string? search)
{
if (CheckIfAuthorized())
return ExecUnauthorized("Message here if needed", "Message code here if needed (can be used for translation keys for instance)");
// Explicit usage of Bad Request. 'ExecErrorDetail' could be used directly as well.
if (search == null)
return ExecBadRequest("Message here if needed", "Message code here if needed (can be used for translation keys for instance)");
var data = _dbContext.Data.Where(x => x.Property1 == search).ToList();
if (data.Count == 0)
return ExecNoContent();
return data; // -> This implicit usage utilizes ExecOk, which returns 'success' with the HTTP status code of 200.
}
}
- Handling The Result:
// By using the Match method's overloads, you can handle success, redirection or error of the execution.
var result = _myService.GetData();
result.Match(
(code, value, metadata) => { /* Success */ },
(code, errors, metadata) => { /* Error */ }
);
var result = _myService.GetData();
result.Match(
(code, metadata) => { /* Redirection */ },
(code, errors, metadata) => { /* Error */ }
);
var result = _myService.GetData();
result.Match(
(code, value, metadata) => { /* Success */ },
(code, metadata) => { /* Redirection */ },
(code, errors, metadata) => { /* Error */ }
);
// Since the returned result also includes the HTTP code, the response can be returned in action methods by using the 'ObjectResult' class.
For CQRS handlers utilizing the MediatR
library:
- Request:
public class GetDataRequest : IRequest<ExecResult<GetDataResponse>>
{
// ...
}
- Handler:
public class GetDataHandler : IRequestHandler<GetDataRequest, ExecResult<GetDataResponse>>
{
// ...
}
- Response:
public class GetDataResponse
{
// ...
}
Result Classes
The library includes all result classes representing 2xx
, 3xx
, 4xx
and 5xx
HTTP status codes. These classes start with the Exec
prefix. For instance, the class representing 204 No Content
is called ExecNoContent
and is under the Cayd.AspNetCore.ExecutionResult.Success
namespace.
Type | Namespace |
---|---|
Success (2xx) | Cayd.AspNetCore.ExecutionResult.Success |
Redirection (3xx) | Cayd.AspNetCore.ExecutionResult.Redirection |
Client error (4xx) | Cayd.AspNetCore.ExecutionResult.ClientError |
Server error (5xx) | Cayd.AspNetCore.ExecutionResult.ServerError |
Extras
For CQRS handlers utilizing the MediatR
library as well as FluentValidation
, the validation pipeline can be set up as follows to use ExecBadRequest
automatically when validations fail:
- Validation Behavior:
using Cayd.AspNetCore.ExecutionResult;
using Cayd.AspNetCore.ExecutionResult.ClientError;
using FluentValidation;
using MediatR;
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
if (_validators.Any())
{
foreach (var validator in _validators)
{
if (validator != null)
{
var validationResult = await validator.ValidateAsync(request, cancellationToken);
if (validationResult.Errors.Count > 0)
{
var errorDetails = validationResult.Errors
.Select(e => new ExecErrorDetail(e.ErrorMessage, e.ErrorCode))
.ToList();
return (dynamic)new ExecBadRequest(errorDetails);
}
}
}
}
return await next();
}
}
- Example Validation in CQRS:
public class GetDataValidation : AbstractValidator<GetDataRequest>
{
public LoginValidation()
{
RuleFor(r => r.Property1)
.NotEmpty()
.WithMessage("Error message here")
.WithErrorCode("Error message code here (can be used for translation keys for instance)");
}
}
- Registering The Pipeline:
builder.Services.AddMediatR(config =>
{
// ...
config.AddOpenBehavior(typeof(ValidationBehavior<,>));
});
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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. |
-
net5.0
- No dependencies.
-
net6.0
- No dependencies.
-
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 | 144 | 6/2/2025 |
First release