Created
November 5, 2021 03:53
-
-
Save nathan-alden-sr/14f7d20e3b3a321acd510f0e9e97068f to your computer and use it in GitHub Desktop.
ASP.NET Core 6: Standard response fluent API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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