Request response

Request response

When writing logic, the operation typically validates, executes code (which can fail), and returns a type that encapsulates the result.

Most common code follows the pattern of raising exceptions (the exception path) and returning the response of success, while validations are abstracted into the framework of choice.

I prefer (and I am aware of the pros and cons) to have methods that return a complex type that provides the following information:

Later, I have implemented IActionResult to return the response from the API controller following the .Net Core interface.


Request response:

public class ReqResult<T> : IActionResult
{
    public ValidationStatus? ValidationStatus { get; init; }
    public ServerError? Error { get; init; }
    public T? Result { get; init; }
    public bool Success => Error == null && Result != null && ValidationStatus == null;
    public HttpStatusCode StatusCode { get; init; }
    public static ReqResult<T> CreateSuccess(T result, bool wasCreated = true)
    {
        var statusCode = wasCreated ? HttpStatusCode.Created : HttpStatusCode.Accepted;
        return new ReqResult<T> { Result = result, StatusCode = statusCode };
    }

    public static ReqResult<T> CreateSuccess(bool wasCreated = true)
    {
        var statusCode = wasCreated ? HttpStatusCode.Created : HttpStatusCode.Accepted;
        return new ReqResult<T> { StatusCode = statusCode };
    }

    public static ReqResult<T> NotFound(T result = default)
    {
        return new ReqResult<T> { Result = default, StatusCode = HttpStatusCode.NotFound };
    }

    public static ReqResult<T> NotFound<TNotFound>(TNotFound result = default)
    {
        return new ReqResult<T> { Result = default, StatusCode = HttpStatusCode.NotFound };
    }

    public static ReqResult<T> ValidationFail(ValidationStatus validationStatus)
    {
        return new ReqResult<T> { ValidationStatus = validationStatus, StatusCode = HttpStatusCode.BadRequest };
    }

    public static ReqResult<T> ServerError(ServerError serverError)
    {
        return new ReqResult<T> { Error = serverError, StatusCode = HttpStatusCode.ServiceUnavailable };
    }

    public async Task ExecuteResultAsync(ActionContext context)
    {
        context.HttpContext.Response.StatusCode = (int)StatusCode;
        if (!object.Equals(Result, default(T)))
        {
            await context.HttpContext.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(Result)).ConfigureAwait(false);
            return;
        }
        if (!object.Equals(Error, default(T))) 
        {
            await context.HttpContext.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(Error)).ConfigureAwait(false);
            return;
        }
        if (!object.Equals(ValidationStatus, default(T))) 
        {
            await context.HttpContext.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(ValidationStatus)).ConfigureAwait(false);
            return;
        }
        await context.HttpContext.Response.WriteAsync(string.Empty);
    }
}        


Validation:

public class ValidationStatus
{
    public bool IsValid => !Failures.Any();
    public List<ValidationFailure> Failures { get; set; } = new List<ValidationFailure>();

    public static ValidationStatus CreateInvalid(string code = "", string message = "") 
    {
        return new ValidationStatus
        {
            Failures = new List<ValidationFailure> { new ValidationFailure { FailureCode = code, Message = message } }
        };
    }

    public static ValidationStatus CreateInvalid(List<KeyValuePair<string, string>> failures) 
    {
        var validationStatus = new ValidationStatus
        {
            Failures = new List<ValidationFailure>()
        };
        foreach (var failure in failures) 
        {
            validationStatus.Failures.Add(new ValidationFailure { FailureCode = failure.Key, Message = failure.Value });
        }
        return validationStatus;
    }
}        

ServerError:

public class ServerError
{
    public string Message { get; set; } = string.Empty;
    public string Type { get;set; } = String.Empty;
    public string Title { get; set; } = String.Empty;
    public string Detail { get; set; } = String.Empty;
}        




To view or add a comment, sign in

Others also viewed

Explore topics