@typespec/http-server-csharp
Version:
TypeSpec service code generator for c-sharp
792 lines (698 loc) • 30.1 kB
JavaScript
import { LibrarySourceFile } from "./interfaces.js";
export const GeneratedFileHeader = `// Generated by @typespec/http-server-csharp
// <auto-generated />`;
export const GeneratedFileHeaderWithNullable = `// Generated by @typespec/http-server-csharp
// <auto-generated />
#nullable enable`;
export function getSerializationSourceFiles(emitter) {
const sourceFiles = [];
sourceFiles.push(new LibrarySourceFile({
filename: "TimeSpanDurationConverter.cs",
emitter: emitter,
getContents: getTimeSpanDurationConverter,
}), new LibrarySourceFile({
filename: "Base64UrlJsonConverter.cs",
emitter: emitter,
getContents: getBase64UrlJsonConverter,
}), new LibrarySourceFile({
filename: "UnixEpochDateTimeConverter.cs",
emitter: emitter,
getContents: getUnixEpochDateTimeConverter,
}), new LibrarySourceFile({
filename: "UnixEpochDateTimeOffsetConverter.cs",
emitter: emitter,
getContents: getUnixEpochDateTimeOffsetConverter,
}), new LibrarySourceFile({
filename: "NumericConstraintAttribute.cs",
emitter: emitter,
getContents: getNumericConstraintConverter,
}), new LibrarySourceFile({
filename: "StringConstraintAttribute.cs",
emitter: emitter,
getContents: getStringConstraintConverter,
}), new LibrarySourceFile({
filename: "ArrayConstraintAttribute.cs",
emitter: emitter,
getContents: getArrayConstraintConverter,
}), new LibrarySourceFile({
filename: "StringArrayConstraintAttribute.cs",
emitter: emitter,
getContents: getStringArrayConstraintConverter,
}), new LibrarySourceFile({
filename: "NumericArrayConstraintAttribute.cs",
emitter: emitter,
getContents: getNumericArrayConstraintConverter,
}), new LibrarySourceFile({
filename: "IJsonSerializationProvider.cs",
emitter: emitter,
getContents: getJsonProviderInterface,
}), new LibrarySourceFile({
filename: "JsonSerializationProvider.cs",
emitter: emitter,
getContents: getJsonProvider,
}), new LibrarySourceFile({
filename: "HttpServiceException.cs",
emitter: emitter,
getContents: getHttpServiceException,
}));
return sourceFiles;
}
function getNumericConstraintConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Numerics;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Provides numeric constraint validation at serialization time
/// </summary>
/// <typeparam name="T"></typeparam>
public class NumericConstraintAttribute<T> : JsonConverterAttribute where T: struct, INumber<T>
{
T? _minValue = null, _maxValue = null;
public NumericConstraintAttribute()
{
}
/// <summary>
/// Provides the minimum value
/// </summary>
public T MinValue { get { return _minValue.HasValue ? _minValue.Value : default(T); } set { _minValue = value; } }
/// <summary>
/// Provides the maximum allowed value
/// </summary>
public T MaxValue { get { return _maxValue.HasValue ? _maxValue.Value : default(T); } set { _maxValue = value; } }
/// <summary>
/// If true, then values greater than but not equal to the minimum value are allowed
/// </summary>
public bool MinValueExclusive { get; set; }
/// <summary>
/// If true, values less than, but not equal to the provided maximum are allowed
/// </summary>
public bool MaxValueExclusive { get; set; }
public override JsonConverter? CreateConverter(Type typeToConvert)
{
return new NumericJsonConverter<T>(_minValue, _maxValue, MinValueExclusive, MaxValueExclusive);
}
}
public class NumericJsonConverter<T> : JsonConverter<T> where T : struct, INumber<T>
{
string _rangeString;
public NumericJsonConverter(T? minValue = null, T? maxValue = null, bool? minValueExclusive = false, bool? maxValueExclusive = false, JsonSerializerOptions? options = null)
{
MinValue = minValue;
MaxValue = maxValue;
MinValueExclusive = minValueExclusive.HasValue ? minValueExclusive.Value : false;
MaxValueExclusive = maxValueExclusive.HasValue ? maxValueExclusive.Value : false;
_rangeString = $"{(MinValue.HasValue ? (MinValueExclusive ? $"({MinValue}" : $"[{MinValue}") : $"[{typeof(T).Name}.Min")}, {(MaxValue.HasValue ? (MaxValueExclusive ? $"{MaxValue})" : $"{MaxValue}]") : $"{typeof(T).Name}.Max]")}";
if ( options != null)
{
InnerConverter = options.GetConverter(typeof(T)) as JsonConverter<T>;
}
}
protected T? MinValue { get; }
protected bool MinValueExclusive { get; }
protected T? MaxValue { get; }
protected bool MaxValueExclusive { get; }
private JsonConverter<T>? InnerConverter { get; set; }
private JsonConverter<T> GetInnerConverter(JsonSerializerOptions options)
{
if (InnerConverter == null)
{
InnerConverter = (JsonConverter<T>)options.GetConverter(typeof(T));
}
return InnerConverter;
}
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var inner = GetInnerConverter(options);
T candidate = inner.Read(ref reader, typeToConvert, options);
ValidateRange(candidate);
return candidate;
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
ValidateRange(value);
GetInnerConverter(options).Write(writer, value, options);
}
protected virtual void ValidateRange(T value)
{
if ((MinValue.HasValue && (value < MinValue.Value || (value == MinValue.Value && MinValueExclusive)))
|| (MaxValue.HasValue && (value > MaxValue.Value || (value == MaxValue.Value && MaxValueExclusive))))
throw new JsonException($"{value} is outside the allowed range of {_rangeString}");
}
}
}`;
}
function getStringConstraintConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Provides constraints for a string values property
/// </summary>
public class StringConstraint : JsonConverterAttribute
{
int? _minLength = null, _maxLength = null;
public StringConstraint()
{
}
/// <summary>
/// The minimum length of the string
/// </summary>
public int MinLength { get { return _minLength.HasValue ? _minLength.Value : 0; } set { _minLength = value; } }
/// <summary>
/// The maximum length of the string
/// </summary>
public int MaxLength { get { return _maxLength.HasValue ? _maxLength.Value : 0; } set { _maxLength = value; } }
/// <summary>
/// The pattern that the string must match
/// </summary>
public string? Pattern { get; set; }
public override JsonConverter? CreateConverter(Type typeToConvert)
{
return new StringJsonConverter(_minLength, _maxLength, Pattern);
}
}
public class StringJsonConverter : JsonConverter<string>
{
public StringJsonConverter(int? minLength, int? maxLength, string? pattern, JsonSerializerOptions? options = null)
{
MinLength = minLength;
MaxLength = maxLength;
Pattern = pattern;
if (options != null)
{
InnerConverter = options.GetConverter(typeof(string)) as JsonConverter<string>;
}
}
protected int? MinLength { get; }
protected int? MaxLength { get; }
protected string? Pattern { get; }
private JsonConverter<string>? InnerConverter { get; set; }
private JsonConverter<string> GetInnerConverter(JsonSerializerOptions options)
{
if (InnerConverter == null)
{
InnerConverter = (JsonConverter<string>)options.GetConverter(typeof(string));
}
return InnerConverter;
}
public override bool CanConvert(Type typeToConvert)
{
return base.CanConvert(typeToConvert);
}
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var innerConverter = GetInnerConverter(options);
string? candidate = innerConverter.Read(ref reader, typeToConvert, options);
if (MinLength.HasValue && (candidate == null || candidate.Length < MinLength.Value))
{
throw new JsonException($"String length less than minimum length {MinLength.Value}");
}
if (candidate != null)
{
if (MaxLength.HasValue && candidate.Length > MaxLength.Value)
{
throw new JsonException($"String length greater than maximum length {MaxLength.Value}");
}
if (Pattern != null && !System.Text.RegularExpressions.Regex.IsMatch(candidate, Pattern))
{
throw new JsonException($"String does not match pattern {Pattern}");
}
}
return candidate;
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
if (MinLength.HasValue && (value == null || value.Length < MinLength.Value))
{
throw new JsonException($"String length less than minimum length {MinLength.Value}");
}
if (value != null)
{
if (MaxLength.HasValue && value.Length > MaxLength.Value)
{
throw new JsonException($"String length greater than maximum length {MaxLength.Value}");
}
if (Pattern != null && !System.Text.RegularExpressions.Regex.IsMatch(value, Pattern))
{
throw new JsonException($"String does not match pattern {Pattern}");
}
GetInnerConverter(options).Write(writer, value, options);
}
}
}
}`;
}
function getArrayConstraintConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Constrains the number of elements in an array
/// </summary>
/// <typeparam name="T">The element type of the array</typeparam>
public class ArrayConstraintAttribute<T> : JsonConverterAttribute
{
int? _minItems = null, _maxItems = null;
/// <summary>
/// The smallest number of allowed items
/// </summary>
public int MinItems { get { return _minItems.HasValue ? _minItems.Value : 0; } set { _minItems = value; } }
/// <summary>
/// The largest number of allowed items
/// </summary>
public int MaxItems { get { return _maxItems.HasValue ? _maxItems.Value : 0; } set { _maxItems = value; } }
public ArrayConstraintAttribute()
{
}
public override JsonConverter? CreateConverter(Type typeToConvert)
{
if (typeof(ISet<T>).IsAssignableFrom(typeToConvert))
{
return new ConstrainedSetConverter<T>(_minItems, _maxItems);
}
else if (typeToConvert.IsArray && typeToConvert.GetElementType() == typeof(T))
{
return new ConstrainedStandardArrayConverter<T>(_minItems, _maxItems);
}
else
{
return new ConstrainedEnumerableConverter<T>(_minItems, _maxItems);
}
}
}
public abstract class ConstrainedCollectionConverter<T, TCollection> : JsonConverter<TCollection>
{
protected ConstrainedCollectionConverter(int? min, int? max)
{
_minItems = min;
_maxItems = max;
}
protected int? _minItems, _maxItems;
public JsonConverter<T>? InnerConverter { get; set; }
public virtual Func<ConstrainedCollectionConverter<T, TCollection>, JsonSerializerOptions, JsonConverter<T>> InnerConverterFactory { get; set; } = ConverterHelpers.GetStandardInnerConverter<T, TCollection>;
protected bool ValidateMin(int count)
{
return !_minItems.HasValue || count >= _minItems.Value;
}
protected bool ValidateMax(int count)
{
return !_maxItems.HasValue || count <= _maxItems.Value;
}
protected void ValidateRange(int count)
{
if (!ValidateMax(count) || !ValidateMin(count))
{
throw new JsonException($"Number of array elements not in range [{(_minItems.HasValue ? _minItems.Value : 0)}, {(_maxItems.HasValue ? _maxItems.Value : Array.MaxLength)}]");
}
}
public override TCollection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var _innerConverter = InnerConverterFactory(this, options);
if (reader.TokenType != JsonTokenType.StartArray) { throw new JsonException("Expected start of array"); }
var list = new List<T>();
int count = 0;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray) { ValidateRange(count); break; }
if (!ValidateMax(count)) { ValidateRange(count); break; }
T value = _innerConverter.Read(ref reader, typeof(T), options)!;
list.Add(value);
count++;
}
return ConvertToCollection(list);
}
public override void Write(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options)
{
var _innerConverter = InnerConverterFactory(this, options);
writer.WriteStartArray();
foreach (var item in GetEnumerable(value))
_innerConverter.Write(writer, item, options);
writer.WriteEndArray();
}
protected abstract TCollection ConvertToCollection(List<T> list);
protected abstract IEnumerable<T> GetEnumerable(TCollection collection);
}
public class ConstrainedEnumerableConverter<T> : ConstrainedCollectionConverter<T, IEnumerable<T>>
{
public ConstrainedEnumerableConverter(int? min, int? max) : base(min, max) { }
protected override IEnumerable<T> ConvertToCollection(List<T> list) => list;
protected override IEnumerable<T> GetEnumerable(IEnumerable<T> collection) => collection;
}
public class ConstrainedSetConverter<T> : ConstrainedCollectionConverter<T, ISet<T>>
{
public ConstrainedSetConverter(int? min, int? max) : base(min, max) { }
protected override ISet<T> ConvertToCollection(List<T> list) => new HashSet<T>(list);
protected override IEnumerable<T> GetEnumerable(ISet<T> collection) => collection;
}
public class ConstrainedStandardArrayConverter<T> : ConstrainedCollectionConverter<T, T[]>
{
public ConstrainedStandardArrayConverter(int? min, int? max) : base(min, max) { }
protected override T[] ConvertToCollection(List<T> list) => list.ToArray();
protected override IEnumerable<T> GetEnumerable(T[] collection) => collection;
}
internal static class ConverterHelpers
{
internal static JsonConverter<T> GetStandardInnerConverter<T, TCollection>(this ConstrainedCollectionConverter<T, TCollection> converter, JsonSerializerOptions options)
{
if (converter.InnerConverter == null)
{
converter.InnerConverter = (JsonConverter<T>)options.GetConverter(typeof(T));
}
return converter.InnerConverter;
}
}
}`;
}
function getNumericArrayConstraintConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Numerics;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Constrains an array and the item types within it
/// </summary>
/// <typeparam name="T">The item type</typeparam>
public class NumericArrayConstraintAttribute<T> : ArrayConstraintAttribute<T> where T: struct, INumber<T>
{
T? _minValue = null, _maxValue = null;
public NumericArrayConstraintAttribute() : base()
{
}
public T MinValue { get { return _minValue.HasValue ? _minValue.Value : default(T); } set { _minValue = value; } }
public T MaxValue { get { return _maxValue.HasValue ? _maxValue.Value : default(T); } set { _maxValue = value; } }
bool MinValueExclusive { get; set; }
bool MaxValueExclusive { get; set; }
public override JsonConverter? CreateConverter(Type typeToConvert)
{
var result = base.CreateConverter(typeToConvert);
var resultSet = result as ConstrainedSetConverter<T>;
if (resultSet != null) {
resultSet.InnerConverterFactory = (c, o) => new NumericJsonConverter<T>(MinValue, MaxValue, MinValueExclusive, MaxValueExclusive, o);
return resultSet;
}
var resultEnumerable = result as ConstrainedEnumerableConverter<T>;
if (resultEnumerable != null) {
resultEnumerable.InnerConverterFactory = (c, o) => new NumericJsonConverter<T>(MinValue, MaxValue, MinValueExclusive, MaxValueExclusive, o);
return resultEnumerable;
}
var resultStandardArray = result as ConstrainedStandardArrayConverter<T>;
if (resultStandardArray != null) {
resultStandardArray.InnerConverterFactory = (c, o) => new NumericJsonConverter<T>(MinValue, MaxValue, MinValueExclusive, MaxValueExclusive, o);
return resultStandardArray;
}
throw new InvalidOperationException($"Cannot create converter for {typeToConvert} with {this}");
}
}
}`;
}
function getStringArrayConstraintConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Constrains an array of strings
/// </summary>
public class StringArrayConstraintAttribute : ArrayConstraintAttribute<string>
{
int? _minItemLength = null, _maxItemLength = null;
public StringArrayConstraintAttribute() : base()
{
}
public int MinItemLength { get { return _minItemLength.HasValue ? _minItemLength.Value : 0; } set { _minItemLength = value; } }
public int MaxItemLength { get { return _maxItemLength.HasValue ? _maxItemLength.Value : 0; } set { _maxItemLength = value; } }
public string? Pattern { get; set; }
override public JsonConverter? CreateConverter(Type typeToConvert)
{
var result = base.CreateConverter(typeToConvert);
var resultSet = result as ConstrainedSetConverter<string>;
if (resultSet != null) {
resultSet.InnerConverterFactory = (c, o) => new StringJsonConverter(MinItemLength, MaxItemLength, Pattern, o);
return resultSet;
}
var resultEnumerable = result as ConstrainedEnumerableConverter<string>;
if (resultEnumerable != null) {
resultEnumerable.InnerConverterFactory = (c, o) => new StringJsonConverter(MinItemLength, MaxItemLength, Pattern, o);
return resultEnumerable;
}
var resultStandardArray = result as ConstrainedStandardArrayConverter<string>;
if (resultStandardArray != null) {
resultStandardArray.InnerConverterFactory = (c, o) => new StringJsonConverter(MinItemLength, MaxItemLength, Pattern, o);
return resultStandardArray;
}
throw new InvalidOperationException($"Cannot create converter for {typeToConvert} with {this}");
}
}
}`;
}
function getTimeSpanDurationConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Xml;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Converts between Json duration and .Net TimeSpan
/// </summary>
public class TimeSpanDurationConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (typeToConvert != typeof(TimeSpan))
throw new ArgumentException($"Cannot apply converter {this.GetType().FullName} to type {typeToConvert.FullName}");
var value = reader.GetString();
if (string.IsNullOrWhiteSpace(value)) return TimeSpan.MinValue;
return XmlConvert.ToTimeSpan(value);
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(XmlConvert.ToString(value));
}
}
}
`;
}
function getBase64UrlJsonConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// System.Text.Json converter for the properties using Base64Url encoding
/// </summary>
public class Base64UrlJsonConverter : JsonConverter<byte[]>
{
/// <summary>
/// Adds padding to the input
/// </summary>
/// <param name="input"> the input string </param>
/// <returns> the padded string </returns>
private static string Pad(string input)
{
var count = 3 - ((input.Length + 3) % 4);
if (count == 0)
{
return input;
}
return $"{input}{new string('=', count)}";
}
public override byte[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (typeToConvert != typeof(byte[])) throw new ArgumentException($"Cannot apply converter {this.GetType().FullName} to type {typeToConvert.FullName}");
var value = reader.GetString();
if (string.IsNullOrWhiteSpace(value)) return null;
return Convert.FromBase64String(Pad(value.Replace('-', '+').Replace('_', '/')));
}
public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
{
writer.WriteStringValue(Convert.ToBase64String(value).TrimEnd('=').Replace('+', '-').Replace('/', '_'));
}
}
}
`;
}
function getUnixEpochDateTimeConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Converts between an integer timestamp and a .Net DateTime
/// </summary>
public sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new DateTime(1970, 1, 1, 0, 0, 0);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var formatted = reader.GetInt64()!;
return s_epoch.AddMilliseconds(formatted);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
writer.WriteNumberValue(unixTime);
}
}
}
`;
}
function getUnixEpochDateTimeOffsetConverter() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers.JsonConverters
{
/// <summary>
/// Converts between a Unix TimeStamp and a .Net DateTimeOffset
/// </summary>
public sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var formatted = reader.GetInt64()!;
return s_epoch.AddMilliseconds(formatted);
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
writer.WriteNumberValue(unixTime);
}
}
}
`;
}
function getJsonProviderInterface() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers
{
/// <summary>
/// Interface for Json serialization, suitable for providing a service in ASP.Net dependency injection
/// </summary>
public interface IJsonSerializationProvider
{
/// <summary>
/// Serialize an object to a JSON string
/// </summary>
/// <typeparam name="T">The type of the object</typeparam>
/// <param name="value">The object to serialize</param>
/// <returns>A string representing the serialized object</returns>
string Serialize<T>(T value);
/// <summary>
/// Create an object from a json string
/// </summary>
/// <typeparam name="T">The type of the object represented in the string</typeparam>
/// <param name="value">The strign to deserialize</param>
/// <returns>The deserialized object, or null</returns>
T? Deserialize<T>(string value);
}
}
`;
}
function getJsonProvider() {
return `${GeneratedFileHeaderWithNullable}
using System.Text.Json;
using System.Text.Json.Serialization;
namespace TypeSpec.Helpers
{
/// <summary>
/// Standard implementation of IJsonSerializationProvider
/// </summary>
public class JsonSerializationProvider : IJsonSerializationProvider
{
/// <summary>
/// The options to use for serialization
/// </summary>
public virtual JsonSerializerOptions Options { get; } = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
/// <summary>
/// Create an object from a json string
/// </summary>
/// <typeparam name="T">The type of the object represented in the string</typeparam>
/// <param name="value">The strign to deserialize</param>
/// <returns>The deserialized object, or null</returns>
public virtual T? Deserialize<T>(string value)
{
return JsonSerializer.Deserialize<T>(value, Options);
}
/// <summary>
/// Serialize an object to a JSON string
/// </summary>
/// <typeparam name="T">The type of the object</typeparam>
/// <param name="value">The object to serialize</param>
/// <returns>A string representing the serialized object</returns>
public virtual string Serialize<T>(T value)
{
return JsonSerializer.Serialize(value, Options);
}
}
}
`;
}
function getHttpServiceException() {
return `${GeneratedFileHeaderWithNullable}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace TypeSpec.Helpers
{
/// <summary>
/// Represents an HTTP response exception with a status code and optional value.
/// </summary>
public class HttpServiceException : Exception
{
/// <summary>
/// Initializes a new instance of the HttpServiceException class.
/// </summary>
/// <param name="statusCode">The HTTP status code.</param>
/// <param name="value">The optional value to include in the response.</param>
public HttpServiceException(int statusCode, object? value = null, Dictionary<string, string>? headers = null) =>
(StatusCode, Value, Headers) = (statusCode, value, headers ?? new Dictionary<string, string>());
public int StatusCode { get; }
public object? Value { get; }
public Dictionary<string, string> Headers { get; }
}
/// <summary>
/// An action filter that handles HttpServiceException and converts it to an HTTP response.
/// </summary>
public class HttpServiceExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order => int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context) { }
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is HttpServiceException httpServiceException)
{
foreach (var header in httpServiceException.Headers)
{
context.HttpContext.Response.Headers.Append(header.Key, header.Value.ToString());
}
context.Result = new ObjectResult(httpServiceException.Value)
{
StatusCode = httpServiceException.StatusCode
};
context.ExceptionHandled = true;
}
}
}
}
`;
}
//# sourceMappingURL=boilerplate.js.map