RDG by Microsoft
Nuget / site data
Details
Info
Name: RDG
The HttpClient factory is a pattern for configuring and retrieving named HttpClients in a composable way. The HttpClient factory provides extensibility to plug in DelegatingHandlers that address cross-cutting concerns such as service location, load balancing, and reliability. The default HttpClient factory provides built-in diagnostics and logging and manages the lifetimes of connections in a performant way. Commonly used types: System.Net.Http.IHttpClientFactory
Author: Microsoft
NuGet: https://www.nuget.org/packages/Microsoft.Extensions.Http
You can find more details at https://learn.microsoft.com/en-us/aspnet/core/fundamentals/aot/request-delegate-generator/rdg?view=aspnetcore-8.0
Source : https://github.com/dotnet/aspnetcore
Original Readme
ASP.NET Core
ASP.NET Core is an open-source and cross-platform framework for building modern cloud-based internet-connected applications, such as web apps, IoT apps, and mobile backends. ASP.NET Core apps run on .NET, a free, cross-platform, and open-source application runtime. It was architected to provide an optimized development framework for apps that are deployed to the cloud or run on-premises. It consists of modular components with minimal overhead, so you retain flexibility while constructing your solutions. You can develop and run your ASP.NET Core apps cross-platform on Windows, Mac, and Linux. Learn more about ASP.NET Core.
Get started
Follow the Getting Started instructions.
Also check out the .NET Homepage for released versions of .NET, getting started guides, and learning resources.
See the Triage Process document for more information on how we handle incoming issues.
How to engage, contribute, and give feedback
Some of the best ways to contribute are to try things out, file issues, join in design conversations, and make pull-requests.
- Download our latest daily builds
- Follow along with the development of ASP.NET Core:
- Community Standup: The community standup is held every week and streamed live on YouTube. You can view past standups in the linked playlist.
- Roadmap: The schedule and milestone themes for ASP.NET Core.
- Build ASP.NET Core source code
- Check out the contributing page to see the best places to log issues and start discussions.
Reporting security issues and bugs
Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) secure@microsoft.com. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.
Related projects
These are some other repos for related projects:
- Documentation - documentation sources for https://learn.microsoft.com/aspnet/core/
- Entity Framework Core - data access technology
- Runtime - cross-platform runtime for cloud, mobile, desktop, and IoT apps
- Razor - the Razor compiler and tooling for working with Razor syntax (.cshtml, .razor)
Code of conduct
See CODE-OF-CONDUCT
Nightly builds
This table includes links to download the latest builds of the ASP.NET Core Shared Framework. Also included are links to download the Windows Hosting Bundle, which includes the ASP.NET Core Shared Framework, the .NET Runtime Shared Framework, and the IIS plugin (ASP.NET Core Module). You can download the latest .NET Runtime builds here, and the latest .NET SDK builds here. If you're unsure what you need, then install the SDK; it has everything except the IIS plugin.
Platform | Shared Framework (Installer) | Shared Framework (Binaries) | Hosting Bundle (Installer) |
---|---|---|---|
Windows x64 | Installer | Binaries | Installer |
Windows x86 | Installer | Binaries | Installer |
Windows arm64 | Installer | Binaries | Installer |
macOS x64 | N/A | Binaries | N/A |
macOS arm64 | N/A | Binaries | N/A |
Linux x64 | Deb Installer - RPM Installer | Binaries | N/A |
Linux arm | N/A | Binaries | N/A |
Linux arm64 | RPM Installer | Binaries | N/A |
Linux-musl-x64 | N/A | Binaries | N/A |
Linux-musl-arm | N/A | Binaries | N/A |
Linux-musl-arm64 | N/A | Binaries | N/A |
About
Generating replacing for minimal API Map
How to use
Example ( source csproj, source files )
- CSharp Project
- Program.cs
This is the CSharp Project that references RDG
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<!--
<PackageReference Include="Microsoft.Extensions.Http"></PackageReference>
-->
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<PropertyGroup>
<EnableRequestDelegateGenerator>true</EnableRequestDelegateGenerator>
</PropertyGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
This is the use of RDG in Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
app.Run();
internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- GeneratedRouteBuilderExtensions.g.cs
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
#nullable enable
namespace System.Runtime.CompilerServices
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.2.0")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
file sealed class InterceptsLocationAttribute : Attribute
{
public InterceptsLocationAttribute(string filePath, int line, int column)
{
}
}
}
namespace Microsoft.AspNetCore.Http.Generated
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using System.Threading.Tasks;
using System.IO;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Microsoft.Extensions.Options;
using MetadataPopulator = System.Func<System.Reflection.MethodInfo, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions?, Microsoft.AspNetCore.Http.RequestDelegateMetadataResult>;
using RequestDelegateFactoryFunc = System.Func<System.Delegate, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions, Microsoft.AspNetCore.Http.RequestDelegateMetadataResult?, Microsoft.AspNetCore.Http.RequestDelegateResult>;
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.2.0")]
file static class GeneratedRouteBuilderExtensionsCore
{
private static readonly JsonOptions FallbackJsonOptions = new();
private static readonly string[] GetVerb = new[] { global::Microsoft.AspNetCore.Http.HttpMethods.Get };
[InterceptsLocation(@"D:\gth\RSCG_Examples\v2\rscg_examples\RDG\src\RDGDemoWebApi\Program.cs", 22, 5)]
internal static RouteHandlerBuilder MapGet0(
this IEndpointRouteBuilder endpoints,
[StringSyntax("Route")] string pattern,
Delegate handler)
{
MetadataPopulator populateMetadata = (methodInfo, options) =>
{
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
options.EndpointBuilder.Metadata.Add(new System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.2.0"));
options.EndpointBuilder.Metadata.Add(new ProducesResponseTypeMetadata(statusCode: StatusCodes.Status200OK, type: typeof(global::WeatherForecast[]), contentTypes: GeneratedMetadataConstants.JsonContentType));
return new RequestDelegateMetadataResult { EndpointMetadata = options.EndpointBuilder.Metadata.AsReadOnly() };
};
RequestDelegateFactoryFunc createRequestDelegate = (del, options, inferredMetadataResult) =>
{
Debug.Assert(options != null, "RequestDelegateFactoryOptions not found.");
Debug.Assert(options.EndpointBuilder != null, "EndpointBuilder not found.");
Debug.Assert(options.EndpointBuilder.ApplicationServices != null, "ApplicationServices not found.");
Debug.Assert(options.EndpointBuilder.FilterFactories != null, "FilterFactories not found.");
var handler = Cast(del, global::WeatherForecast[] () => throw null!);
EndpointFilterDelegate? filteredInvocation = null;
var serviceProvider = options.ServiceProvider ?? options.EndpointBuilder.ApplicationServices;
var jsonOptions = serviceProvider?.GetService<IOptions<JsonOptions>>()?.Value ?? FallbackJsonOptions;
var jsonSerializerOptions = jsonOptions.SerializerOptions;
jsonSerializerOptions.MakeReadOnly();
var objectJsonTypeInfo = (JsonTypeInfo<object?>)jsonSerializerOptions.GetTypeInfo(typeof(object));
var responseJsonTypeInfo = (JsonTypeInfo<global::WeatherForecast[]?>)jsonSerializerOptions.GetTypeInfo(typeof(global::WeatherForecast[]));
if (options.EndpointBuilder.FilterFactories.Count > 0)
{
filteredInvocation = GeneratedRouteBuilderExtensionsCore.BuildFilterDelegate(ic =>
{
if (ic.HttpContext.Response.StatusCode == 400)
{
return ValueTask.FromResult<object?>(Results.Empty);
}
return ValueTask.FromResult<object?>(handler());
},
options.EndpointBuilder,
handler.Method);
}
Task RequestHandler(HttpContext httpContext)
{
var wasParamCheckFailure = false;
if (wasParamCheckFailure)
{
httpContext.Response.StatusCode = 400;
return Task.CompletedTask;
}
var result = handler();
return GeneratedRouteBuilderExtensionsCore.WriteJsonResponseAsync(httpContext.Response, result, responseJsonTypeInfo);
}
async Task RequestHandlerFiltered(HttpContext httpContext)
{
var wasParamCheckFailure = false;
if (wasParamCheckFailure)
{
httpContext.Response.StatusCode = 400;
}
var result = await filteredInvocation(EndpointFilterInvocationContext.Create(httpContext));
if (result is not null)
{
await GeneratedRouteBuilderExtensionsCore.ExecuteReturnAsync(result, httpContext, objectJsonTypeInfo);
}
}
RequestDelegate targetDelegate = filteredInvocation is null ? RequestHandler : RequestHandlerFiltered;
var metadata = inferredMetadataResult?.EndpointMetadata ?? ReadOnlyCollection<object>.Empty;
return new RequestDelegateResult(targetDelegate, metadata);
};
return MapCore(
endpoints,
pattern,
handler,
GetVerb,
populateMetadata,
createRequestDelegate);
}
internal static RouteHandlerBuilder MapCore(
this IEndpointRouteBuilder routes,
string pattern,
Delegate handler,
IEnumerable<string>? httpMethods,
MetadataPopulator populateMetadata,
RequestDelegateFactoryFunc createRequestDelegate)
{
return RouteHandlerServices.Map(routes, pattern, handler, httpMethods, populateMetadata, createRequestDelegate);
}
private static T Cast<T>(Delegate d, T _) where T : Delegate
{
return (T)d;
}
private static EndpointFilterDelegate BuildFilterDelegate(EndpointFilterDelegate filteredInvocation, EndpointBuilder builder, MethodInfo mi)
{
var routeHandlerFilters = builder.FilterFactories;
var context0 = new EndpointFilterFactoryContext
{
MethodInfo = mi,
ApplicationServices = builder.ApplicationServices,
};
var initialFilteredInvocation = filteredInvocation;
for (var i = routeHandlerFilters.Count - 1; i >= 0; i--)
{
var filterFactory = routeHandlerFilters[i];
filteredInvocation = filterFactory(context0, filteredInvocation);
}
return filteredInvocation;
}
private static Task ExecuteReturnAsync(object? obj, HttpContext httpContext, JsonTypeInfo<object?> jsonTypeInfo)
{
if (obj is IResult r)
{
return r.ExecuteAsync(httpContext);
}
else if (obj is string s)
{
return httpContext.Response.WriteAsync(s);
}
else
{
return WriteJsonResponseAsync(httpContext.Response, obj, jsonTypeInfo);
}
}
[UnconditionalSuppressMessage("Trimming", "IL2026:RequiresUnreferencedCode",
Justification = "The 'JsonSerializer.IsReflectionEnabledByDefault' feature switch, which is set to false by default for trimmed ASP.NET apps, ensures the JsonSerializer doesn't use Reflection.")]
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "See above.")]
private static Task WriteJsonResponseAsync<T>(HttpResponse response, T? value, JsonTypeInfo<T?> jsonTypeInfo)
{
var runtimeType = value?.GetType();
if (jsonTypeInfo.ShouldUseWith(runtimeType))
{
return HttpResponseJsonExtensions.WriteAsJsonAsync(response, value, jsonTypeInfo, default);
}
return response.WriteAsJsonAsync<object?>(value, jsonTypeInfo.Options);
}
private static bool HasKnownPolymorphism(this JsonTypeInfo jsonTypeInfo)
=> jsonTypeInfo.Type.IsSealed || jsonTypeInfo.Type.IsValueType || jsonTypeInfo.PolymorphismOptions is not null;
private static bool ShouldUseWith(this JsonTypeInfo jsonTypeInfo, [NotNullWhen(false)] Type? runtimeType)
=> runtimeType is null || jsonTypeInfo.Type == runtimeType || jsonTypeInfo.HasKnownPolymorphism();
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.2.0")]
file static class GeneratedMetadataConstants
{
public static readonly string[] JsonContentType = new [] { "application/json" };
public static readonly string[] PlaintextContentType = new [] { "text/plain" };
public static readonly string[] FormFileContentType = new[] { "multipart/form-data" };
public static readonly string[] FormContentType = new[] { "multipart/form-data", "application/x-www-form-urlencoded" };
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.AspNetCore.Http.RequestDelegateGenerator, Version=8.0.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60", "8.0.2.0")]
file sealed class LogOrThrowExceptionHelper
{
private readonly ILogger? _rdgLogger;
private readonly bool _shouldThrow;
public LogOrThrowExceptionHelper(IServiceProvider? serviceProvider, RequestDelegateFactoryOptions? options)
{
var loggerFactory = serviceProvider?.GetRequiredService<ILoggerFactory>();
_rdgLogger = loggerFactory?.CreateLogger("Microsoft.AspNetCore.Http.RequestDelegateGenerator.RequestDelegateGenerator");
_shouldThrow = options?.ThrowOnBadRequest ?? false;
}
public void RequestBodyIOException(IOException exception)
{
if (_rdgLogger != null)
{
_requestBodyIOException(_rdgLogger, exception);
}
}
private static readonly Action<ILogger, Exception?> _requestBodyIOException =
LoggerMessage.Define(LogLevel.Debug, new EventId(1, "RequestBodyIOException"), "Reading the request body failed with an IOException.");
public void InvalidJsonRequestBody(string parameterTypeName, string parameterName, Exception exception)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Failed to read parameter \"{0} {1}\" from the request body as JSON.", parameterTypeName, parameterName);
throw new BadHttpRequestException(message, exception);
}
if (_rdgLogger != null)
{
_invalidJsonRequestBody(_rdgLogger, parameterTypeName, parameterName, exception);
}
}
private static readonly Action<ILogger, string, string, Exception?> _invalidJsonRequestBody =
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(2, "InvalidJsonRequestBody"), "Failed to read parameter \"{ParameterType} {ParameterName}\" from the request body as JSON.");
public void ParameterBindingFailed(string parameterTypeName, string parameterName, string sourceValue)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Failed to bind parameter \"{0} {1}\" from \"{2}\".", parameterTypeName, parameterName, sourceValue);
throw new BadHttpRequestException(message);
}
if (_rdgLogger != null)
{
_parameterBindingFailed(_rdgLogger, parameterTypeName, parameterName, sourceValue, null);
}
}
private static readonly Action<ILogger, string, string, string, Exception?> _parameterBindingFailed =
LoggerMessage.Define<string, string, string>(LogLevel.Debug, new EventId(3, "ParameterBindingFailed"), "Failed to bind parameter \"{ParameterType} {ParameterName}\" from \"{SourceValue}\".");
public void RequiredParameterNotProvided(string parameterTypeName, string parameterName, string source)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Required parameter \"{0} {1}\" was not provided from {2}.", parameterTypeName, parameterName, source);
throw new BadHttpRequestException(message);
}
if (_rdgLogger != null)
{
_requiredParameterNotProvided(_rdgLogger, parameterTypeName, parameterName, source, null);
}
}
private static readonly Action<ILogger, string, string, string, Exception?> _requiredParameterNotProvided =
LoggerMessage.Define<string, string, string>(LogLevel.Debug, new EventId(4, "RequiredParameterNotProvided"), "Required parameter \"{ParameterType} {ParameterName}\" was not provided from {Source}.");
public void ImplicitBodyNotProvided(string parameterName)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Implicit body inferred for parameter \"{0}\" but no body was provided. Did you mean to use a Service instead?", parameterName);
throw new BadHttpRequestException(message);
}
if (_rdgLogger != null)
{
_implicitBodyNotProvided(_rdgLogger, parameterName, null);
}
}
private static readonly Action<ILogger, string, Exception?> _implicitBodyNotProvided =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(5, "ImplicitBodyNotProvided"), "Implicit body inferred for parameter \"{ParameterName}\" but no body was provided. Did you mean to use a Service instead?");
public void UnexpectedJsonContentType(string? contentType)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Expected a supported JSON media type but got \"{0}\".", contentType);
throw new BadHttpRequestException(message, StatusCodes.Status415UnsupportedMediaType);
}
if (_rdgLogger != null)
{
_unexpectedJsonContentType(_rdgLogger, contentType ?? "(none)", null);
}
}
private static readonly Action<ILogger, string, Exception?> _unexpectedJsonContentType =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(6, "UnexpectedContentType"), "Expected a supported JSON media type but got \"{ContentType}\".");
public void UnexpectedNonFormContentType(string? contentType)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Expected a supported form media type but got \"{0}\".", contentType);
throw new BadHttpRequestException(message, StatusCodes.Status415UnsupportedMediaType);
}
if (_rdgLogger != null)
{
_unexpectedNonFormContentType(_rdgLogger, contentType ?? "(none)", null);
}
}
private static readonly Action<ILogger, string, Exception?> _unexpectedNonFormContentType =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(7, "UnexpectedNonFormContentType"), "Expected a supported form media type but got \"{ContentType}\".");
public void InvalidFormRequestBody(string parameterTypeName, string parameterName, Exception exception)
{
if (_shouldThrow)
{
var message = string.Format(CultureInfo.InvariantCulture, "Failed to read parameter \"{0} {1}\" from the request body as form.", parameterTypeName, parameterName);
throw new BadHttpRequestException(message, exception);
}
if (_rdgLogger != null)
{
_invalidFormRequestBody(_rdgLogger, parameterTypeName, parameterName, exception);
}
}
private static readonly Action<ILogger, string, string, Exception?> _invalidFormRequestBody =
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(8, "InvalidFormRequestBody"), "Failed to read parameter \"{ParameterType} {ParameterName}\" from the request body as form.");
}
}
Usefull
Download Example (.NET C# )
Share RDG
https://ignatandrei.github.io/RSCG_Examples/v2/docs/RDG