Skip to content

Instantly share code, notes, and snippets.

@nathan-alden-sr
Created November 5, 2021 03:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nathan-alden-sr/14f7d20e3b3a321acd510f0e9e97068f to your computer and use it in GitHub Desktop.
Save nathan-alden-sr/14f7d20e3b3a321acd510f0e9e97068f to your computer and use it in GitHub Desktop.
ASP.NET Core 6: Standard response fluent API
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.Extensions.Primitives;
public static class StandardResponse
{
// 100 Continue
public static StandardResponseBuilder Continue() => new(StatusCodes.Status100Continue);
// 200 OK
public static StandardResponseBuilder Ok() => new(StatusCodes.Status200OK);
// 201 Created
public static StandardResponseBuilder Created(string location) =>
new StandardResponseBuilder(StatusCodes.Status201Created).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder Created(Uri location) =>
Created(location.ToString());
public static StandardResponseBuilder CreatedAtAction(string? actionName, string? controllerName, object? routeValues)
{
return new StandardResponseBuilder(StatusCodes.Status201Created).WithFormatting(
context =>
{
HttpRequest request = context.HttpContext.Request;
IUrlHelper urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
string? url = urlHelper.Action(actionName, controllerName, routeValues, request.Scheme, request.Host.ToUriComponent());
if (string.IsNullOrEmpty(url))
{
ThrowInvalidOperationException("No routes matched the supplied values.");
}
context.HttpContext.Response.Headers.Location = url;
});
}
public static StandardResponseBuilder CreatedAtAction(string? actionName, object? routeValues) =>
CreatedAtAction(actionName, null, routeValues);
public static StandardResponseBuilder CreatedAtAction(string? actionName) =>
CreatedAtAction(actionName, null, null);
public static StandardResponseBuilder CreatedAtRoute(string? routeName, object? routeValues)
{
return new StandardResponseBuilder(StatusCodes.Status201Created).WithFormatting(
context =>
{
ThrowIfNull(context, nameof(context));
IUrlHelper urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
string? url = urlHelper.Link(routeName, routeValues);
if (string.IsNullOrEmpty(url))
{
ThrowInvalidOperationException("No routes matched the supplied values.");
}
context.HttpContext.Response.Headers.Location = url;
});
}
public static StandardResponseBuilder CreatedAtRoute(string? routeName) =>
CreatedAtRoute(routeName, null);
public static StandardResponseBuilder CreatedAtRoute(object? routeValues) =>
CreatedAtRoute(null, routeValues);
// 202 Accepted
public static StandardResponseBuilder Accepted(string? location) =>
new StandardResponseBuilder(StatusCodes.Status202Accepted).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder Accepted(Uri? location) =>
Accepted(location?.ToString());
public static StandardResponseBuilder AcceptedAtAction(string? actionName, string? controllerName, object? routeValues)
{
return new StandardResponseBuilder(StatusCodes.Status202Accepted).WithFormatting(
context =>
{
HttpRequest request = context.HttpContext.Request;
IUrlHelper urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
string? url = urlHelper.Action(actionName, controllerName, routeValues, request.Scheme, request.Host.ToUriComponent());
if (string.IsNullOrEmpty(url))
{
ThrowInvalidOperationException("No routes matched the supplied values.");
}
context.HttpContext.Response.Headers.Location = url;
});
}
public static StandardResponseBuilder AcceptedAtAction(string? actionName, object? routeValues) =>
AcceptedAtAction(actionName, null, routeValues);
public static StandardResponseBuilder AcceptedAtAction(string? actionName) =>
AcceptedAtAction(actionName, null, null);
public static StandardResponseBuilder AcceptedAtRoute(string? routeName, object? routeValues)
{
return new StandardResponseBuilder(StatusCodes.Status202Accepted).WithFormatting(
context =>
{
ThrowIfNull(context, nameof(context));
IUrlHelper urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
string? url = urlHelper.Link(routeName, routeValues);
if (string.IsNullOrEmpty(url))
{
ThrowInvalidOperationException("No routes matched the supplied values.");
}
context.HttpContext.Response.Headers.Location = url;
});
}
public static StandardResponseBuilder AcceptedAtRoute(string? routeName) =>
AcceptedAtRoute(routeName, null);
public static StandardResponseBuilder AcceptedAtRoute(object? routeValues) =>
AcceptedAtRoute(null, routeValues);
// 204 No Content
public static StandardResponseBuilder NoContent() =>
new(StatusCodes.Status204NoContent);
// 300 Multiple Choices
public static StandardResponseBuilder MultipleChoices(string? location) =>
new StandardResponseBuilder(StatusCodes.Status300MultipleChoices).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder MultipleChoices(Uri? location) =>
new StandardResponseBuilder(StatusCodes.Status300MultipleChoices).WithFormatting(
context => context.HttpContext.Response.Headers.Location = location?.ToString());
public static StandardResponseBuilder MultipleChoicesWithPreferredAction(string? actionName, string? controllerName, object? routeValues)
{
return new StandardResponseBuilder(StatusCodes.Status300MultipleChoices).WithFormatting(
context =>
{
HttpRequest request = context.HttpContext.Request;
IUrlHelper urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
string? url = urlHelper.Action(actionName, controllerName, routeValues, request.Scheme, request.Host.ToUriComponent());
if (string.IsNullOrEmpty(url))
{
ThrowInvalidOperationException("No routes matched the supplied values.");
}
context.HttpContext.Response.Headers.Location = url;
});
}
public static StandardResponseBuilder MultipleChoicesWithPreferredAction(string? actionName, object? routeValues) =>
MultipleChoicesWithPreferredAction(actionName, null, routeValues);
public static StandardResponseBuilder MultipleChoicesWithPreferredAction(string? actionName) =>
MultipleChoicesWithPreferredAction(actionName, null, null);
public static StandardResponseBuilder MultipleChoicesWithPreferredRoute(string? routeName, object? routeValues)
{
return new StandardResponseBuilder(StatusCodes.Status300MultipleChoices).WithFormatting(
context =>
{
ThrowIfNull(context, nameof(context));
IUrlHelper urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
string? url = urlHelper.Link(routeName, routeValues);
if (string.IsNullOrEmpty(url))
{
ThrowInvalidOperationException("No routes matched the supplied values.");
}
context.HttpContext.Response.Headers.Location = url;
});
}
public static StandardResponseBuilder MultipleChoicesWithPreferredRoute(string? routeName) =>
MultipleChoicesWithPreferredRoute(routeName, null);
public static StandardResponseBuilder MultipleChoicesWithPreferredRoute(object? routeValues) =>
MultipleChoicesWithPreferredRoute(null, routeValues);
// 301 Moved Permanently
public static StandardResponseBuilder MovedPermanently(string location) =>
new StandardResponseBuilder(StatusCodes.Status301MovedPermanently).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder MovedPermanently(Uri location) =>
MovedPermanently(location.ToString());
// 302 Found
public static StandardResponseBuilder Found(string location) =>
new StandardResponseBuilder(StatusCodes.Status302Found).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder Found(Uri location) =>
Found(location.ToString());
// 303 See Other
public static StandardResponseBuilder SeeOther(string location) =>
new StandardResponseBuilder(StatusCodes.Status302Found).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder SeeOther(Uri location) =>
SeeOther(location.ToString());
// 304 Not Modified
public static StandardResponseBuilder NotModified() => new(StatusCodes.Status304NotModified);
// 307 Temporary Redirect
public static StandardResponseBuilder TemporaryRedirect(string location) =>
new StandardResponseBuilder(StatusCodes.Status307TemporaryRedirect).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder TemporaryRedirect(Uri location) =>
TemporaryRedirect(location.ToString());
// 308 Permanent Redirect
public static StandardResponseBuilder PermanentRedirect(string location) =>
new StandardResponseBuilder(StatusCodes.Status308PermanentRedirect).WithFormatting(context => context.HttpContext.Response.Headers.Location = location);
public static StandardResponseBuilder PermanentRedirect(Uri location) =>
PermanentRedirect(location.ToString());
// 400 Bad Request
public static StandardResponseBuilder BadRequest() => new(StatusCodes.Status400BadRequest);
// 401 Unauthorized
public static StandardResponseBuilder Unauthorized(StringValues wwwAuthenticate) =>
new StandardResponseBuilder(StatusCodes.Status401Unauthorized)
.WithFormatting(context => context.HttpContext.Response.Headers.WWWAuthenticate = wwwAuthenticate);
// 403 Forbidden
public static StandardResponseBuilder Forbidden() => new(StatusCodes.Status403Forbidden);
// 404 Not Found
public static StandardResponseBuilder NotFound() => new(StatusCodes.Status404NotFound);
// 405 Method Not Allowed
public static StandardResponseBuilder MethodNotAllowed() => new(StatusCodes.Status405MethodNotAllowed);
// 406 Not Acceptable
public static StandardResponseBuilder NotAcceptable() => new(StatusCodes.Status406NotAcceptable);
// 407 Proxy Authentication Required
public static StandardResponseBuilder ProxyAuthenticationRequired(StringValues proxyAuthenticate) =>
new StandardResponseBuilder(StatusCodes.Status407ProxyAuthenticationRequired)
.WithFormatting(context => context.HttpContext.Response.Headers.ProxyAuthenticate = proxyAuthenticate);
// 408 Request Timeout
public static StandardResponseBuilder RequestTimeout(bool closeConnection = true) =>
new StandardResponseBuilder(StatusCodes.Status408RequestTimeout)
.WithFormatting(
context =>
{
if (closeConnection)
{
context.HttpContext.Response.Headers.Connection = "Close";
}
});
// 409 Conflict
public static StandardResponseBuilder Conflict() => new(StatusCodes.Status409Conflict);
// 410 Gone
public static StandardResponseBuilder Gone() => new(StatusCodes.Status410Gone);
// 411 Length Required
public static StandardResponseBuilder LengthRequired() => new(StatusCodes.Status411LengthRequired);
// 412 Preconditon Failed
public static StandardResponseBuilder PreconditionFailed() => new(StatusCodes.Status412PreconditionFailed);
// 413 Payload Too Large
public static StandardResponseBuilder PayloadTooLarge() => new(StatusCodes.Status413PayloadTooLarge);
// 414 URI Too Large
public static StandardResponseBuilder UriTooLong() => new(StatusCodes.Status414UriTooLong);
// 415 Unsupported Media Type
public static StandardResponseBuilder UnsupportedMediaType() => new(StatusCodes.Status415UnsupportedMediaType);
// 416 Range Not Satisfiable
public static StandardResponseBuilder RangeNotSatisfiable(StringValues contentRange) =>
new StandardResponseBuilder(StatusCodes.Status416RangeNotSatisfiable)
.WithFormatting(context => context.HttpContext.Response.Headers.ContentRange = contentRange);
// 417 Expectation Failed
public static StandardResponseBuilder ExpectationFailed() => new(StatusCodes.Status417ExpectationFailed);
// 418 I'm a Teapot
public static StandardResponseBuilder ImATeapot() => new(StatusCodes.Status418ImATeapot);
// 428 Precondition Required
public static StandardResponseBuilder PreconditionRequired() => new(StatusCodes.Status428PreconditionRequired);
// 431 Request Header Fields Too Large
public static StandardResponseBuilder RequestHeaderFieldsTooLarge() => new(StatusCodes.Status431RequestHeaderFieldsTooLarge);
// 451 Unavailable for Legal Reasons
public static StandardResponseBuilder UnavailableForLegalReasons() => new(StatusCodes.Status451UnavailableForLegalReasons);
// 500 Internal Server Error
public static StandardResponseBuilder InternalServerError() => new(StatusCodes.Status500InternalServerError);
// 501 Not Implemented
public static StandardResponseBuilder NotImplemented(StringValues? retryAfter) =>
new StandardResponseBuilder(StatusCodes.Status501NotImplemented)
.WithFormatting(
context =>
{
if (retryAfter is not null)
{
context.HttpContext.Response.Headers.RetryAfter = retryAfter.Value;
}
});
// 502 Bad Gateway
public static StandardResponseBuilder BadGateway() => new(StatusCodes.Status502BadGateway);
// 503 Service Unavailable
public static StandardResponseBuilder ServiceUnavailable() => new(StatusCodes.Status503ServiceUnavailable);
// 504 Gateway Timeout
public static StandardResponseBuilder GatewayTimeout() => new(StatusCodes.Status504GatewayTimeout);
// 505 HTTP Version Not Supported
public static StandardResponseBuilder HttpVersionNotSupported() => new(StatusCodes.Status505HttpVersionNotsupported);
// 506 Variant Also Negotiates
public static StandardResponseBuilder VariantAlsoNegotiates() => new(StatusCodes.Status506VariantAlsoNegotiates);
// 510 Not Extended
public static StandardResponseBuilder NotExtended() => new(StatusCodes.Status510NotExtended);
// 511 Network Authentication Required
public static StandardResponseBuilder NetworkAuthenticationRequired() => new(StatusCodes.Status511NetworkAuthenticationRequired);
}
using Microsoft.AspNetCore.Mvc;
public class StandardResponseBuilder
{
public StandardResponseBuilder(int? statusCode = null)
{
StatusCode = statusCode;
}
public int? StatusCode { get; private set; }
public string? Message { get; private set; }
public List<Action<ActionContext>> Formatters { get; } = new();
public StandardResponseBuilder WithStatusCode(int statusCode)
{
StatusCode = statusCode;
return this;
}
public StandardResponseBuilder<T> WithData<T>(T data) =>
new(data);
public StandardResponseBuilder WithMessage(string message)
{
ThrowIfNull(message, nameof(message));
Message = message;
return this;
}
public StandardResponseBuilder WithFormatting(Action<ActionContext> formatter)
{
ThrowIfNull(formatter, nameof(formatter));
Formatters.Add(formatter);
return this;
}
public IStandardResponse<object?> Build() =>
new StandardResponse<object?>(
StatusCode,
null,
Message,
Formatters.Count > 0
? context =>
{
foreach (Action<ActionContext> formatter in Formatters)
{
formatter(context);
}
}
: null);
}
using Microsoft.AspNetCore.Mvc;
public sealed class StandardResponseBuilder<T> : StandardResponseBuilder
{
public StandardResponseBuilder(T? data = default, int? statusCode = null) : base(statusCode)
{
Data = data;
}
public T? Data { get; }
public new IStandardResponse<T> Build() =>
new StandardResponse<T>(
StatusCode,
Data,
Message,
Formatters.Count > 0
? context =>
{
foreach (Action<ActionContext> formatter in Formatters)
{
formatter(context);
}
}
: null);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment