diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index d93754c..20d7651 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -15,9 +15,6 @@ jobs: contents: read security-events: write - strategy: - fail-fast: false - steps: - name: Checkout repository uses: actions/checkout@v4 @@ -27,10 +24,10 @@ jobs: with: languages: 'csharp' - - name: Setup .NET 9.0 + - name: Setup .NET 10.0 uses: actions/setup-dotnet@v4 with: - dotnet-version: 9.x + dotnet-version: 10.x - name: Restore dependencies run: dotnet restore @@ -39,7 +36,7 @@ jobs: run: dotnet build --configuration Release --no-restore - name: Test - run: dotnet test ./tests/GeneratedEndpoints.Tests/GeneratedEndpoints.Tests.csproj --configuration Release --no-build --verbosity normal --framework net9.0 + run: dotnet test ./tests/GeneratedEndpoints.Tests/GeneratedEndpoints.Tests.csproj --configuration Release --no-build --verbosity normal --framework net10.0 - name: Perform CodeQL analysis uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 03b9cc0..462d270 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,17 +13,14 @@ jobs: contents: read security-events: write - strategy: - fail-fast: false - steps: - name: Checkout repository uses: actions/checkout@v4 - - name: Setup .NET 9.0 + - name: Setup .NET 10.0 uses: actions/setup-dotnet@v4 with: - dotnet-version: 9.x + dotnet-version: 10.x - name: Restore dependencies run: dotnet restore diff --git a/GeneratedEndpoints.sln b/GeneratedEndpoints.sln index ea88e6a..88e9eaf 100644 --- a/GeneratedEndpoints.sln +++ b/GeneratedEndpoints.sln @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneratedEndpoints.Tests", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneratedEndpoints", "src\GeneratedEndpoints\GeneratedEndpoints.csproj", "{2F54865E-0F46-416B-A18D-C6C2ACF912B2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneratedEndpoints.Tests.Lab", "tests\GeneratedEndpoints.Tests.Lab\GeneratedEndpoints.Tests.Lab.csproj", "{2E39D0D0-B4C7-4A28-94E0-067E3B0902E2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,8 +22,13 @@ Global {2F54865E-0F46-416B-A18D-C6C2ACF912B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F54865E-0F46-416B-A18D-C6C2ACF912B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F54865E-0F46-416B-A18D-C6C2ACF912B2}.Release|Any CPU.Build.0 = Release|Any CPU + {2E39D0D0-B4C7-4A28-94E0-067E3B0902E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E39D0D0-B4C7-4A28-94E0-067E3B0902E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E39D0D0-B4C7-4A28-94E0-067E3B0902E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E39D0D0-B4C7-4A28-94E0-067E3B0902E2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {01E8E43A-EA5C-4F28-BAAE-A3EB7861B57E} = {F1E3D1D7-B9E4-4EFF-8FD5-2A735A4695B4} + {2E39D0D0-B4C7-4A28-94E0-067E3B0902E2} = {F1E3D1D7-B9E4-4EFF-8FD5-2A735A4695B4} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index 0864b24..1f6aa08 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![Banner](https://raw.githubusercontent.com/jscarle/GeneratedEndpoints/develop/Banner.png)](https://github.com/jscarle/GeneratedEndpoints) -# GeneratedEndpoints - Attribute-driven, source-generated minimal API endpoints for feature-based development +# GeneratedEndpoints - Attribute-driven, source-generated Minimal API endpoints for feature-based development GeneratedEndpoints is a .NET source generator that automatically wires up Minimal API endpoints from attribute-annotated methods. This simplifies integration of HTTP handlers within Clean Architecture (CA) or Vertical Slice Architecture (VSA) @@ -10,149 +10,171 @@ by keeping endpoint definitions inside their features while generating the boile [![nuget](https://img.shields.io/nuget/v/GeneratedEndpoints)](https://www.nuget.org/packages/GeneratedEndpoints) [![downloads](https://img.shields.io/nuget/dt/GeneratedEndpoints)](https://www.nuget.org/packages/GeneratedEndpoints) -## Getting Started +## Setup -### Installation - -Add the package to the Minimal API project that will host your endpoints. You can install it with the .NET CLI: +Add the package to any ASP.NET Core project that hosts Minimal APIs: ```bash dotnet add package GeneratedEndpoints ``` -Once the package is referenced, the source generator will contribute its attributes and extension methods to the consuming project at build time. +The source generator emits two extension methods: + +```csharp +using Microsoft.AspNetCore.Generated.Routing; -### 1. Define a request handler +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddEndpointHandlers(); -Create a feature class that encapsulates the logic for a single endpoint and decorate its handler method with one of the generated HTTP verb attributes. The attributes live in the `Microsoft.AspNetCore.Generated.Attributes` namespace and map directly to Minimal API routing methods. +var app = builder.Build(); + +app.MapEndpointHandlers(); + +app.Run(); +``` -Handler classes can be expressed in whichever style best fits the feature: +- The `AddEndpointHandlers` method registers each endpoint class with injected services as a `Scoped` service. +- The `MapEndpointHandlers` method calls the generated `Map` method for each endpoint. -* **Instance classes** (non-static) allow constructor injection and can expose either instance or static handler methods. When an annotated method is not static the generator will call it on a resolved instance from dependency injection. -* **Static classes** make it easy to group stateless functionality. Every annotated method inside must also be static, mirroring standard C# rules. +## A simple endpoint -#### Instance handler example +An endpoint is wired using a class with a method marked by one of the `[Map*]` attributes. The source generator produces the handler delegate and automatically +calls the appropriate map method on the route builder. ```csharp using Microsoft.AspNetCore.Generated.Attributes; using Microsoft.AspNetCore.Http.HttpResults; -namespace Todos.Features; +namespace Contoso.Example.Endpoints; -public sealed class GetTodo +internal static class TimeEndpoints { - private readonly TodoDbContext _db; - - public GetTodo(TodoDbContext db) => _db = db; - - [MapGet("/todos/{id}", Summary = "Retrieve a todo", Description = "Returns the todo matching the provided identifier.")] - [Tags("Todos")] - [RequireAuthorization("Todos.Read")] - public async Task, NotFound>> HandleAsync(Guid id, CancellationToken cancellationToken) - { - var entity = await _db.Todos.FindAsync(new object?[] { id }, cancellationToken); - return entity is null ? TypedResults.NotFound() : TypedResults.Ok(entity); - } + [MapGet("/time")] + public static Ok GetCurrentTime() => TypedResults.Ok(DateTimeOffset.UtcNow.ToString("O")); } ``` -Key points: - -* Use `[MapGet]`, `[MapPost]`, `[MapPut]`, `[MapDelete]`, `[MapPatch]`, `[MapHead]`, `[MapOptions]`, `[MapTrace]`, or `[MapConnect]` to describe the HTTP verb and route pattern. -* Optional `Name`, `Summary`, and `Description` named parameters populate the generated `.WithName`, `.WithSummary`, and `.WithDescription` metadata calls. When omitted, the generator derives the endpoint name from the method name (stripping a trailing `Async`). -* Apply standard ASP.NET Core parameter binding attributes (`[FromRoute]`, `[FromQuery]`, `[FromBody]`, `[FromServices]`, `[AsParameters]`, etc.). The generator mirrors them onto the produced delegate so binding behaves exactly as declared. -* Annotate the **class**, an individual **method**, or both with `[Tags]`, `[RequireAuthorization]`, or `[DisableAntiforgery]`. Class-level metadata is merged onto every generated endpoint, while method-level attributes can refine or augment the settings for a specific handler. -* Non-static handler classes are automatically registered with dependency injection (as transient services). Their instance methods receive a scoped instance resolved from DI, while static methods continue to behave like any other static helper. - -#### Static handler example +## Expanding the endpoint -The same attribute-driven approach works for static handler types when no dependencies are needed: +You can add additional metadata to endpoints using attributes. ```csharp using Microsoft.AspNetCore.Generated.Attributes; using Microsoft.AspNetCore.Http.HttpResults; -namespace Todos.Features; +namespace Contoso.Example.Endpoints; -public static class ListTodos +[Tags("Users", "Lookup")] +internal static class UserEndpoints { - [MapGet("/todos")] - [Tags("Todos")] - public static Ok> Handle() - => TypedResults.Ok(TodoStore.All); + [Summary("Gets a user by ID.")] + [RequireAuthorization("Users.Read")] + [MapGet("/users/{id:int}")] + public static Results, NotFound> GetUser(int id) + { + if (id <= 0) + return TypedResults.NotFound(); + + return TypedResults.Ok(new UserDto(id, $"User {id}")); + } } + +internal sealed record UserDto(int Id, string DisplayName); ``` -### 2. Wire up the application +* `[Tags]` on the class assigns OpenAPI tags to every endpoint inside the type. +* `[Summary]` annotates the endpoint with OpenAI summary metadata. +* `[RequireAuthorization]` enforces authorization policies on the endpoint. -The generator emits extension methods in the `Microsoft.AspNetCore.Generated.Routing` namespace. Call them during startup to register handler types and map the generated endpoints. +## Static vs instantiable classes -```csharp -using Microsoft.AspNetCore.Generated.Routing; - -var builder = WebApplication.CreateBuilder(args); +To avoid clutering your endpoint method with service dependencies, you can specify them using a class constructor. This also allows you to reuse the same +service declaration across multiple endpoints. The source generator will generate the appropriate service injection code for each endpoint method. -// Registers non-static handler classes with the DI container. -builder.Services.AddEndpointHandlers(); +```csharp +using Microsoft.AspNetCore.Generated.Attributes; +using Microsoft.AspNetCore.Http.HttpResults; -var app = builder.Build(); +namespace Contoso.Example.Endpoints; -// Maps every method decorated with a Map* attribute. -app.MapEndpointHandlers(); +internal static class HealthEndpoints +{ + [MapGet("/health")] + public static Ok Check(IHostEnvironment env) => TypedResults.Ok("Healthy, {env.EnvironmentName}"); +} -app.Run(); +internal sealed class EnvironmentEndpoints(IHostEnvironment env) +{ + [MapGet("/env")] + public Ok GetEnvironmentName() => TypedResults.Ok(env.EnvironmentName); +} ``` -`AddEndpointHandlers` ensures any non-static handler types can be resolved from dependency injection, while `MapEndpointHandlers` generates Minimal API route mappings for every annotated method in the application. - -### 3. Compose additional endpoints +## Advanced configuration -Add as many handler classes as needed—each annotated method becomes an endpoint. You can mix synchronous and asynchronous methods, return `IResult` or typed `Results<>`, and combine static and instance handlers in the same project. Metadata from attributes composes naturally: class-level attributes are applied to every endpoint, while method-level attributes add to (or override, when relevant) the defaults. +Endpoint classes may include an optional `Configure` method to apply conventions after the handler is mapped. The source generator will look for the following +signature: ```csharp using Microsoft.AspNetCore.Generated.Attributes; using Microsoft.AspNetCore.Http.HttpResults; -namespace Todos.Features; +namespace Contoso.Example.Endpoints; -[Tags("Todos")] -[RequireAuthorization("Todos.Read")] -public sealed class TodoEndpoints +internal static class HealthEndpoints { - private readonly TodoDbContext _db; - - public TodoEndpoints(TodoDbContext db) => _db = db; - - [MapGet("/todos/{id}", Summary = "Retrieve a todo")] - public async Task, NotFound>> GetAsync(Guid id, CancellationToken cancellationToken) - { - var entity = await _db.Todos.FindAsync(new object?[] { id }, cancellationToken); - return entity is null ? TypedResults.NotFound() : TypedResults.Ok(entity); - } + [MapGet("/health")] + public static Ok Check() => TypedResults.Ok("Healthy"); - [MapDelete("/todos/{id}")] - [RequireAuthorization("Todos.Write")] - public static async Task> DeleteAsync( - Guid id, - [FromServices] TodoDbContext db, - CancellationToken cancellationToken) + public static void Configure(TBuilder builder) + where TBuilder : IEndpointConventionBuilder { - var entity = await db.Todos.FindAsync(new object?[] { id }, cancellationToken); - if (entity is null) - return TypedResults.NotFound(); - - db.Todos.Remove(entity); - await db.SaveChangesAsync(cancellationToken); - return TypedResults.NoContent(); + builder.WithRequestTimeout(TimeSpan.FromSeconds(5)); } } ``` -In this example: - -* The class-level `[Tags]` and `[RequireAuthorization]` attributes apply to both endpoints, while the method-level `[RequireAuthorization]` adds an additional policy for the delete handler. -* `GetAsync` is an instance method that uses the injected `TodoDbContext` field, illustrating how non-static handlers can maintain state. -* `DeleteAsync` is a static method in the same class and explicitly receives its dependencies via `[FromServices]`, demonstrating that you can mix static and instance methods in a single handler type. - -Every new handler will automatically appear in the generated routing table the next time the project builds—no manual `MapGet`, `MapPost`, or registration code is required. - +Inside `Configure` you can continue to chain configurations that are not already exposed as attributes by the source generator. The `Configure` method is +applied to all endpoints within the class. + +## Attribute Reference + +| Definition | Usage | Description | +| --- | --- | --- | +| `[Accepts(string contentType = "application/json", params string[] additionalContentTypes, RequestType = null, IsOptional = false)]` | Method | Declares the accepted request body CLR type, optional status, and list of content types for the handler. | +| `[Accepts(string contentType = "application/json", params string[] additionalContentTypes, IsOptional = false)]` | Method | Generic shortcut for specifying the request type and accepted content types for the handler. | +| `[AllowAnonymous]` | Class or Method | Allows the annotated endpoint or class to bypass authorization requirements. | +| `[Description(string description)]` | Method | Sets the OpenAPI description metadata for the generated endpoint. | +| `[DisableAntiforgery]` | Class or Method | Disables antiforgery protection for the annotated endpoint(s). | +| `[DisableRequestTimeout]` | Class or Method | Disables request timeout enforcement for the annotated endpoint(s). | +| `[DisableValidation]` | Class or Method | Disables automatic request validation (when supported) for the annotated endpoint(s). | +| `[DisplayName(string displayName)]` | Method | Overrides the endpoint display name used in diagnostics and metadata. | +| `[EndpointFilter(Type filterType)]` | Class or Method | Adds the specified endpoint filter type to the handler pipeline. | +| `[EndpointFilter]` | Class or Method | Generic form for registering an endpoint filter type on the handler pipeline. | +| `[ExcludeFromDescription]` | Class or Method | Hides the endpoint or class from generated API descriptions (e.g., OpenAPI). | +| `[MapConnect(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP CONNECT endpoint using the supplied route pattern and optional name. | +| `[MapDelete(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP DELETE endpoint using the supplied route pattern and optional name. | +| `[MapFallback(string pattern = "", Name = null)]` | Method | Maps the method as the fallback endpoint invoked when no other route matches. | +| `[MapGroup(string pattern, Name = null)]` | Class | Assigns a route group pattern and optional endpoint group name to every handler in the class. | +| `[MapGet(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP GET endpoint using the supplied route pattern and optional name. | +| `[MapHead(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP HEAD endpoint using the supplied route pattern and optional name. | +| `[MapOptions(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP OPTIONS endpoint using the supplied route pattern and optional name. | +| `[MapPatch(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP PATCH endpoint using the supplied route pattern and optional name. | +| `[MapPost(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP POST endpoint using the supplied route pattern and optional name. | +| `[MapPut(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP PUT endpoint using the supplied route pattern and optional name. | +| `[MapQuery(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP QUERY endpoint using the supplied route pattern and optional name. | +| `[MapTrace(string pattern = "", Name = null)]` | Method | Marks the method as an HTTP TRACE endpoint using the supplied route pattern and optional name. | +| `[Order(int order)]` | Method | Controls the order in which endpoint conventions are applied to the handler. | +| `[ProducesProblem(int statusCode = StatusCodes.Status500InternalServerError, string? contentType = null, params string[] additionalContentTypes)]` | Method | Declares that the endpoint emits a problem details payload for the given status code and content types. | +| `[ProducesResponse(int statusCode = StatusCodes.Status200OK, string? contentType = null, params string[] additionalContentTypes, ResponseType = null)]` | Method | Declares response metadata for the handler, including status code, optional CLR type, and content types. | +| `[ProducesResponse(int statusCode = StatusCodes.Status200OK, string? contentType = null, params string[] additionalContentTypes)]` | Method | Generic shorthand for declaring the CLR response type along with status code and content types. | +| `[ProducesValidationProblem(int statusCode = StatusCodes.Status400BadRequest, string? contentType = null, params string[] additionalContentTypes)]` | Method | Declares that the endpoint returns validation problem details for the specified status code and content types. | +| `[RequestTimeout(string? policyName = null)]` | Class or Method | Applies the default or a named request-timeout policy to the handler(s). | +| `[RequireAuthorization(params string[] policies)]` | Class or Method | Enforces authorization on the handler(s), optionally scoping access to specific policies. | +| `[RequireCors(string? policyName = null)]` | Class or Method | Requires the default or a named CORS policy for the annotated handler(s). | +| `[RequireHost(params string[] hosts)]` | Class or Method | Restricts the handler(s) to the specified allowed hostnames. | +| `[RequireRateLimiting(string policyName)]` | Class or Method | Enforces the named rate-limiting policy on the annotated handler(s). | +| `[ShortCircuit]` | Class or Method | Marks the handler(s) to short-circuit the request pipeline when invoked. | +| `[Summary(string summary)]` | Class or Method | Sets the summary metadata applied to the generated endpoint(s). | +| `[Tags(params string[] tags)]` | Class or Method | Assigns OpenAPI tags to the annotated handler(s) for grouping in API docs. | diff --git a/global.json b/global.json new file mode 100644 index 0000000..9a523dc --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "10.0.0", + "rollForward": "latestMajor", + "allowPrerelease": false + } +} \ No newline at end of file diff --git a/src/GeneratedEndpoints/Common/EquatableImmutableArray.cs b/src/GeneratedEndpoints/Common/EquatableImmutableArray.cs index d0e3b76..54c8caa 100644 --- a/src/GeneratedEndpoints/Common/EquatableImmutableArray.cs +++ b/src/GeneratedEndpoints/Common/EquatableImmutableArray.cs @@ -26,6 +26,6 @@ public static EquatableImmutableArray ToEquatableImmutableArray(this Immut /// An containing the same elements as the original enumerable. public static EquatableImmutableArray ToEquatableImmutableArray(this IEnumerable enumerable) { - return new EquatableImmutableArray(enumerable.ToImmutableArray()); + return new EquatableImmutableArray([..enumerable]); } } diff --git a/src/GeneratedEndpoints/Common/StringBuilderPool.cs b/src/GeneratedEndpoints/Common/StringBuilderPool.cs new file mode 100644 index 0000000..92ab132 --- /dev/null +++ b/src/GeneratedEndpoints/Common/StringBuilderPool.cs @@ -0,0 +1,46 @@ +using System.Text; + +namespace GeneratedEndpoints.Common; + +/// Provides a simple per-thread cache for instances. +internal static class StringBuilderPool +{ + private const int MaxBuilderCapacity = 128 * 1024; + + [ThreadStatic] + private static StringBuilder? _cachedInstance; + + /// Gets a with at least the requested capacity. + public static StringBuilder Get(int capacity = 16) + { + var builder = _cachedInstance; + if (builder is null) + return new StringBuilder(capacity); + + _cachedInstance = null; + builder.Clear(); + if (builder.Capacity < capacity) + builder.EnsureCapacity(capacity); + + return builder; + } + + /// Returns the to the pool if it is below the maximum retention size. + public static void Return(StringBuilder builder) + { + if (builder.Capacity > MaxBuilderCapacity) + return; + + builder.Clear(); + if (_cachedInstance is null) + _cachedInstance = builder; + } + + /// Converts the builder to a string and returns it to the pool. + public static string ToStringAndReturn(StringBuilder builder) + { + var result = builder.ToString(); + Return(builder); + return result; + } +} diff --git a/src/GeneratedEndpoints/Common/TypeSymbolExtensions.cs b/src/GeneratedEndpoints/Common/TypeSymbolExtensions.cs index 1258fbc..1047514 100644 --- a/src/GeneratedEndpoints/Common/TypeSymbolExtensions.cs +++ b/src/GeneratedEndpoints/Common/TypeSymbolExtensions.cs @@ -2,194 +2,8 @@ namespace GeneratedEndpoints.Common; -/// Provides extension methods for working with type symbols. internal static class TypeSymbolExtensions { - public static bool IsFromRouteAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromRouteAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsFromQueryAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromQueryAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsFromHeaderAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromHeaderAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsFromBodyAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromBodyAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsFromFormAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromFormAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsFromServicesAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromServicesAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsFromKeyedServicesAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "FromKeyedServicesAttribute", - ContainingNamespace: - { - Name: "Mvc", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsAsParametersAttribute(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "AsParametersAttribute", - ContainingNamespace: - { - Name: "Http", - ContainingNamespace: - { - Name: "AspNetCore", - ContainingNamespace: - { - Name: "Microsoft", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }, - }; - } - - public static bool IsCancellationToken(this ITypeSymbol symbol) - { - return symbol is INamedTypeSymbol - { - MetadataName: "CancellationToken", - ContainingNamespace: - { - Name: "Threading", - ContainingNamespace: - { - Name: "System", - ContainingNamespace.IsGlobalNamespace: true, - }, - }, - }; - } - public static bool IsValueTask(this ITypeSymbol symbol, out INamedTypeSymbol valueTaskSymbol) { if (symbol is INamedTypeSymbol diff --git a/src/GeneratedEndpoints/GeneratedEndpoints.csproj b/src/GeneratedEndpoints/GeneratedEndpoints.csproj index 8c260ed..55bf32f 100644 --- a/src/GeneratedEndpoints/GeneratedEndpoints.csproj +++ b/src/GeneratedEndpoints/GeneratedEndpoints.csproj @@ -20,7 +20,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -36,9 +36,9 @@ GeneratedEndpoints - 9.0.0-preview.1 - 9.0.0.0 - 9.0.0.0 + 10.0.0 + 10.0.0.0 + 10.0.0.0 en-US false diff --git a/src/GeneratedEndpoints/MinimalApiGenerator.Constants.cs b/src/GeneratedEndpoints/MinimalApiGenerator.Constants.cs new file mode 100644 index 0000000..0f51419 --- /dev/null +++ b/src/GeneratedEndpoints/MinimalApiGenerator.Constants.cs @@ -0,0 +1,773 @@ +using System.Collections.Immutable; +using System.Runtime.CompilerServices; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace GeneratedEndpoints; + +public sealed partial class MinimalApiGenerator +{ + private const string BaseNamespace = "Microsoft.AspNetCore.Generated"; + private const string AttributesNamespace = $"{BaseNamespace}.Attributes"; + + private const string FallbackHttpMethod = "__FALLBACK__"; + + private const string NameAttributeNamedParameter = "Name"; + private const string ResponseTypeAttributeNamedParameter = "ResponseType"; + private const string RequestTypeAttributeNamedParameter = "RequestType"; + private const string IsOptionalAttributeNamedParameter = "IsOptional"; + private const string PolicyNameAttributeNamedParameter = "PolicyName"; + + private const string RequireAuthorizationAttributeName = "RequireAuthorizationAttribute"; + private const string RequireAuthorizationAttributeFullyQualifiedName = $"{AttributesNamespace}.{RequireAuthorizationAttributeName}"; + private const string RequireAuthorizationAttributeHint = $"{RequireAuthorizationAttributeFullyQualifiedName}.gs.cs"; + + private const string RequireCorsAttributeName = "RequireCorsAttribute"; + private const string RequireCorsAttributeFullyQualifiedName = $"{AttributesNamespace}.{RequireCorsAttributeName}"; + private const string RequireCorsAttributeHint = $"{RequireCorsAttributeFullyQualifiedName}.gs.cs"; + + private const string RequireRateLimitingAttributeName = "RequireRateLimitingAttribute"; + private const string RequireRateLimitingAttributeFullyQualifiedName = $"{AttributesNamespace}.{RequireRateLimitingAttributeName}"; + private const string RequireRateLimitingAttributeHint = $"{RequireRateLimitingAttributeFullyQualifiedName}.gs.cs"; + + private const string RequireHostAttributeName = "RequireHostAttribute"; + private const string RequireHostAttributeFullyQualifiedName = $"{AttributesNamespace}.{RequireHostAttributeName}"; + private const string RequireHostAttributeHint = $"{RequireHostAttributeFullyQualifiedName}.gs.cs"; + + private const string DisableAntiforgeryAttributeName = "DisableAntiforgeryAttribute"; + private const string DisableAntiforgeryAttributeFullyQualifiedName = $"{AttributesNamespace}.{DisableAntiforgeryAttributeName}"; + private const string DisableAntiforgeryAttributeHint = $"{DisableAntiforgeryAttributeFullyQualifiedName}.gs.cs"; + + private const string ShortCircuitAttributeName = "ShortCircuitAttribute"; + private const string ShortCircuitAttributeFullyQualifiedName = $"{AttributesNamespace}.{ShortCircuitAttributeName}"; + private const string ShortCircuitAttributeHint = $"{ShortCircuitAttributeFullyQualifiedName}.gs.cs"; + + private const string DisableRequestTimeoutAttributeName = "DisableRequestTimeoutAttribute"; + private const string DisableRequestTimeoutAttributeFullyQualifiedName = $"{AttributesNamespace}.{DisableRequestTimeoutAttributeName}"; + private const string DisableRequestTimeoutAttributeHint = $"{DisableRequestTimeoutAttributeFullyQualifiedName}.gs.cs"; + + private const string DisableValidationAttributeName = "DisableValidationAttribute"; + private const string DisableValidationAttributeFullyQualifiedName = $"{AttributesNamespace}.{DisableValidationAttributeName}"; + private const string DisableValidationAttributeHint = $"{DisableValidationAttributeFullyQualifiedName}.gs.cs"; + + private const string RequestTimeoutAttributeName = "RequestTimeoutAttribute"; + private const string RequestTimeoutAttributeFullyQualifiedName = $"{AttributesNamespace}.{RequestTimeoutAttributeName}"; + private const string RequestTimeoutAttributeHint = $"{RequestTimeoutAttributeFullyQualifiedName}.gs.cs"; + + private const string OrderAttributeName = "OrderAttribute"; + private const string OrderAttributeFullyQualifiedName = $"{AttributesNamespace}.{OrderAttributeName}"; + private const string OrderAttributeHint = $"{OrderAttributeFullyQualifiedName}.gs.cs"; + + private const string MapGroupAttributeName = "MapGroupAttribute"; + private const string MapGroupAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapGroupAttributeName}"; + private const string MapGroupAttributeHint = $"{MapGroupAttributeFullyQualifiedName}.gs.cs"; + + private const string SummaryAttributeName = "SummaryAttribute"; + private const string SummaryAttributeFullyQualifiedName = $"{AttributesNamespace}.{SummaryAttributeName}"; + private const string SummaryAttributeHint = $"{SummaryAttributeFullyQualifiedName}.gs.cs"; + + private const string AllowAnonymousAttributeName = "AllowAnonymousAttribute"; + + private const string EndpointFilterAttributeName = "EndpointFilterAttribute"; + private const string EndpointFilterAttributeFullyQualifiedName = $"{AttributesNamespace}.{EndpointFilterAttributeName}"; + private const string EndpointFilterAttributeHint = $"{EndpointFilterAttributeFullyQualifiedName}.gs.cs"; + + private const string AcceptsAttributeName = "AcceptsAttribute"; + private const string AcceptsAttributeFullyQualifiedName = $"{AttributesNamespace}.{AcceptsAttributeName}"; + private const string AcceptsAttributeHint = $"{AcceptsAttributeFullyQualifiedName}.gs.cs"; + + private const string ProducesResponseAttributeName = "ProducesResponseAttribute"; + private const string ProducesResponseAttributeFullyQualifiedName = $"{AttributesNamespace}.{ProducesResponseAttributeName}"; + private const string ProducesResponseAttributeHint = $"{ProducesResponseAttributeFullyQualifiedName}.gs.cs"; + + private const string ProducesProblemAttributeName = "ProducesProblemAttribute"; + private const string ProducesProblemAttributeFullyQualifiedName = $"{AttributesNamespace}.{ProducesProblemAttributeName}"; + private const string ProducesProblemAttributeHint = $"{ProducesProblemAttributeFullyQualifiedName}.gs.cs"; + + private const string ProducesValidationProblemAttributeName = "ProducesValidationProblemAttribute"; + + private const string ProducesValidationProblemAttributeFullyQualifiedName = $"{AttributesNamespace}.{ProducesValidationProblemAttributeName}"; + + private const string ProducesValidationProblemAttributeHint = $"{ProducesValidationProblemAttributeFullyQualifiedName}.gs.cs"; + + private const string RoutingNamespace = $"{BaseNamespace}.Routing"; + + private const string AddEndpointHandlersClassName = "EndpointServicesExtensions"; + private const string AddEndpointHandlersMethodName = "AddEndpointHandlers"; + private const string AddEndpointHandlersMethodHint = $"{RoutingNamespace}.{AddEndpointHandlersMethodName}.g.cs"; + + private const string UseEndpointHandlersClassName = "EndpointRouteBuilderExtensions"; + private const string UseEndpointHandlersMethodName = "MapEndpointHandlers"; + private const string UseEndpointHandlersMethodHint = $"{RoutingNamespace}.{UseEndpointHandlersMethodName}.g.cs"; + + private const string ConfigureMethodName = "Configure"; + private const string AsyncSuffix = "Async"; + private const string GlobalPrefix = "global::"; + private static readonly string[] AttributesNamespaceParts = AttributesNamespace.Split('.'); + private static readonly string[] AspNetCoreHttpNamespaceParts = ["Microsoft", "AspNetCore", "Http"]; + private static readonly string[] AspNetCoreMvcNamespaceParts = ["Microsoft", "AspNetCore", "Mvc"]; + private static readonly string[] AspNetCoreAuthorizationNamespaceParts = ["Microsoft", "AspNetCore", "Authorization"]; + private static readonly string[] AspNetCoreRoutingNamespaceParts = ["Microsoft", "AspNetCore", "Routing"]; + private static readonly string[] ExtensionsDependencyInjectionNamespaceParts = + ["Microsoft", "Extensions", "DependencyInjection"]; + private static readonly string[] ComponentModelNamespaceParts = ["System", "ComponentModel"]; + private static readonly ConditionalWeakTable CompilationTypeCaches = new(); + private static readonly ConditionalWeakTable RequestHandlerClassCache = new(); + private static readonly ConditionalWeakTable GeneratedAttributeKindCache = new(); + + private static readonly string FileHeader = $""" + //----------------------------------------------------------------------------- + // + // This code was generated by {nameof(MinimalApiGenerator)} which can be found + // in the {typeof(MinimalApiGenerator).Namespace} namespace. + // + // Changes to this file may cause incorrect behavior + // and will be lost if the code is regenerated. + // + //----------------------------------------------------------------------------- + + #nullable enable + """; + + private static readonly ImmutableArray HttpAttributeDefinitions = + [ + CreateHttpAttributeDefinition("MapGetAttribute", "GET"), + CreateHttpAttributeDefinition("MapPostAttribute", "POST"), + CreateHttpAttributeDefinition("MapPutAttribute", "PUT"), + CreateHttpAttributeDefinition("MapPatchAttribute", "PATCH"), + CreateHttpAttributeDefinition("MapDeleteAttribute", "DELETE"), + CreateHttpAttributeDefinition("MapOptionsAttribute", "OPTIONS"), + CreateHttpAttributeDefinition("MapHeadAttribute", "HEAD"), + CreateHttpAttributeDefinition("MapQueryAttribute", "QUERY"), + CreateHttpAttributeDefinition("MapTraceAttribute", "TRACE"), + CreateHttpAttributeDefinition("MapConnectAttribute", "CONNECT"), + CreateHttpAttributeDefinition("MapFallbackAttribute", FallbackHttpMethod, true), + ]; + + private static readonly ImmutableDictionary HttpAttributeDefinitionsByName = + HttpAttributeDefinitions.ToImmutableDictionary(static definition => definition.Name); + + private static readonly SourceText RequireAuthorizationAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies that authorization is required for the annotated endpoint or class. + /// Optionally restricts access to the specified authorization policies. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{RequireAuthorizationAttributeName}} : global::System.Attribute + { + /// + /// Gets the policy names that the endpoint or class requires. + /// + public string[] PolicyNames { get; } + + /// + /// Marks the endpoint or class as requiring authorization. + /// + public {{RequireAuthorizationAttributeName}}() + { + PolicyNames = []; + } + + /// + /// Marks the endpoint or class as requiring authorization with one or more policies. + /// + public {{RequireAuthorizationAttributeName}}(params string[] policyNames) + { + PolicyNames = policyNames ?? []; + } + } + """, Encoding.UTF8 + ); + + private static readonly SourceText RequireCorsAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies that the annotated endpoint requires a configured CORS policy. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{RequireCorsAttributeName}} : global::System.Attribute + { + /// + /// Gets the optional CORS policy name. + /// + public string? PolicyName { get; } + + /// + /// Marks the endpoint or class as requiring the default CORS policy. + /// + public {{RequireCorsAttributeName}}() + { + } + + /// + /// Marks the endpoint or class as requiring the specified named CORS policy. + /// + public {{RequireCorsAttributeName}}(string policyName) + { + PolicyName = policyName; + } + } + """, Encoding.UTF8 + ); + + private static readonly SourceText RequireRateLimitingAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies that the annotated endpoint requires the provided rate limiting policy. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{RequireRateLimitingAttributeName}} : global::System.Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The rate limiting policy to apply. + public {{RequireRateLimitingAttributeName}}(string policyName) + { + PolicyName = policyName; + } + + /// + /// Gets the rate limiting policy name. + /// + public string PolicyName { get; } + } + """, Encoding.UTF8 + ); + + private static readonly SourceText RequireHostAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies the allowed hosts for the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{RequireHostAttributeName}} : global::System.Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// The hosts that are allowed to access the endpoint. + public {{RequireHostAttributeName}}(params string[] hosts) + { + Hosts = hosts ?? []; + } + + /// + /// Gets the allowed hosts. + /// + public string[] Hosts { get; } + } + """, Encoding.UTF8 + ); + + private static readonly SourceText DisableAntiforgeryAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Disables antiforgery protection for the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{DisableAntiforgeryAttributeName}} : global::System.Attribute + { + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText ShortCircuitAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Marks the annotated endpoint or class to short-circuit the request pipeline. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{ShortCircuitAttributeName}} : global::System.Attribute + { + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText DisableRequestTimeoutAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Disables the request timeout for the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{DisableRequestTimeoutAttributeName}} : global::System.Attribute + { + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText DisableValidationAttributeSourceText = SourceText.From($$""" + #if NET10_0_OR_GREATER + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Disables request validation for the annotated endpoint or class when targeting .NET 10 or later. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{DisableValidationAttributeName}} : global::System.Attribute + { + } + #endif + + """, Encoding.UTF8 + ); + + private static readonly SourceText RequestTimeoutAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Applies the request timeout metadata to the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{RequestTimeoutAttributeName}} : global::System.Attribute + { + /// + /// Gets the optional request timeout policy name. + /// + public string? PolicyName { get; init; } + + /// + /// Applies the default request timeout behavior. + /// + public {{RequestTimeoutAttributeName}}() + { + } + + /// + /// Applies the specified request timeout policy. + /// + /// The request timeout policy name. + public {{RequestTimeoutAttributeName}}(string policyName) + { + PolicyName = policyName; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText OrderAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies the order for the annotated endpoint when building conventions. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{OrderAttributeName}} : global::System.Attribute + { + /// + /// Gets the order that will be applied to the endpoint. + /// + public int Order { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The order value to apply to the endpoint. + public {{OrderAttributeName}}(int order) + { + Order = order; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText MapGroupAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies the route group for the annotated class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + internal sealed class {{MapGroupAttributeName}} : global::System.Attribute + { + /// + /// Gets the route group pattern. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint group name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route group pattern to apply. + public {{MapGroupAttributeName}}(string pattern) + { + Pattern = pattern; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText SummaryAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies the summary metadata for the annotated endpoint. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] + internal sealed class {{SummaryAttributeName}} : global::System.Attribute + { + /// + /// Gets the summary value for the endpoint. + /// + public string Summary { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The summary to apply to the endpoint. + public {{SummaryAttributeName}}(string summary) + { + Summary = summary; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText AcceptsAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies the request type and content types accepted by the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{AcceptsAttributeName}} : global::System.Attribute + { + /// + /// Gets the request type accepted by the endpoint. + /// + public global::System.Type? RequestType { get; init; } + + /// + /// Gets a value indicating whether the request body is optional. + /// + public bool IsOptional { get; init; } + + /// + /// Gets the primary content type accepted by the endpoint. + /// + public string ContentType { get; } + + /// + /// Gets the additional content types accepted by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The primary content type accepted by the endpoint. + /// Additional content types accepted by the endpoint. + public {{AcceptsAttributeName}}(string contentType = "application/json", params string[] additionalContentTypes) + { + ContentType = string.IsNullOrWhiteSpace(contentType) ? "application/json" : contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } + } + + /// + /// Specifies the request type using a generic argument and the content types accepted by the annotated endpoint or class. + /// + /// The CLR type of the request body. + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{AcceptsAttributeName}} : global::System.Attribute + { + /// + /// Gets the request type accepted by the endpoint. + /// + public global::System.Type RequestType => typeof(TRequest); + + /// + /// Gets a value indicating whether the request body is optional. + /// + public bool IsOptional { get; init; } + + /// + /// Gets the primary content type accepted by the endpoint. + /// + public string ContentType { get; } + + /// + /// Gets the additional content types accepted by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the generic Accepts attribute class. + /// + /// The primary content type accepted by the endpoint. + /// Additional content types accepted by the endpoint. + public {{AcceptsAttributeName}}(string contentType = "application/json", params string[] additionalContentTypes) + { + ContentType = string.IsNullOrWhiteSpace(contentType) ? "application/json" : contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText EndpointFilterAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies an endpoint filter type to apply to the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{EndpointFilterAttributeName}} : global::System.Attribute + { + /// + /// Gets the CLR type of the endpoint filter. + /// + public global::System.Type FilterType { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The CLR type of the endpoint filter. + public {{EndpointFilterAttributeName}}(global::System.Type filterType) + { + FilterType = filterType ?? throw new global::System.ArgumentNullException(nameof(filterType)); + } + } + + /// + /// Specifies an endpoint filter type using a generic argument. + /// + /// The CLR type of the endpoint filter. + [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{EndpointFilterAttributeName}} : global::System.Attribute + { + /// + /// Gets the CLR type of the endpoint filter. + /// + public global::System.Type FilterType => typeof(TFilter); + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText ProducesResponseAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies a response type, status code, and content types produced by the annotated endpoint or class. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{ProducesResponseAttributeName}} : global::System.Attribute + { + /// + /// Gets the response type produced by the endpoint. + /// + public global::System.Type? ResponseType { get; init; } + + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public {{ProducesResponseAttributeName}}(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status200OK, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } + } + + /// + /// Specifies a response type using a generic argument along with status code and content types produced by the annotated endpoint or class. + /// + /// The CLR type of the response body. + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{ProducesResponseAttributeName}} : global::System.Attribute + { + /// + /// Gets the response type produced by the endpoint. + /// + public global::System.Type ResponseType => typeof(TResponse); + + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the generic Produces attribute class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public {{ProducesResponseAttributeName}}(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status200OK, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText ProducesProblemAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies that the endpoint produces a problem details payload. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{ProducesProblemAttributeName}} : global::System.Attribute + { + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public {{ProducesProblemAttributeName}}(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } + } + + """, Encoding.UTF8 + ); + + private static readonly SourceText ProducesValidationProblemAttributeSourceText = SourceText.From($$""" + {{FileHeader}} + + namespace {{AttributesNamespace}}; + + /// + /// Specifies that the endpoint produces a validation problem details payload. + /// + [global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] + internal sealed class {{ProducesValidationProblemAttributeName}} : global::System.Attribute + { + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public {{ProducesValidationProblemAttributeName}}(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } + } + + """, Encoding.UTF8 + ); + +} diff --git a/src/GeneratedEndpoints/MinimalApiGenerator.Types.cs b/src/GeneratedEndpoints/MinimalApiGenerator.Types.cs new file mode 100644 index 0000000..8ec7a24 --- /dev/null +++ b/src/GeneratedEndpoints/MinimalApiGenerator.Types.cs @@ -0,0 +1,234 @@ +using GeneratedEndpoints.Common; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; + +namespace GeneratedEndpoints; + +public sealed partial class MinimalApiGenerator +{ + private readonly record struct HttpAttributeDefinition( + string Name, + string FullyQualifiedName, + string Hint, + string Verb, + SourceText SourceText + ); + + private readonly record struct RequestHandler( + RequestHandlerClass Class, + RequestHandlerMethod Method, + string HttpMethod, + string Pattern, + EndpointConfiguration Configuration + ); + + private readonly record struct RequestHandlerClass( + string Name, + bool IsStatic, + bool HasConfigureMethod, + bool ConfigureMethodAcceptsServiceProvider, + string? MapGroupPattern, + string? MapGroupBuilderIdentifier, + EndpointConfiguration Configuration + ); + + private readonly record struct EndpointConfiguration( + RequestHandlerMetadata Metadata, + bool RequireAuthorization, + EquatableImmutableArray? AuthorizationPolicies, + bool DisableAntiforgery, + bool AllowAnonymous, + bool RequireCors, + string? CorsPolicyName, + EquatableImmutableArray? RequiredHosts, + bool RequireRateLimiting, + string? RateLimitingPolicyName, + EquatableImmutableArray? EndpointFilterTypes, + bool ShortCircuit, + bool DisableValidation, + bool DisableRequestTimeout, + bool WithRequestTimeout, + string? RequestTimeoutPolicyName, + int? Order, + string? EndpointGroupName + ); + + private readonly record struct RequestHandlerMethod(string Name, bool IsStatic, bool IsAwaitable, EquatableImmutableArray Parameters); + + private readonly record struct RequestHandlerMetadata( + string? Name, + string? DisplayName, + string? Summary, + string? Description, + EquatableImmutableArray? Tags, + EquatableImmutableArray? Accepts, + EquatableImmutableArray? Produces, + EquatableImmutableArray? ProducesProblem, + EquatableImmutableArray? ProducesValidationProblem, + bool ExcludeFromDescription + ); + + private readonly record struct AcceptsMetadata( + string RequestType, + string ContentType, + EquatableImmutableArray? AdditionalContentTypes, + bool IsOptional + ); + + private readonly record struct ProducesMetadata( + string ResponseType, + int StatusCode, + string? ContentType, + EquatableImmutableArray? AdditionalContentTypes + ); + + private readonly record struct ProducesProblemMetadata(int StatusCode, string? ContentType, EquatableImmutableArray? AdditionalContentTypes); + + private readonly record struct ProducesValidationProblemMetadata( + int StatusCode, + string? ContentType, + EquatableImmutableArray? AdditionalContentTypes + ); + + private readonly record struct Parameter(string Name, string Type, string BindingPrefix); + + private readonly record struct ConfigureMethodDetails(bool HasConfigureMethod, bool ConfigureMethodAcceptsServiceProvider); + + private struct EndpointAttributeState + { + public EquatableImmutableArray? Tags; + public bool? RequireAuthorization; + public EquatableImmutableArray? AuthorizationPolicies; + public bool? DisableAntiforgery; + public bool? AllowAnonymous; + public bool? ExcludeFromDescription; + public List? Accepts; + public List? Produces; + public List? ProducesProblem; + public List? ProducesValidationProblem; + public bool? RequireCors; + public string? CorsPolicyName; + public EquatableImmutableArray? RequiredHosts; + public bool? RequireRateLimiting; + public string? RateLimitingPolicyName; + public List? EndpointFilters; + public HashSet? EndpointFilterSet; + public bool HasAllowAnonymousAttribute; + public bool HasRequireAuthorizationAttribute; + public bool? ShortCircuit; + public bool? DisableValidation; + public bool? DisableRequestTimeout; + public bool? WithRequestTimeout; + public string? RequestTimeoutPolicyName; + public int? Order; + public string? EndpointGroupName; + public string? Summary; + } + + private enum GeneratedAttributeKind + { + None = 0, + ShortCircuit, + DisableValidation, + DisableRequestTimeout, + RequestTimeout, + Order, + MapGroup, + Summary, + Accepts, + ProducesResponse, + RequireAuthorization, + RequireCors, + RequireHost, + RequireRateLimiting, + EndpointFilter, + DisableAntiforgery, + ProducesProblem, + ProducesValidationProblem, + } + + private enum BindingSource + { + None = 0, + FromRoute = 1, + FromQuery = 2, + FromHeader = 3, + FromBody = 4, + FromForm = 5, + FromServices = 6, + FromKeyedServices = 7, + AsParameters = 8, + } + + private sealed class RequestHandlerComparer : IComparer + { + public static RequestHandlerComparer Instance { get; } = new(); + + public int Compare(RequestHandler x, RequestHandler y) + { + var comparison = string.Compare(x.Class.Name, y.Class.Name, StringComparison.Ordinal); + if (comparison != 0) + return comparison; + + comparison = string.Compare(x.Method.Name, y.Method.Name, StringComparison.Ordinal); + if (comparison != 0) + return comparison; + + comparison = string.Compare(x.HttpMethod, y.HttpMethod, StringComparison.Ordinal); + if (comparison != 0) + return comparison; + + return string.Compare(x.Pattern, y.Pattern, StringComparison.Ordinal); + } + } + + private sealed class CompilationTypeCache(Compilation compilation) + { + public INamedTypeSymbol? EndpointConventionBuilderSymbol { get; } = + compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Builder.IEndpointConventionBuilder"); + + public INamedTypeSymbol? ServiceProviderSymbol { get; } = compilation.GetTypeByMetadataName("System.IServiceProvider"); + } + + private sealed class RequestHandlerClassCacheEntry + { + private readonly object _lock = new(); + private RequestHandlerClass _value; + private bool _initialized; + + public RequestHandlerClass GetOrCreate(INamedTypeSymbol classSymbol, CompilationTypeCache compilationCache, CancellationToken cancellationToken) + { + if (_initialized) + return _value; + + lock (_lock) + { + if (_initialized) + return _value; + + cancellationToken.ThrowIfCancellationRequested(); + + var name = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var isStatic = classSymbol.IsStatic; + var configureMethodDetails = GetConfigureMethodDetails(classSymbol, compilationCache.EndpointConventionBuilderSymbol, + compilationCache.ServiceProviderSymbol, cancellationToken + ); + + var mapGroupPattern = GetMapGroupPattern(classSymbol); + var mapGroupIdentifier = mapGroupPattern is null ? null : GetMapGroupIdentifier(name); + var classConfiguration = GetEndpointConfiguration(classSymbol.GetAttributes(), null, null, null, false); + + _value = new RequestHandlerClass(name, isStatic, configureMethodDetails.HasConfigureMethod, + configureMethodDetails.ConfigureMethodAcceptsServiceProvider, mapGroupPattern, mapGroupIdentifier, classConfiguration + ); + _initialized = true; + return _value; + } + } + } + + private sealed class GeneratedAttributeKindCacheEntry(GeneratedAttributeKind kind) + { + public GeneratedAttributeKind Kind { get; } = kind; + } +} diff --git a/src/GeneratedEndpoints/MinimalApiGenerator.cs b/src/GeneratedEndpoints/MinimalApiGenerator.cs index ff0449d..c5ebad8 100644 --- a/src/GeneratedEndpoints/MinimalApiGenerator.cs +++ b/src/GeneratedEndpoints/MinimalApiGenerator.cs @@ -1,4 +1,6 @@ -using System.Collections.Immutable; +using System.Buffers; +using System.Collections.Immutable; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; @@ -10,235 +12,83 @@ namespace GeneratedEndpoints; [Generator] -public sealed class MinimalApiGenerator : IIncrementalGenerator +public sealed partial class MinimalApiGenerator : IIncrementalGenerator { - private const string BaseNamespace = "Microsoft.AspNetCore.Generated"; - private const string AttributesNamespace = $"{BaseNamespace}.Attributes"; - - private const string MapGetAttributeName = "MapGetAttribute"; - private const string MapGetAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapGetAttributeName}"; - private const string MapGetAttributeHint = $"{MapGetAttributeFullyQualifiedName}.gs.cs"; - - private const string MapPostAttributeName = "MapPostAttribute"; - private const string MapPostAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapPostAttributeName}"; - private const string MapPostAttributeHint = $"{MapPostAttributeFullyQualifiedName}.gs.cs"; - - private const string MapPutAttributeName = "MapPutAttribute"; - private const string MapPutAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapPutAttributeName}"; - private const string MapPutAttributeHint = $"{MapPutAttributeFullyQualifiedName}.gs.cs"; - - private const string MapDeleteAttributeName = "MapDeleteAttribute"; - private const string MapDeleteAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapDeleteAttributeName}"; - private const string MapDeleteAttributeHint = $"{MapDeleteAttributeFullyQualifiedName}.gs.cs"; - - private const string MapOptionsAttributeName = "MapOptionsAttribute"; - private const string MapOptionsAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapOptionsAttributeName}"; - private const string MapOptionsAttributeHint = $"{MapOptionsAttributeFullyQualifiedName}.gs.cs"; - - private const string MapHeadAttributeName = "MapHeadAttribute"; - private const string MapHeadAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapHeadAttributeName}"; - private const string MapHeadAttributeHint = $"{MapHeadAttributeFullyQualifiedName}.gs.cs"; - - private const string MapPatchAttributeName = "MapPatchAttribute"; - private const string MapPatchAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapPatchAttributeName}"; - private const string MapPatchAttributeHint = $"{MapPatchAttributeFullyQualifiedName}.gs.cs"; - - private const string MapTraceAttributeName = "MapTraceAttribute"; - private const string MapTraceAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapTraceAttributeName}"; - private const string MapTraceAttributeHint = $"{MapTraceAttributeFullyQualifiedName}.gs.cs"; - - private const string MapConnectAttributeName = "MapConnectAttribute"; - private const string MapConnectAttributeFullyQualifiedName = $"{AttributesNamespace}.{MapConnectAttributeName}"; - private const string MapConnectAttributeHint = $"{MapConnectAttributeFullyQualifiedName}.gs.cs"; - - private const string NameAttributeNamedParameter = "Name"; - private const string SummaryAttributeNamedParameter = "Summary"; - private const string DescriptionAttributeNamedParameter = "Description"; - - private const string RequireAuthorizationAttributeName = "RequireAuthorizationAttribute"; - private const string RequireAuthorizationAttributeFullyQualifiedName = $"{AttributesNamespace}.{RequireAuthorizationAttributeName}"; - private const string RequireAuthorizationAttributeHint = $"{RequireAuthorizationAttributeFullyQualifiedName}.gs.cs"; - - private const string DisableAntiforgeryAttributeName = "DisableAntiforgeryAttribute"; - private const string DisableAntiforgeryAttributeFullyQualifiedName = $"{AttributesNamespace}.{DisableAntiforgeryAttributeName}"; - private const string DisableAntiforgeryAttributeHint = $"{DisableAntiforgeryAttributeFullyQualifiedName}.gs.cs"; + public void Initialize(IncrementalGeneratorInitializationContext context) + { + context.RegisterPostInitializationOutput(RegisterAttributes); - private const string RoutingNamespace = $"{BaseNamespace}.Routing"; + var requestHandlerProviders = ImmutableArray.CreateBuilder>>(HttpAttributeDefinitions.Length); - private const string AddEndpointHandlersClassName = "EndpointServicesExtensions"; - private const string AddEndpointHandlersMethodName = "AddEndpointHandlers"; - private const string AddEndpointHandlersMethodHint = $"{RoutingNamespace}.{AddEndpointHandlersMethodName}.g.cs"; + foreach (var definition in HttpAttributeDefinitions) + { + var handlers = context.SyntaxProvider + .ForAttributeWithMetadataName(definition.FullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) + .WhereNotNull() + .Collect(); - private const string UseEndpointHandlersClassName = "EndpointRouteBuilderExtensions"; - private const string UseEndpointHandlersMethodName = "MapEndpointHandlers"; - private const string UseEndpointHandlersMethodHint = $"{RoutingNamespace}.{UseEndpointHandlersMethodName}.g.cs"; + requestHandlerProviders.Add(handlers); + } - private const string AsyncSuffix = "Async"; + var requestHandlers = CombineRequestHandlers(requestHandlerProviders.MoveToImmutable()); - private static readonly string FileHeader = $""" - //----------------------------------------------------------------------------- - // - // This code was generated by {nameof(MinimalApiGenerator)} which can be found - // in the {typeof(MinimalApiGenerator).Namespace} namespace. - // - // Changes to this file may cause incorrect behavior - // and will be lost if the code is regenerated. - // - //----------------------------------------------------------------------------- + context.RegisterSourceOutput(requestHandlers, GenerateSource); + } - #nullable enable - """; + private static HttpAttributeDefinition CreateHttpAttributeDefinition(string attributeName, string verb, bool allowOptionalPattern = false) + { + var fullyQualifiedName = $"{AttributesNamespace}.{attributeName}"; + var hint = $"{fullyQualifiedName}.gs.cs"; + var summaryVerb = verb == FallbackHttpMethod ? "fallback" : verb; + var source = GenerateHttpAttributeSource(AttributesNamespace, attributeName, summaryVerb, allowOptionalPattern); + return new HttpAttributeDefinition(attributeName, fullyQualifiedName, hint, verb, SourceText.From(source, Encoding.UTF8)); + } - public void Initialize(IncrementalGeneratorInitializationContext context) + private static IncrementalValueProvider> CombineRequestHandlers( + ImmutableArray>> handlerProviders + ) { - context.RegisterPostInitializationOutput(RegisterAttributes); + if (handlerProviders.IsDefaultOrEmpty) + throw new InvalidOperationException("No HTTP attribute definitions were provided."); - var getRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapGetAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var postRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapPostAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var putRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapPutAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var deleteRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapDeleteAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var optionsRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapOptionsAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var headRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapHeadAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var patchRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapPatchAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var traceRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapTraceAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var connectRequestHandlers = context.SyntaxProvider - .ForAttributeWithMetadataName(MapConnectAttributeFullyQualifiedName, RequestHandlerFilter, RequestHandlerTransform) - .WhereNotNull() - .Collect(); - - var requestHandlers = getRequestHandlers.Combine(postRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(putRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(patchRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(deleteRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(optionsRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(headRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(traceRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)) - .Combine(connectRequestHandlers) - .Select(static (x, _) => x.Left.AddRange(x.Right)); + var combined = handlerProviders[0]; + for (var i = 1; i < handlerProviders.Length; i++) + { + combined = combined.Combine(handlerProviders[i]) + .Select(static (x, _) => x.Left.AddRange(x.Right)); + } - context.RegisterSourceOutput(requestHandlers, GenerateSource); + return combined; } private static void RegisterAttributes(IncrementalGeneratorPostInitializationContext context) { - // Definitions for HTTP method attributes - var httpAttributes = new[] - { - (Name: MapGetAttributeName, FullyQualified: MapGetAttributeFullyQualifiedName, Hint: MapGetAttributeHint, Verb: "GET"), - (Name: MapPostAttributeName, FullyQualified: MapPostAttributeFullyQualifiedName, Hint: MapPostAttributeHint, Verb: "POST"), - (Name: MapPutAttributeName, FullyQualified: MapPutAttributeFullyQualifiedName, Hint: MapPutAttributeHint, Verb: "PUT"), - (Name: MapDeleteAttributeName, FullyQualified: MapDeleteAttributeFullyQualifiedName, Hint: MapDeleteAttributeHint, Verb: "DELETE"), - (Name: MapOptionsAttributeName, FullyQualified: MapOptionsAttributeFullyQualifiedName, Hint: MapOptionsAttributeHint, Verb: "OPTIONS"), - (Name: MapHeadAttributeName, FullyQualified: MapHeadAttributeFullyQualifiedName, Hint: MapHeadAttributeHint, Verb: "HEAD"), - (Name: MapPatchAttributeName, FullyQualified: MapPatchAttributeFullyQualifiedName, Hint: MapPatchAttributeHint, Verb: "PATCH"), - (Name: MapTraceAttributeName, FullyQualified: MapTraceAttributeFullyQualifiedName, Hint: MapTraceAttributeHint, Verb: "TRACE"), - (Name: MapConnectAttributeName, FullyQualified: MapConnectAttributeFullyQualifiedName, Hint: MapConnectAttributeHint, Verb: "CONNECT"), - }; + foreach (var definition in HttpAttributeDefinitions) + context.AddSource(definition.Hint, definition.SourceText); + + context.AddSource(RequireAuthorizationAttributeHint, RequireAuthorizationAttributeSourceText); + context.AddSource(RequireCorsAttributeHint, RequireCorsAttributeSourceText); + context.AddSource(RequireRateLimitingAttributeHint, RequireRateLimitingAttributeSourceText); + context.AddSource(RequireHostAttributeHint, RequireHostAttributeSourceText); + context.AddSource(DisableAntiforgeryAttributeHint, DisableAntiforgeryAttributeSourceText); + context.AddSource(ShortCircuitAttributeHint, ShortCircuitAttributeSourceText); + context.AddSource(DisableRequestTimeoutAttributeHint, DisableRequestTimeoutAttributeSourceText); + context.AddSource(DisableValidationAttributeHint, DisableValidationAttributeSourceText); + context.AddSource(RequestTimeoutAttributeHint, RequestTimeoutAttributeSourceText); + context.AddSource(OrderAttributeHint, OrderAttributeSourceText); + context.AddSource(MapGroupAttributeHint, MapGroupAttributeSourceText); + context.AddSource(SummaryAttributeHint, SummaryAttributeSourceText); + context.AddSource(AcceptsAttributeHint, AcceptsAttributeSourceText); + context.AddSource(EndpointFilterAttributeHint, EndpointFilterAttributeSourceText); + context.AddSource(ProducesResponseAttributeHint, ProducesResponseAttributeSourceText); + context.AddSource(ProducesProblemAttributeHint, ProducesProblemAttributeSourceText); + context.AddSource(ProducesValidationProblemAttributeHint, ProducesValidationProblemAttributeSourceText); + } - foreach (var (name, _, hint, verb) in httpAttributes) - { - var source = GenerateHttpAttributeSource(FileHeader, AttributesNamespace, name, verb); - context.AddSource(hint, SourceText.From(source, Encoding.UTF8)); - } - - // RequireAuthorization - var requireAuthorizationSource = $$""" - {{FileHeader}} - - namespace {{AttributesNamespace}}; - - /// - /// Specifies that authorization is required for the annotated endpoint or class. - /// Optionally restricts access to the specified authorization policies. - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] - internal sealed class {{RequireAuthorizationAttributeName}} : global::System.Attribute - { - /// - /// Gets the policy names that the endpoint or class requires. - /// - public string[] PolicyNames { get; } - - /// - /// Marks the endpoint or class as requiring authorization. - /// - public {{RequireAuthorizationAttributeName}}() - { - PolicyNames = []; - } - - /// - /// Marks the endpoint or class as requiring authorization with one or more policies. - /// - public {{RequireAuthorizationAttributeName}}(params string[] policyNames) - { - PolicyNames = policyNames ?? []; - } - } - """; - context.AddSource(RequireAuthorizationAttributeHint, SourceText.From(requireAuthorizationSource, Encoding.UTF8)); - - // DisableAntiforgery - var disableAntiforgerySource = $$""" - {{FileHeader}} - - namespace {{AttributesNamespace}}; - - /// - /// Disables antiforgery protection for the annotated endpoint or class. - /// - [global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] - internal sealed class {{DisableAntiforgeryAttributeName}} : global::System.Attribute - { - } - - """; - context.AddSource(DisableAntiforgeryAttributeHint, SourceText.From(disableAntiforgerySource, Encoding.UTF8)); - } - - private static string GenerateHttpAttributeSource(string fileHeader, string attributesNamespace, string attributeName, string summaryVerb) + private static string GenerateHttpAttributeSource(string attributesNamespace, string attributeName, string summaryVerb, bool allowOptionalPattern = false) { return $$""" - {{fileHeader}} + {{FileHeader}} namespace {{attributesNamespace}}; @@ -251,31 +101,21 @@ internal sealed class {{attributeName}} : global::System.Attribute /// /// Gets the route pattern for the endpoint. /// - public string Pattern { get; } + public string{{(allowOptionalPattern ? "?" : "")}} Pattern { get; } /// /// Gets or sets the endpoint name. /// - public string Name { get; set; } = ""; - - /// - /// Gets or sets the endpoint summary. - /// - public string Summary { get; set; } = ""; - - /// - /// Gets or sets the endpoint description. - /// - public string Description { get; set; } = ""; + public string? Name { get; init; } /// /// Initializes a new instance of the class. /// /// The route pattern for the endpoint. - public {{attributeName}}([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) - { - Pattern = pattern; - } + public {{attributeName}}([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string{{(allowOptionalPattern ? "?" : "")}} pattern{{(allowOptionalPattern ? " = null" : "")}}) + { + Pattern = pattern; + } } """; } @@ -295,26 +135,21 @@ private static bool RequestHandlerFilter(SyntaxNode syntaxNode, CancellationToke return null; var attribute = context.Attributes[0]; - var requestHandlerClassResult = GetRequestHandlerClass(requestHandlerMethodSymbol, cancellationToken); - if (requestHandlerClassResult is null) + var requestHandlerClass = GetRequestHandlerClass(requestHandlerMethodSymbol, context.SemanticModel.Compilation, cancellationToken); + if (requestHandlerClass is null) return null; - var (requestHandlerClassSymbol, requestHandlerClass) = requestHandlerClassResult.Value; - var requestHandlerMethod = GetRequestHandlerMethod(requestHandlerMethodSymbol, cancellationToken); - var (httpMethod, pattern, name, summary, description) = GetRequestHandlerAttribute(attribute, cancellationToken); + var (httpMethod, pattern, name) = GetRequestHandlerAttribute(attribute, cancellationToken); - var (tags, requireAuthorization, authorizationPolicies, disableAntiforgery) = - GetAdditionalRequestHandlerAttributes(requestHandlerClassSymbol, requestHandlerMethodSymbol, cancellationToken); + var (displayName, description) = GetDisplayAndDescriptionAttributes(requestHandlerMethodSymbol); name ??= RemoveAsyncSuffix(requestHandlerMethod.Name); - var metadata = new RequestHandlerMetadata(name, summary, description, tags); + var methodConfiguration = GetEndpointConfiguration(requestHandlerMethodSymbol.GetAttributes(), name, displayName, description, true); - var requestHandler = new RequestHandler(requestHandlerClass, requestHandlerMethod, httpMethod, pattern, metadata, requireAuthorization, - authorizationPolicies, disableAntiforgery - ); + var requestHandler = new RequestHandler(requestHandlerClass.Value, requestHandlerMethod, httpMethod, pattern, methodConfiguration); return requestHandler; } @@ -327,34 +162,17 @@ private static string RemoveAsyncSuffix(string methodName) return methodName; } - private static (string HttpMethod, string Pattern, string? Name, string? Summary, string? Description) GetRequestHandlerAttribute( - AttributeData attribute, - CancellationToken cancellationToken - ) + private static ( string HttpMethod, string Pattern, string? Name ) GetRequestHandlerAttribute(AttributeData attribute, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var attributeName = attribute.AttributeClass?.Name ?? ""; - var httpMethod = attributeName switch - { - MapGetAttributeName => "Get", - MapPostAttributeName => "Post", - MapPutAttributeName => "Put", - MapDeleteAttributeName => "Delete", - MapOptionsAttributeName => "OPTIONS", - MapHeadAttributeName => "HEAD", - MapPatchAttributeName => "Patch", - MapTraceAttributeName => "TRACE", - MapConnectAttributeName => "CONNECT", - _ => "", - }; + var httpMethod = HttpAttributeDefinitionsByName.TryGetValue(attributeName, out var definition) ? definition.Verb : ""; var pattern = (attribute.ConstructorArguments.Length > 0 ? attribute.ConstructorArguments[0].Value as string : "") ?? ""; string? name = null; - string? summary = null; - string? description = null; foreach (var namedArg in attribute.NamedArguments) { switch (namedArg.Key) @@ -365,96 +183,252 @@ CancellationToken cancellationToken name = string.IsNullOrWhiteSpace(value) ? null : value!.Trim(); break; } - case SummaryAttributeNamedParameter: - { - var value = namedArg.Value.Value as string; - summary = string.IsNullOrWhiteSpace(value) ? null : value!.Trim(); - break; - } - case DescriptionAttributeNamedParameter: - { - var value = namedArg.Value.Value as string; - description = string.IsNullOrWhiteSpace(value) ? null : value!.Trim(); - break; - } } } - return (httpMethod, pattern, name, summary, description); + return (httpMethod, pattern, name); } - private static (EquatableImmutableArray? tags, bool requireAuthorization, EquatableImmutableArray? authorizationPolicies, bool - disableAntiforgery) GetAdditionalRequestHandlerAttributes(INamedTypeSymbol classSymbol, IMethodSymbol methodSymbol, CancellationToken cancellationToken) + private static (string? DisplayName, string? Description) GetDisplayAndDescriptionAttributes(IMethodSymbol methodSymbol) { - cancellationToken.ThrowIfCancellationRequested(); + string? displayName = null; + string? description = null; - EquatableImmutableArray? tags = null; - var requireAuthorization = false; - EquatableImmutableArray? authorizationPolicies = null; - var disableAntiforgery = false; + foreach (var attribute in methodSymbol.GetAttributes()) + { + var attributeClass = attribute.AttributeClass; + if (attributeClass is null) + continue; - var classAttributes = classSymbol.GetAttributes(); - GetAdditionalRequestHandlerAttributeValues(classAttributes, ref tags, ref requireAuthorization, ref authorizationPolicies, ref disableAntiforgery); + if (IsAttribute(attributeClass, nameof(DisplayNameAttribute), ComponentModelNamespaceParts)) + { + displayName = NormalizeOptionalString(attribute.ConstructorArguments.Length > 0 ? attribute.ConstructorArguments[0].Value as string : null); - var methodAttributes = methodSymbol.GetAttributes(); - GetAdditionalRequestHandlerAttributeValues(methodAttributes, ref tags, ref requireAuthorization, ref authorizationPolicies, ref disableAntiforgery); + continue; + } + + if (IsAttribute(attributeClass, nameof(DescriptionAttribute), ComponentModelNamespaceParts)) + description = NormalizeOptionalString(attribute.ConstructorArguments.Length > 0 ? attribute.ConstructorArguments[0].Value as string : null); + } - return (tags, requireAuthorization, authorizationPolicies, disableAntiforgery); + return (displayName, description); } - private static void GetAdditionalRequestHandlerAttributeValues( + private static EndpointConfiguration GetEndpointConfiguration( ImmutableArray attributes, - ref EquatableImmutableArray? tags, - ref bool requireAuthorization, - ref EquatableImmutableArray? authorizationPolicies, - ref bool disableAntiforgery + string? name, + string? displayName, + string? description, + bool enforceMethodRequireAuthorizationRules ) { + var state = new EndpointAttributeState(); + + GetAdditionalRequestHandlerAttributeValues(attributes, ref state); + + if (enforceMethodRequireAuthorizationRules && state is { HasRequireAuthorizationAttribute: true, HasAllowAnonymousAttribute: false }) + state.AllowAnonymous = false; + + var metadata = new RequestHandlerMetadata(name, displayName, state.Summary, description, state.Tags, ToEquatableOrNull(state.Accepts), + ToEquatableOrNull(state.Produces), ToEquatableOrNull(state.ProducesProblem), ToEquatableOrNull(state.ProducesValidationProblem), + state.ExcludeFromDescription ?? false + ); + + var withRequestTimeout = state.WithRequestTimeout ?? false; + var requestTimeoutPolicyName = withRequestTimeout ? state.RequestTimeoutPolicyName : null; + + return new EndpointConfiguration(metadata, state.RequireAuthorization ?? false, state.AuthorizationPolicies, state.DisableAntiforgery ?? false, + state.AllowAnonymous ?? false, state.RequireCors ?? false, state.CorsPolicyName, state.RequiredHosts, state.RequireRateLimiting ?? false, + state.RateLimitingPolicyName, ToEquatableOrNull(state.EndpointFilters), state.ShortCircuit ?? false, state.DisableValidation ?? false, + state.DisableRequestTimeout ?? false, withRequestTimeout, requestTimeoutPolicyName, state.Order, state.EndpointGroupName + ); + } + + private static void GetAdditionalRequestHandlerAttributeValues(ImmutableArray attributes, ref EndpointAttributeState state) + { + ref var tags = ref state.Tags; + ref var requireAuthorization = ref state.RequireAuthorization; + ref var authorizationPolicies = ref state.AuthorizationPolicies; + ref var disableAntiforgery = ref state.DisableAntiforgery; + ref var allowAnonymous = ref state.AllowAnonymous; + ref var excludeFromDescription = ref state.ExcludeFromDescription; + ref var accepts = ref state.Accepts; + ref var produces = ref state.Produces; + ref var producesProblem = ref state.ProducesProblem; + ref var producesValidationProblem = ref state.ProducesValidationProblem; + ref var requireCors = ref state.RequireCors; + ref var corsPolicyName = ref state.CorsPolicyName; + ref var requiredHosts = ref state.RequiredHosts; + ref var requireRateLimiting = ref state.RequireRateLimiting; + ref var rateLimitingPolicyName = ref state.RateLimitingPolicyName; + ref var endpointFilters = ref state.EndpointFilters; + ref var endpointFilterSet = ref state.EndpointFilterSet; + ref var hasAllowAnonymousAttribute = ref state.HasAllowAnonymousAttribute; + ref var hasRequireAuthorizationAttribute = ref state.HasRequireAuthorizationAttribute; + ref var shortCircuit = ref state.ShortCircuit; + ref var disableValidation = ref state.DisableValidation; + ref var disableRequestTimeout = ref state.DisableRequestTimeout; + ref var withRequestTimeout = ref state.WithRequestTimeout; + ref var requestTimeoutPolicyName = ref state.RequestTimeoutPolicyName; + ref var order = ref state.Order; + ref var endpointGroupName = ref state.EndpointGroupName; + ref var summary = ref state.Summary; + foreach (var attribute in attributes) { var attributeClass = attribute.AttributeClass; if (attributeClass is null) continue; - var fullyQualifiedName = attributeClass.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - - switch (fullyQualifiedName) + switch (GetGeneratedAttributeKind(attributeClass)) { - case "global::Microsoft.AspNetCore.Http.TagsAttribute": + case GeneratedAttributeKind.ShortCircuit: + shortCircuit = true; + continue; + case GeneratedAttributeKind.DisableValidation: + disableValidation = true; + continue; + case GeneratedAttributeKind.DisableRequestTimeout: + disableRequestTimeout = true; + withRequestTimeout = false; + requestTimeoutPolicyName = null; + continue; + case GeneratedAttributeKind.RequestTimeout: + { + disableRequestTimeout = false; + withRequestTimeout = true; + + string? policyName = null; + if (attribute.ConstructorArguments.Length > 0) + policyName = attribute.ConstructorArguments[0].Value as string; + + policyName ??= GetNamedStringValue(attribute, PolicyNameAttributeNamedParameter); + requestTimeoutPolicyName = NormalizeOptionalString(policyName); + continue; + } + case GeneratedAttributeKind.Order: + if (attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is int orderValue) + order = orderValue; + continue; + case GeneratedAttributeKind.MapGroup: + { + var groupName = GetNamedStringValue(attribute, NameAttributeNamedParameter); + if (!string.IsNullOrEmpty(groupName)) + endpointGroupName = groupName; + continue; + } + case GeneratedAttributeKind.Summary: if (attribute.ConstructorArguments.Length > 0) { - var arg = attribute.ConstructorArguments[0]; - if (arg.Values.Length > 0) - { - var values = arg.Values - .Select(v => v.Value as string) - .Where(s => !string.IsNullOrWhiteSpace(s)) - .Select(s => s!.Trim()); - - MergeInto(ref tags, values); - } + var summaryValue = NormalizeOptionalString(attribute.ConstructorArguments[0].Value as string); + if (!string.IsNullOrEmpty(summaryValue)) + summary = summaryValue; } - break; - case $"global::{RequireAuthorizationAttributeFullyQualifiedName}": + continue; + case GeneratedAttributeKind.Accepts: + TryAddAcceptsMetadata(attribute, attributeClass, ref accepts); + continue; + case GeneratedAttributeKind.ProducesResponse: + TryAddProducesMetadata(attribute, attributeClass, ref produces); + continue; + case GeneratedAttributeKind.RequireAuthorization: requireAuthorization = true; + hasRequireAuthorizationAttribute = true; if (attribute.ConstructorArguments.Length == 1) { var arg = attribute.ConstructorArguments[0]; - if (arg.Values.Length > 0) - { - var values = arg.Values - .Select(v => v.Value as string) - .Where(s => !string.IsNullOrWhiteSpace(s)) - .Select(s => s!.Trim()); - - MergeInto(ref authorizationPolicies, values); - } + MergeInto(ref authorizationPolicies, arg.Values); } - break; - case $"global::{DisableAntiforgeryAttributeFullyQualifiedName}": + + continue; + case GeneratedAttributeKind.RequireCors: + requireCors = true; + corsPolicyName = attribute.ConstructorArguments.Length > 0 + ? NormalizeOptionalString(attribute.ConstructorArguments[0].Value as string) + : null; + continue; + case GeneratedAttributeKind.RequireHost: + if (attribute.ConstructorArguments.Length == 1) + { + var arg = attribute.ConstructorArguments[0]; + if (arg is { Kind: TypedConstantKind.Array, Values.Length: > 0 }) + MergeInto(ref requiredHosts, arg.Values); + else if (arg.Value is string singleHost && !string.IsNullOrWhiteSpace(singleHost)) + MergeInto(ref requiredHosts, [singleHost.Trim()]); + } + + continue; + case GeneratedAttributeKind.RequireRateLimiting: + { + var policyName = attribute.ConstructorArguments.Length > 0 + ? NormalizeOptionalString(attribute.ConstructorArguments[0].Value as string) + : null; + + if (!string.IsNullOrEmpty(policyName)) + { + requireRateLimiting = true; + rateLimitingPolicyName = policyName; + } + + continue; + } + case GeneratedAttributeKind.EndpointFilter: + TryAddEndpointFilter(attribute, attributeClass, ref endpointFilters, ref endpointFilterSet); + continue; + case GeneratedAttributeKind.DisableAntiforgery: disableAntiforgery = true; - break; + continue; + case GeneratedAttributeKind.ProducesProblem: + { + var statusCode = attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is int producesProblemStatusCode + ? producesProblemStatusCode + : 500; + var contentType = attribute.ConstructorArguments.Length > 1 + ? NormalizeOptionalContentType(attribute.ConstructorArguments[1].Value as string) + : null; + var additionalContentTypes = attribute.ConstructorArguments.Length > 2 ? GetStringArrayValues(attribute.ConstructorArguments[2]) : null; + + var producesProblemList = producesProblem ??= []; + producesProblemList.Add(new ProducesProblemMetadata(statusCode, contentType, additionalContentTypes)); + continue; + } + case GeneratedAttributeKind.ProducesValidationProblem: + { + var statusCode = + attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is int producesValidationProblemStatusCode + ? producesValidationProblemStatusCode + : 400; + var contentType = attribute.ConstructorArguments.Length > 1 + ? NormalizeOptionalContentType(attribute.ConstructorArguments[1].Value as string) + : null; + var additionalContentTypes = attribute.ConstructorArguments.Length > 2 ? GetStringArrayValues(attribute.ConstructorArguments[2]) : null; + + var producesValidationProblemList = producesValidationProblem ??= []; + producesValidationProblemList.Add(new ProducesValidationProblemMetadata(statusCode, contentType, additionalContentTypes)); + continue; + } + } + + if (IsAttribute(attributeClass, AllowAnonymousAttributeName, AspNetCoreAuthorizationNamespaceParts)) + { + allowAnonymous = true; + hasAllowAnonymousAttribute = true; + continue; } + + if (IsAttribute(attributeClass, "TagsAttribute", AspNetCoreHttpNamespaceParts)) + { + if (attribute.ConstructorArguments.Length > 0) + { + var arg = attribute.ConstructorArguments[0]; + MergeInto(ref tags, arg.Values); + } + + continue; + } + + if (IsAttribute(attributeClass, "ExcludeFromDescriptionAttribute", AspNetCoreRoutingNamespaceParts)) + excludeFromDescription = true; } } @@ -464,23 +438,344 @@ private static void MergeInto(ref EquatableImmutableArray? target, IEnum target = merged.Count > 0 ? merged : null; } + private static void MergeInto(ref EquatableImmutableArray? target, ImmutableArray values) + { + if (values.IsDefaultOrEmpty) + return; + + List? normalized = null; + foreach (var value in values) + { + if (value.Value is not string stringValue) + continue; + + var trimmed = NormalizeOptionalString(stringValue); + if (trimmed is not { Length: > 0 }) + continue; + + normalized ??= new List(values.Length); + normalized.Add(trimmed); + } + + if (normalized is { Count: > 0 }) + MergeInto(ref target, normalized); + } + + private static EquatableImmutableArray? ToEquatableOrNull(List? values) + { + return values is { Count: > 0 } ? values.ToEquatableImmutableArray() : null; + } + + private static string NormalizeRequiredContentType(string? contentType, string defaultValue) + { + return string.IsNullOrWhiteSpace(contentType) ? defaultValue : contentType!.Trim(); + } + + private static string? NormalizeOptionalContentType(string? contentType) + { + return string.IsNullOrWhiteSpace(contentType) ? null : contentType!.Trim(); + } + + private static string? NormalizeOptionalString(string? value) + { + return string.IsNullOrWhiteSpace(value) ? null : value!.Trim(); + } + + [SuppressMessage("Major Code Smell", "S3398:Move this method into a class of its own", Justification = "Shared helper for multiple caching paths.")] + private static string? GetMapGroupPattern(INamedTypeSymbol classSymbol) + { + foreach (var attribute in classSymbol.GetAttributes()) + { + var attributeClass = attribute.AttributeClass; + if (attributeClass is null) + continue; + + if (GetGeneratedAttributeKind(attributeClass) != GeneratedAttributeKind.MapGroup) + continue; + + if (attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is string pattern) + return pattern.Trim(); + } + + return null; + } + + [SuppressMessage("Major Code Smell", "S3398:Move this method into a class of its own", Justification = "Shared helper for multiple caching paths.")] + private static string GetMapGroupIdentifier(string className) + { + if (className.StartsWith(GlobalPrefix, StringComparison.Ordinal)) + className = className.Substring(GlobalPrefix.Length); + + var builder = StringBuilderPool.Get(className.Length + 8); + builder.Append('_'); + + foreach (var character in className) + builder.Append(char.IsLetterOrDigit(character) ? character : '_'); + + builder.Append("_Group"); + return StringBuilderPool.ToStringAndReturn(builder); + } + + private static EquatableImmutableArray? GetStringArrayValues(TypedConstant typedConstant) + { + if (typedConstant.Kind != TypedConstantKind.Array || typedConstant.Values.IsDefaultOrEmpty) + return null; + + var builder = ImmutableArray.CreateBuilder(typedConstant.Values.Length); + foreach (var value in typedConstant.Values) + { + if (value.Value is string s && !string.IsNullOrWhiteSpace(s)) + builder.Add(s.Trim()); + } + + return builder.Count > 0 ? builder.ToEquatableImmutable() : null; + } + + private static GeneratedAttributeKind GetGeneratedAttributeKind(INamedTypeSymbol attributeClass) + { + var definition = attributeClass.OriginalDefinition; + var cacheEntry = + GeneratedAttributeKindCache.GetValue(definition, static def => new GeneratedAttributeKindCacheEntry(GetGeneratedAttributeKindCore(def))); + + return cacheEntry.Kind; + } + + private static GeneratedAttributeKind GetGeneratedAttributeKindCore(INamedTypeSymbol definition) + { + if (!IsInNamespace(definition.ContainingNamespace, AttributesNamespaceParts)) + return GeneratedAttributeKind.None; + + return definition.Name switch + { + ShortCircuitAttributeName => GeneratedAttributeKind.ShortCircuit, + DisableValidationAttributeName => GeneratedAttributeKind.DisableValidation, + DisableRequestTimeoutAttributeName => GeneratedAttributeKind.DisableRequestTimeout, + RequestTimeoutAttributeName => GeneratedAttributeKind.RequestTimeout, + OrderAttributeName => GeneratedAttributeKind.Order, + MapGroupAttributeName => GeneratedAttributeKind.MapGroup, + SummaryAttributeName => GeneratedAttributeKind.Summary, + AcceptsAttributeName => GeneratedAttributeKind.Accepts, + ProducesResponseAttributeName => GeneratedAttributeKind.ProducesResponse, + RequireAuthorizationAttributeName => GeneratedAttributeKind.RequireAuthorization, + RequireCorsAttributeName => GeneratedAttributeKind.RequireCors, + RequireHostAttributeName => GeneratedAttributeKind.RequireHost, + RequireRateLimitingAttributeName => GeneratedAttributeKind.RequireRateLimiting, + EndpointFilterAttributeName => GeneratedAttributeKind.EndpointFilter, + DisableAntiforgeryAttributeName => GeneratedAttributeKind.DisableAntiforgery, + ProducesProblemAttributeName => GeneratedAttributeKind.ProducesProblem, + ProducesValidationProblemAttributeName => GeneratedAttributeKind.ProducesValidationProblem, + _ => GeneratedAttributeKind.None, + }; + } + + private static bool IsAttribute(INamedTypeSymbol attributeClass, string attributeName, string[] namespaceParts) + { + var definition = attributeClass.OriginalDefinition; + return definition.Name == attributeName && IsInNamespace(definition.ContainingNamespace, namespaceParts); + } + + private static BindingSource GetBindingSourceFromAttributeClass(INamedTypeSymbol attributeClass) + { + var definition = attributeClass.OriginalDefinition; + var namespaceSymbol = definition.ContainingNamespace; + + return definition.Name switch + { + "FromRouteAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreMvcNamespaceParts) => BindingSource.FromRoute, + "FromQueryAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreMvcNamespaceParts) => BindingSource.FromQuery, + "FromHeaderAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreMvcNamespaceParts) => BindingSource.FromHeader, + "FromBodyAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreMvcNamespaceParts) => BindingSource.FromBody, + "FromFormAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreMvcNamespaceParts) => BindingSource.FromForm, + "FromServicesAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreMvcNamespaceParts) => BindingSource.FromServices, + "FromKeyedServicesAttribute" when IsInNamespace(namespaceSymbol, ExtensionsDependencyInjectionNamespaceParts) + => BindingSource.FromKeyedServices, + "AsParametersAttribute" when IsInNamespace(namespaceSymbol, AspNetCoreHttpNamespaceParts) => BindingSource.AsParameters, + _ => BindingSource.None, + }; + } + + private static bool IsInNamespace(INamespaceSymbol? namespaceSymbol, string[] namespaceParts) + { + for (var i = namespaceParts.Length - 1; i >= 0; i--) + { + if (namespaceSymbol is null || namespaceSymbol.Name != namespaceParts[i]) + return false; + + namespaceSymbol = namespaceSymbol.ContainingNamespace; + } + + return namespaceSymbol is null || namespaceSymbol.IsGlobalNamespace; + } + + private static void TryAddAcceptsMetadata(AttributeData attribute, INamedTypeSymbol attributeClass, ref List? accepts) + { + string? requestType; + string contentType; + EquatableImmutableArray? additionalContentTypes; + var isOptional = GetNamedBoolValue(attribute, IsOptionalAttributeNamedParameter); + + if (attributeClass is { IsGenericType: true, TypeArguments.Length: 1 }) + { + requestType = attributeClass.TypeArguments[0] + .ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + contentType = attribute.ConstructorArguments.Length > 0 + ? NormalizeRequiredContentType(attribute.ConstructorArguments[0].Value as string, "application/json") + : "application/json"; + additionalContentTypes = attribute.ConstructorArguments.Length > 1 ? GetStringArrayValues(attribute.ConstructorArguments[1]) : null; + } + else if (GetNamedTypeSymbol(attribute, RequestTypeAttributeNamedParameter) is { } requestTypeSymbol) + { + requestType = requestTypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + contentType = attribute.ConstructorArguments.Length > 0 + ? NormalizeRequiredContentType(attribute.ConstructorArguments[0].Value as string, "application/json") + : "application/json"; + additionalContentTypes = attribute.ConstructorArguments.Length > 1 ? GetStringArrayValues(attribute.ConstructorArguments[1]) : null; + } + else + { + return; + } + + var acceptsList = accepts ??= []; + acceptsList.Add(new AcceptsMetadata(requestType, contentType, additionalContentTypes, isOptional)); + } + + private static void TryAddProducesMetadata(AttributeData attribute, INamedTypeSymbol attributeClass, ref List? produces) + { + string? responseType; + int statusCode; + string? contentType; + EquatableImmutableArray? additionalContentTypes; + + if (attributeClass is { IsGenericType: true, TypeArguments.Length: 1 }) + { + responseType = attributeClass.TypeArguments[0] + .ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + statusCode = attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is int producesStatusCode + ? producesStatusCode + : 200; + contentType = attribute.ConstructorArguments.Length > 1 ? NormalizeOptionalContentType(attribute.ConstructorArguments[1].Value as string) : null; + additionalContentTypes = attribute.ConstructorArguments.Length > 2 ? GetStringArrayValues(attribute.ConstructorArguments[2]) : null; + } + else if (GetNamedTypeSymbol(attribute, ResponseTypeAttributeNamedParameter) is { } responseTypeSymbol) + { + responseType = responseTypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + statusCode = attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is int producesStatusCode + ? producesStatusCode + : 200; + contentType = attribute.ConstructorArguments.Length > 1 ? NormalizeOptionalContentType(attribute.ConstructorArguments[1].Value as string) : null; + additionalContentTypes = attribute.ConstructorArguments.Length > 2 ? GetStringArrayValues(attribute.ConstructorArguments[2]) : null; + } + else + { + return; + } + + var producesList = produces ??= []; + producesList.Add(new ProducesMetadata(responseType, statusCode, contentType, additionalContentTypes)); + } + + private static void TryAddEndpointFilter( + AttributeData attribute, + INamedTypeSymbol attributeClass, + ref List? endpointFilters, + ref HashSet? endpointFilterSet) + { + if (attributeClass is { IsGenericType: true, TypeArguments.Length: 1 }) + { + TryAddEndpointFilterType(attributeClass.TypeArguments[0], ref endpointFilters, ref endpointFilterSet); + return; + } + + if (attribute.ConstructorArguments.Length == 0) + return; + + if (attribute.ConstructorArguments[0].Value is ITypeSymbol filterTypeSymbol) + TryAddEndpointFilterType(filterTypeSymbol, ref endpointFilters, ref endpointFilterSet); + } + + private static void TryAddEndpointFilterType( + ITypeSymbol? typeSymbol, + ref List? endpointFilters, + ref HashSet? endpointFilterSet) + { + if (typeSymbol is null or ITypeParameterSymbol or IErrorTypeSymbol) + return; + + var displayString = typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + if (string.IsNullOrWhiteSpace(displayString)) + return; + + endpointFilterSet ??= new HashSet(StringComparer.Ordinal); + if (!endpointFilterSet.Add(displayString)) + return; + + endpointFilters ??= []; + endpointFilters.Add(displayString); + } + + private static ITypeSymbol? GetNamedTypeSymbol(AttributeData attribute, string namedParameter) + { + foreach (var namedArg in attribute.NamedArguments) + { + if (namedArg.Key == namedParameter && namedArg.Value.Value is ITypeSymbol typeSymbol) + return typeSymbol; + } + + return null; + } + + private static bool GetNamedBoolValue(AttributeData attribute, string namedParameter, bool defaultValue = false) + { + foreach (var namedArg in attribute.NamedArguments) + { + if (namedArg.Key == namedParameter && namedArg.Value.Value is bool boolValue) + return boolValue; + } + + return defaultValue; + } + + private static string? GetNamedStringValue(AttributeData attribute, string namedParameter) + { + foreach (var namedArg in attribute.NamedArguments) + { + if (namedArg.Key == namedParameter && namedArg.Value.Value is string stringValue) + return NormalizeOptionalString(stringValue); + } + + return null; + } + private static EquatableImmutableArray MergeUnion(EquatableImmutableArray? existing, IEnumerable values) { - var list = new List(); + List? list = null; + HashSet? seen = null; if (existing is { Count: > 0 }) + { + var count = existing.Value.Count; + list = new List(count + 4); list.AddRange(existing.Value); + seen = new HashSet(existing.Value, StringComparer.OrdinalIgnoreCase); + } foreach (var value in values) { - if (string.IsNullOrWhiteSpace(value)) + var normalized = NormalizeOptionalString(value); + if (normalized is not { Length: > 0 }) continue; - var trimmed = value.Trim(); - if (!list.Contains(trimmed, StringComparer.OrdinalIgnoreCase)) - list.Add(trimmed); + + seen ??= new HashSet(StringComparer.OrdinalIgnoreCase); + if (!seen.Add(normalized)) + continue; + + list ??= []; + + list.Add(normalized); } - return list.ToEquatableImmutableArray(); + return list?.ToEquatableImmutableArray() ?? EquatableImmutableArray.Empty; } private static RequestHandlerMethod GetRequestHandlerMethod(IMethodSymbol methodSymbol, CancellationToken cancellationToken) @@ -497,10 +792,7 @@ private static RequestHandlerMethod GetRequestHandlerMethod(IMethodSymbol method return requestHandlerMethod; } - private static (INamedTypeSymbol RequestHandlerClassSymbol, RequestHandlerClass RequestHandlerClass)? GetRequestHandlerClass( - IMethodSymbol methodSymbol, - CancellationToken cancellationToken - ) + private static RequestHandlerClass? GetRequestHandlerClass(IMethodSymbol methodSymbol, Compilation compilation, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -508,78 +800,358 @@ CancellationToken cancellationToken if (classSymbol.TypeKind != TypeKind.Class) return null; - var name = classSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - var isStatic = classSymbol.IsStatic; + var typeCache = GetCompilationTypeCache(compilation); + var cacheEntry = RequestHandlerClassCache.GetValue(classSymbol, static _ => new RequestHandlerClassCacheEntry()); + var requestHandlerClass = cacheEntry.GetOrCreate(classSymbol, typeCache, cancellationToken); + return requestHandlerClass; + } + + private static CompilationTypeCache GetCompilationTypeCache(Compilation compilation) + { + return CompilationTypeCaches.GetValue(compilation, static c => new CompilationTypeCache(c)); + } + + [SuppressMessage("Major Code Smell", "S3398:Move this method into a class of its own", Justification = "Shared helper reused by caching infrastructure.")] + private static ConfigureMethodDetails GetConfigureMethodDetails( + INamedTypeSymbol classSymbol, + INamedTypeSymbol? endpointConventionBuilderSymbol, + INamedTypeSymbol? serviceProviderSymbol, + CancellationToken cancellationToken + ) + { + cancellationToken.ThrowIfCancellationRequested(); + + var hasConfigureMethod = false; + var acceptsServiceProvider = false; + foreach (var member in classSymbol.GetMembers(ConfigureMethodName)) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (member is not IMethodSymbol methodSymbol) + continue; + + if (IsConfigureMethod(methodSymbol, endpointConventionBuilderSymbol, serviceProviderSymbol, out var methodAcceptsServiceProvider)) + { + hasConfigureMethod = true; + if (methodAcceptsServiceProvider) + { + acceptsServiceProvider = true; + break; + } + } + } + + return new ConfigureMethodDetails(hasConfigureMethod, acceptsServiceProvider); + } + + private static bool IsConfigureMethod( + IMethodSymbol methodSymbol, + INamedTypeSymbol? endpointConventionBuilderSymbol, + INamedTypeSymbol? serviceProviderSymbol, + out bool acceptsServiceProvider + ) + { + acceptsServiceProvider = false; + + if (!methodSymbol.IsStatic) + return false; + + if (methodSymbol.TypeParameters.Length != 1) + return false; + + if (methodSymbol.Parameters.Length is < 1 or > 2) + return false; + + var builderTypeParameter = methodSymbol.TypeParameters[0]; + var builderParameter = methodSymbol.Parameters[0]; + + if (!SymbolEqualityComparer.Default.Equals(builderParameter.Type, builderTypeParameter)) + return false; + + if (methodSymbol.Parameters.Length == 2) + { + var serviceProviderParameter = methodSymbol.Parameters[1]; + if (!IsServiceProviderParameter(serviceProviderParameter.Type, serviceProviderSymbol)) + return false; + + acceptsServiceProvider = true; + } + + if (!methodSymbol.ReturnsVoid) + return false; + + if (!HasEndpointConventionBuilderConstraint(builderTypeParameter, methodSymbol, endpointConventionBuilderSymbol)) + return false; + + return true; + } + + private static bool IsServiceProviderParameter(ITypeSymbol typeSymbol, INamedTypeSymbol? serviceProviderSymbol) + { + if (serviceProviderSymbol is not null) + return SymbolEqualityComparer.Default.Equals(typeSymbol, serviceProviderSymbol); + + return MatchesServiceProvider(typeSymbol); + } + + private static bool HasEndpointConventionBuilderConstraint( + ITypeParameterSymbol builderTypeParameter, + IMethodSymbol methodSymbol, + INamedTypeSymbol? endpointConventionBuilderSymbol + ) + { + var symbolMatches = builderTypeParameter.ConstraintTypes.Any(constraint => + endpointConventionBuilderSymbol is not null + ? SymbolEqualityComparer.Default.Equals(constraint, endpointConventionBuilderSymbol) + : MatchesEndpointConventionBuilder(constraint) + ); + + if (symbolMatches) + return true; + + return methodSymbol.DeclaringSyntaxReferences + .Select(reference => reference.GetSyntax()) + .OfType() + .SelectMany(methodSyntax => methodSyntax.ConstraintClauses) + .Where(clause => string.Equals(clause.Name.Identifier.ValueText, builderTypeParameter.Name, StringComparison.Ordinal)) + .SelectMany(clause => clause.Constraints.OfType()) + .Any(constraint => IsEndpointConventionBuilderIdentifier(constraint.Type)); + } + + private static bool IsEndpointConventionBuilderIdentifier(TypeSyntax typeSyntax) + { + return typeSyntax switch + { + QualifiedNameSyntax qualified => IsEndpointConventionBuilderIdentifier(qualified.Right), + AliasQualifiedNameSyntax alias => IsEndpointConventionBuilderIdentifier(alias.Name), + SimpleNameSyntax simple => string.Equals(simple.Identifier.ValueText, "IEndpointConventionBuilder", StringComparison.Ordinal), + _ => false, + }; + } + + private static bool MatchesEndpointConventionBuilder(ITypeSymbol typeSymbol) + { + if (typeSymbol is not INamedTypeSymbol namedType) + return false; + + if (!string.Equals(namedType.Name, "IEndpointConventionBuilder", StringComparison.Ordinal)) + return false; + + var containingNamespace = namedType.ContainingNamespace?.ToDisplayString() ?? string.Empty; + return string.Equals(containingNamespace, "Microsoft.AspNetCore.Builder", StringComparison.Ordinal); + } + + private static bool MatchesServiceProvider(ITypeSymbol typeSymbol) + { + if (typeSymbol is not INamedTypeSymbol namedType) + return false; + + if (!string.Equals(namedType.Name, "IServiceProvider", StringComparison.Ordinal)) + return false; + + var containingNamespace = namedType.ContainingNamespace?.ToDisplayString() ?? string.Empty; + return string.Equals(containingNamespace, "System", StringComparison.Ordinal); + } + + private static EquatableImmutableArray GetRequestHandlerParameters(IMethodSymbol methodSymbol, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var methodParameters = ImmutableArray.CreateBuilder(methodSymbol.Parameters.Length); + foreach (var parameter in methodSymbol.Parameters) + { + cancellationToken.ThrowIfCancellationRequested(); + + var source = BindingSource.None; + TypedConstant? typedKey = null; + string? bindingName = null; + + foreach (var attribute in parameter.GetAttributes()) + { + var attributeClass = attribute.AttributeClass; + if (attributeClass is null) + continue; + + var attributeSource = GetBindingSourceFromAttributeClass(attributeClass); + if (attributeSource == BindingSource.None) + continue; + + source = attributeSource; + switch (attributeSource) + { + case BindingSource.FromRoute: + case BindingSource.FromQuery: + case BindingSource.FromHeader: + case BindingSource.FromForm: + bindingName = GetBindingAttributeName(attribute) ?? bindingName; + break; + case BindingSource.FromKeyedServices: + typedKey = attribute.ConstructorArguments.Length > 0 ? attribute.ConstructorArguments[0] : null; + break; + } + } + + var parameterName = parameter.Name; + var parameterType = parameter.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var key = typedKey.HasValue ? ConstLiteral(typedKey.Value) : null; + var bindingPrefix = GetBindingSourceAttribute(source, key, bindingName); + methodParameters.Add(new Parameter(parameterName, parameterType, bindingPrefix)); + } + + return methodParameters.ToEquatableImmutable(); + } + + private static string? GetBindingAttributeName(AttributeData attribute) + { + foreach (var namedArg in attribute.NamedArguments) + { + if (string.Equals(namedArg.Key, NameAttributeNamedParameter, StringComparison.Ordinal) && namedArg.Value.Value is string namedValue) + { + var normalized = NormalizeBindingName(namedValue); + if (normalized is not null) + return normalized; + } + } + + if (attribute.ConstructorArguments.Length > 0 && attribute.ConstructorArguments[0].Value is string constructorName) + return NormalizeBindingName(constructorName); + + return null; + } + + private static string? NormalizeBindingName(string? value) + { + if (string.IsNullOrWhiteSpace(value)) + return null; + + var trimmed = value!.Trim(); + return trimmed.Length > 0 ? trimmed : null; + } + + private static void GenerateSource(SourceProductionContext context, ImmutableArray requestHandlers) + { + context.CancellationToken.ThrowIfCancellationRequested(); + + var sorted = SortRequestHandlers(requestHandlers); + sorted = EnsureUniqueEndpointNames(sorted); + + GenerateAddEndpointHandlersClass(context, sorted); + GenerateUseEndpointHandlersClass(context, sorted); + } - var requestHandlerClass = new RequestHandlerClass(name, isStatic); + private static ImmutableArray SortRequestHandlers(ImmutableArray requestHandlers) + { + if (requestHandlers.Length <= 1) + return requestHandlers; + + var array = requestHandlers.ToArray(); + Array.Sort(array, RequestHandlerComparer.Instance); + return [..array]; + } + + private static ImmutableArray EnsureUniqueEndpointNames(ImmutableArray requestHandlers) + { + var collidingHandlers = GetRequestHandlersWithNameCollisions(requestHandlers); + if (collidingHandlers.IsEmpty) + return requestHandlers; + + var builder = requestHandlers.ToBuilder(); + foreach (var index in collidingHandlers) + { + var handler = builder[index]; + var configuration = handler.Configuration; + var metadata = configuration.Metadata with + { + Name = GetFullyQualifiedMethodDisplayName(handler), + }; + configuration = configuration with + { + Metadata = metadata, + }; + builder[index] = handler with + { + Configuration = configuration, + }; + } - return (classSymbol, requestHandlerClass); + return builder.MoveToImmutable(); } - private static EquatableImmutableArray GetRequestHandlerParameters(IMethodSymbol methodSymbol, CancellationToken cancellationToken) + private static ImmutableArray GetRequestHandlersWithNameCollisions(ImmutableArray requestHandlers) { - cancellationToken.ThrowIfCancellationRequested(); - - var methodParameters = new List(); - foreach (var parameter in methodSymbol.Parameters) - { - cancellationToken.ThrowIfCancellationRequested(); + if (requestHandlers.IsDefaultOrEmpty) + return ImmutableArray.Empty; - var source = BindingSource.None; - TypedConstant? typedKey = null; + var handlerCount = requestHandlers.Length; + var nameToFirstIndex = new Dictionary<(string Name, string Method), int>(handlerCount); + var collisionFlags = ArrayPool.Shared.Rent(handlerCount); + Array.Clear(collisionFlags, 0, handlerCount); + List? collidingIndices = null; - var attributes = parameter.GetAttributes(); - foreach (var attribute in attributes) + try + { + for (var index = 0; index < handlerCount; index++) { - var attributeClass = attribute.AttributeClass; - if (attributeClass is null) + var handler = requestHandlers[index]; + var name = handler.Configuration.Metadata.Name; + if (string.IsNullOrEmpty(name)) continue; - if (attributeClass.IsFromRouteAttribute()) - source = BindingSource.FromRoute; - if (attributeClass.IsFromQueryAttribute()) - source = BindingSource.FromQuery; - if (attributeClass.IsFromHeaderAttribute()) - source = BindingSource.FromHeader; - if (attributeClass.IsFromBodyAttribute()) - source = BindingSource.FromBody; - if (attributeClass.IsFromFormAttribute()) - source = BindingSource.FromForm; - if (attributeClass.IsFromServicesAttribute()) - source = BindingSource.FromServices; - if (attributeClass.IsFromKeyedServicesAttribute()) + var key = (name!, handler.Method.Name); + + if (nameToFirstIndex.TryGetValue(key, out var firstIndex)) + { + MarkCollision(firstIndex); + MarkCollision(index); + } + else { - source = BindingSource.FromKeyedServices; - typedKey = attribute.ConstructorArguments.Length > 0 ? attribute.ConstructorArguments[0] : null; + nameToFirstIndex.Add(key, index); } - if (attributeClass.IsAsParametersAttribute()) - source = BindingSource.AsParameters; } - var parameterName = parameter.Name; - var parameterType = parameter.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); - var key = typedKey.HasValue ? ConstLiteral(typedKey.Value) : null; - methodParameters.Add(new Parameter(parameterName, parameterType, source, key)); + if (collidingIndices is null || collidingIndices.Count == 0) + return ImmutableArray.Empty; + + collidingIndices.Sort(); + var builder = ImmutableArray.CreateBuilder(collidingIndices.Count); + builder.AddRange(collidingIndices); + return builder.MoveToImmutable(); } + finally + { + ArrayPool.Shared.Return(collisionFlags); + } + + void MarkCollision(int handlerIndex) + { + if (collisionFlags[handlerIndex]) + return; - return methodParameters.ToEquatableImmutableArray(); + collisionFlags[handlerIndex] = true; + collidingIndices ??= new List(); + collidingIndices.Add(handlerIndex); + } } - private static void GenerateSource(SourceProductionContext context, ImmutableArray requestHandlers) + private static string GetFullyQualifiedMethodDisplayName(RequestHandler requestHandler) { - var sorted = requestHandlers.OrderBy(r => r.Class.Name, StringComparer.Ordinal) - .ThenBy(r => r.Method.Name, StringComparer.Ordinal) - .ThenBy(r => r.HttpMethod, StringComparer.Ordinal) - .ThenBy(r => r.Pattern, StringComparer.Ordinal) - .ToImmutableArray(); + var className = requestHandler.Class.Name; + if (className.StartsWith(GlobalPrefix, StringComparison.Ordinal)) + className = className.Substring(GlobalPrefix.Length); - GenerateAddEndpointHandlersClass(context, sorted); - GenerateUseEndpointHandlersClass(context, sorted); + if (className.IndexOf('+') >= 0) + className = className.Replace('+', '.'); + + return string.Concat(className, ".", requestHandler.Method.Name); } private static void GenerateAddEndpointHandlersClass(SourceProductionContext context, ImmutableArray requestHandlers) { - var source = GetAddEndpointHandlersStringBuilder(requestHandlers); + context.CancellationToken.ThrowIfCancellationRequested(); + + var nonStaticClassNames = GetDistinctNonStaticClassNames(requestHandlers); + var source = GetAddEndpointHandlersStringBuilder(nonStaticClassNames); source.AppendLine(FileHeader); source.AppendLine(); @@ -606,11 +1178,9 @@ private static void GenerateAddEndpointHandlersClass(SourceProductionContext con source.AppendLine(" {"); - foreach (var className in requestHandlers.Where(requestHandler => !requestHandler.Class.IsStatic) - .Select(x => x.Class.Name) - .Distinct()) + foreach (var className in nonStaticClassNames) { - source.Append(" services.TryAddTransient<"); + source.Append(" services.TryAddScoped<"); source.Append(className); source.Append(">();"); source.AppendLine(); @@ -622,41 +1192,65 @@ private static void GenerateAddEndpointHandlersClass(SourceProductionContext con """ ); - context.AddSource(AddEndpointHandlersMethodHint, SourceText.From(source.ToString(), Encoding.UTF8)); + var sourceText = StringBuilderPool.ToStringAndReturn(source); + context.AddSource(AddEndpointHandlersMethodHint, SourceText.From(sourceText, Encoding.UTF8)); } - private static StringBuilder GetAddEndpointHandlersStringBuilder(ImmutableArray requestHandlers) + [SuppressMessage("Major Code Smell", "S3267:Loops should be simplified by calling the \"Select\" LINQ method", + Justification = "Manual loops avoid repeated allocations in the source generator." + )] + private static List GetDistinctNonStaticClassNames(ImmutableArray requestHandlers) { - var distinctHandlers = requestHandlers.Select(x => x.Class) - .Where(x => !x.IsStatic) - .Distinct() - .ToArray(); + var classNames = new List(); + if (requestHandlers.IsDefaultOrEmpty) + return classNames; + + var seen = new HashSet(StringComparer.Ordinal); + foreach (var requestHandler in requestHandlers) + { + if (requestHandler.Class.IsStatic) + continue; - var estimate = 512 + distinctHandlers.Sum(x => 36 + x.Name.Length); + var className = requestHandler.Class.Name; + if (seen.Add(className)) + classNames.Add(className); + } - estimate += Math.Max(256, distinctHandlers.Length * 12); - estimate = (int)(estimate * 1.10); + return classNames; + } - estimate = estimate switch - { - < 512 => 512, - > 8192 => 8192, - _ => estimate, - }; + private static StringBuilder GetAddEndpointHandlersStringBuilder(List nonStaticClassNames) + { + var estimate = 512L; + foreach (var className in nonStaticClassNames) + estimate += 36 + className.Length; + + estimate += Math.Max(256, nonStaticClassNames.Count * 12); + estimate = (long)(estimate * 1.10); + + if (estimate < 512) + estimate = 512; + else if (estimate > int.MaxValue) + estimate = int.MaxValue; - return new StringBuilder(estimate); + return StringBuilderPool.Get((int)estimate); } private static void GenerateUseEndpointHandlersClass(SourceProductionContext context, ImmutableArray requestHandlers) { + context.CancellationToken.ThrowIfCancellationRequested(); + var source = GetUseEndpointHandlersStringBuilder(requestHandlers); source.AppendLine(FileHeader); source.AppendLine(); source.AppendLine("using Microsoft.AspNetCore.Builder;"); + source.AppendLine("using Microsoft.AspNetCore.Http;"); source.AppendLine("using Microsoft.AspNetCore.Mvc;"); source.AppendLine("using Microsoft.AspNetCore.Routing;"); + if (HasRateLimitedHandlers(requestHandlers)) + source.AppendLine("using Microsoft.AspNetCore.RateLimiting;"); source.AppendLine("using Microsoft.Extensions.DependencyInjection;"); source.AppendLine(); @@ -678,6 +1272,22 @@ private static void GenerateUseEndpointHandlersClass(SourceProductionContext con source.AppendLine(" {"); + var groupedClasses = GetClassesWithMapGroups(requestHandlers); + + foreach (var groupedClass in groupedClasses) + { + source.Append(" var "); + source.Append(groupedClass.MapGroupBuilderIdentifier); + source.Append(" = builder.MapGroup("); + source.Append(StringLiteral(groupedClass.MapGroupPattern!)); + source.Append(')'); + AppendEndpointConfiguration(source, " ", groupedClass.Configuration, false); + source.AppendLine(";"); + } + + if (groupedClasses.Count > 0) + source.AppendLine(); + for (var index = 0; index < requestHandlers.Length; index++) { if (index > 0) @@ -695,22 +1305,89 @@ private static void GenerateUseEndpointHandlersClass(SourceProductionContext con """ ); - context.AddSource(UseEndpointHandlersMethodHint, SourceText.From(source.ToString(), Encoding.UTF8)); + var sourceText = StringBuilderPool.ToStringAndReturn(source); + context.AddSource(UseEndpointHandlersMethodHint, SourceText.From(sourceText, Encoding.UTF8)); + } + + private static bool HasRateLimitedHandlers(ImmutableArray requestHandlers) + { + foreach (var handler in requestHandlers) + { + if (handler.Configuration.RequireRateLimiting) + return true; + } + + return false; + } + + [SuppressMessage("Major Code Smell", "S3267:Loops should be simplified by calling the \"Select\" LINQ method", + Justification = "Manual loops avoid repeated allocations in the source generator." + )] + private static List GetClassesWithMapGroups(ImmutableArray requestHandlers) + { + var groupedClasses = new List(); + if (requestHandlers.IsDefaultOrEmpty) + return groupedClasses; + + var seen = new HashSet(StringComparer.Ordinal); + foreach (var handler in requestHandlers) + { + var handlerClass = handler.Class; + if (handlerClass.MapGroupPattern is null) + continue; + + if (seen.Add(handlerClass.Name)) + groupedClasses.Add(handlerClass); + } + + return groupedClasses; } private static void GenerateMapRequestHandler(StringBuilder source, RequestHandler requestHandler) { - source.Append(" "); - source.Append("builder.Map"); - source.Append(requestHandler.HttpMethod is "Get" or "Post" or "Put" or "Delete" or "Patch" ? requestHandler.HttpMethod : "Methods"); - source.Append('('); - source.Append(StringLiteral(requestHandler.Pattern)); - source.Append(", "); - if (requestHandler.HttpMethod is "OPTIONS" or "HEAD" or "TRACE" or "CONNECT") + var wrapWithConfigure = requestHandler.Class.HasConfigureMethod; + var configureAcceptsServiceProvider = requestHandler.Class.ConfigureMethodAcceptsServiceProvider; + var indent = wrapWithConfigure ? " " : " "; + var continuationIndent = indent + " "; + var routeBuilderIdentifier = requestHandler.Class.MapGroupBuilderIdentifier ?? "builder"; + + if (wrapWithConfigure) + { + source.Append(" "); + source.Append(requestHandler.Class.Name); + source.Append('.'); + source.Append(ConfigureMethodName); + source.AppendLine("("); + } + + var isFallback = string.Equals(requestHandler.HttpMethod, FallbackHttpMethod, StringComparison.Ordinal); + var mapMethodSuffix = isFallback ? null : GetMapMethodSuffix(requestHandler.HttpMethod); + + source.Append(indent); + if (isFallback) + { + source.Append(routeBuilderIdentifier); + source.Append(".MapFallback("); + if (!string.IsNullOrEmpty(requestHandler.Pattern)) + { + source.Append(StringLiteral(requestHandler.Pattern)); + source.Append(", "); + } + } + else { - source.Append("new[] { \""); - source.Append(requestHandler.HttpMethod); - source.Append("\" }, "); + source.Append(routeBuilderIdentifier); + source.Append(".Map"); + source.Append(mapMethodSuffix ?? "Methods"); + source.Append('('); + source.Append(StringLiteral(requestHandler.Pattern)); + source.Append(", "); + if (mapMethodSuffix is null) + { + source.Append("new[] { \""); + source.Append(requestHandler.HttpMethod); + source.Append("\" }, "); + } } if (requestHandler.Method.IsStatic) { @@ -729,7 +1406,7 @@ private static void GenerateMapRequestHandler(StringBuilder source, RequestHandl foreach (var parameter in requestHandler.Method.Parameters) { source.Append(", "); - source.Append(GetBindingSourceAttribute(parameter.Source, parameter.Key)); + source.Append(parameter.BindingPrefix); source.Append(parameter.Type); source.Append(' '); source.Append(parameter.Name); @@ -751,72 +1428,366 @@ private static void GenerateMapRequestHandler(StringBuilder source, RequestHandl } source.Append(')'); - if (!string.IsNullOrEmpty(requestHandler.Metadata.Name)) + var configuration = requestHandler.Configuration; + if (requestHandler.Class.MapGroupPattern is null) + configuration = MergeEndpointConfigurations(requestHandler.Class.Configuration, configuration); + + AppendEndpointConfiguration(source, continuationIndent, configuration, true); + + if (wrapWithConfigure && configureAcceptsServiceProvider) + { + source.AppendLine(","); + source.Append(indent); + source.Append("builder.ServiceProvider"); + } + + if (wrapWithConfigure) + { + source.AppendLine(); + source.Append(" );"); + source.AppendLine(); + } + else + { + source.AppendLine(";"); + } + } + + private static void AppendEndpointConfiguration(StringBuilder source, string indent, EndpointConfiguration configuration, bool includeNameAndDisplayName) + { + var metadata = configuration.Metadata; + + if (includeNameAndDisplayName && !string.IsNullOrEmpty(metadata.Name)) { source.AppendLine(); - source.Append(" .WithName("); - source.Append(StringLiteral(requestHandler.Metadata.Name)); + source.Append(indent); + source.Append(".WithName("); + source.Append(StringLiteral(metadata.Name)); source.Append(')'); } - if (!string.IsNullOrEmpty(requestHandler.Metadata.Summary)) + if (includeNameAndDisplayName && !string.IsNullOrEmpty(metadata.DisplayName)) { source.AppendLine(); - source.Append(" .WithSummary("); - source.Append(StringLiteral(requestHandler.Metadata.Summary)); + source.Append(indent); + source.Append(".WithDisplayName("); + source.Append(StringLiteral(metadata.DisplayName)); source.Append(')'); } - if (!string.IsNullOrEmpty(requestHandler.Metadata.Description)) + if (!string.IsNullOrEmpty(metadata.Summary)) { source.AppendLine(); - source.Append(" .WithDescription("); - source.Append(StringLiteral(requestHandler.Metadata.Description)); + source.Append(indent); + source.Append(".WithSummary("); + source.Append(StringLiteral(metadata.Summary)); source.Append(')'); } - if (requestHandler.Metadata.Tags is { Count: > 0 }) + if (!string.IsNullOrEmpty(metadata.Description)) { source.AppendLine(); - source.Append(" .WithTags("); - source.Append(string.Join(", ", requestHandler.Metadata.Tags.Value.Select(StringLiteral))); + source.Append(indent); + source.Append(".WithDescription("); + source.Append(StringLiteral(metadata.Description)); source.Append(')'); } - if (requestHandler.RequireAuthorization) + if (!string.IsNullOrEmpty(configuration.EndpointGroupName)) + { + source.AppendLine(); + source.Append(indent); + source.Append(".WithGroupName("); + source.Append(StringLiteral(configuration.EndpointGroupName)); + source.Append(')'); + } + + if (configuration.Order is { } orderValue) + { + source.AppendLine(); + source.Append(indent); + source.Append(".WithOrder("); + source.Append(orderValue); + source.Append(')'); + } + + if (metadata.ExcludeFromDescription) + { + source.AppendLine(); + source.Append(indent); + source.Append(".ExcludeFromDescription()"); + } + + if (metadata.Tags is { Count: > 0 }) + { + source.AppendLine(); + source.Append(indent); + source.Append(".WithTags("); + AppendCommaSeparatedLiterals(source, metadata.Tags.Value); + source.Append(')'); + } + + if (metadata.Accepts is { Count: > 0 }) + foreach (var accepts in metadata.Accepts.Value) + { + source.AppendLine(); + source.Append(indent); + source.Append(".Accepts<"); + source.Append(accepts.RequestType); + source.Append('>'); + source.Append('('); + if (accepts.IsOptional) + source.Append("isOptional: true, "); + source.Append(StringLiteral(accepts.ContentType)); + AppendAdditionalContentTypes(source, accepts.AdditionalContentTypes); + source.Append(')'); + } + + if (metadata.Produces is { Count: > 0 }) + foreach (var produces in metadata.Produces.Value) + { + source.AppendLine(); + source.Append(indent); + source.Append(".Produces<"); + source.Append(produces.ResponseType); + source.Append('>'); + source.Append('('); + source.Append(produces.StatusCode); + AppendOptionalContentTypes(source, produces.ContentType, produces.AdditionalContentTypes); + source.Append(')'); + } + + if (metadata.ProducesProblem is { Count: > 0 }) + foreach (var producesProblem in metadata.ProducesProblem.Value) + { + source.AppendLine(); + source.Append(indent); + source.Append(".ProducesProblem("); + source.Append(producesProblem.StatusCode); + AppendOptionalContentTypes(source, producesProblem.ContentType, producesProblem.AdditionalContentTypes); + source.Append(')'); + } + + if (metadata.ProducesValidationProblem is { Count: > 0 }) + foreach (var producesValidationProblem in metadata.ProducesValidationProblem.Value) + { + source.AppendLine(); + source.Append(indent); + source.Append(".ProducesValidationProblem("); + source.Append(producesValidationProblem.StatusCode); + AppendOptionalContentTypes(source, producesValidationProblem.ContentType, producesValidationProblem.AdditionalContentTypes); + source.Append(')'); + } + + if (configuration.RequireAuthorization) + { + source.AppendLine(); + if (configuration.AuthorizationPolicies is { Count: > 0 }) + { + source.Append(indent); + source.Append(".RequireAuthorization("); + AppendCommaSeparatedLiterals(source, configuration.AuthorizationPolicies.Value); + source.Append(')'); + } + else + { + source.Append(indent); + source.Append(".RequireAuthorization()"); + } + } + + if (configuration.RequireCors) { source.AppendLine(); - if (requestHandler.AuthorizationPolicies is { Count: > 0 }) + source.Append(indent); + if (!string.IsNullOrEmpty(configuration.CorsPolicyName)) { - source.Append(" .RequireAuthorization("); - source.Append(string.Join(", ", requestHandler.AuthorizationPolicies.Value.Select(StringLiteral))); + source.Append(".RequireCors("); + source.Append(StringLiteral(configuration.CorsPolicyName)); source.Append(')'); } else { - source.Append(" .RequireAuthorization()"); + source.Append(".RequireCors()"); } } - if (requestHandler.DisableAntiforgery) + if (configuration.RequiredHosts is { Count: > 0 }) { source.AppendLine(); - source.Append(" .DisableAntiforgery()"); + source.Append(indent); + source.Append(".RequireHost("); + AppendCommaSeparatedLiterals(source, configuration.RequiredHosts.Value); + source.Append(')'); } - source.AppendLine(";"); + if (configuration.RequireRateLimiting && !string.IsNullOrEmpty(configuration.RateLimitingPolicyName)) + { + source.AppendLine(); + source.Append(indent); + source.Append(".RequireRateLimiting("); + source.Append(StringLiteral(configuration.RateLimitingPolicyName)); + source.Append(')'); + } + + if (configuration.DisableAntiforgery) + { + source.AppendLine(); + source.Append(indent); + source.Append(".DisableAntiforgery()"); + } + + if (configuration.AllowAnonymous) + { + source.AppendLine(); + source.Append(indent); + source.Append(".AllowAnonymous()"); + } + + if (configuration.ShortCircuit) + { + source.AppendLine(); + source.Append(indent); + source.Append(".ShortCircuit()"); + } + + if (configuration.DisableValidation) + { + source.AppendLine(); + source.Append(indent); + source.Append(".DisableValidation()"); + source.AppendLine(); + } + + if (configuration.DisableRequestTimeout) + { + source.AppendLine(); + source.Append(indent); + source.Append(".DisableRequestTimeout()"); + } + else if (configuration.WithRequestTimeout) + { + source.AppendLine(); + source.Append(indent); + if (!string.IsNullOrEmpty(configuration.RequestTimeoutPolicyName)) + { + source.Append(".WithRequestTimeout("); + source.Append(StringLiteral(configuration.RequestTimeoutPolicyName)); + source.Append(')'); + } + else + { + source.Append(".WithRequestTimeout()"); + } + } + + if (configuration.EndpointFilterTypes is { Count: > 0 }) + foreach (var filterType in configuration.EndpointFilterTypes.Value) + { + source.AppendLine(); + source.Append(indent); + source.Append(".AddEndpointFilter<"); + source.Append(filterType); + source.Append(">()"); + } + } + + private static EndpointConfiguration MergeEndpointConfigurations(EndpointConfiguration classConfiguration, EndpointConfiguration methodConfiguration) + { + var metadata = MergeRequestHandlerMetadata(classConfiguration.Metadata, methodConfiguration.Metadata); + var authorizationPolicies = MergeDistinctStrings(classConfiguration.AuthorizationPolicies, methodConfiguration.AuthorizationPolicies); + var requiredHosts = MergeDistinctStrings(classConfiguration.RequiredHosts, methodConfiguration.RequiredHosts); + var endpointFilterTypes = ConcatEquatable(classConfiguration.EndpointFilterTypes, methodConfiguration.EndpointFilterTypes); + var requireAuthorization = classConfiguration.RequireAuthorization || methodConfiguration.RequireAuthorization; + var disableAntiforgery = classConfiguration.DisableAntiforgery || methodConfiguration.DisableAntiforgery; + var allowAnonymous = classConfiguration.AllowAnonymous || methodConfiguration.AllowAnonymous; + var requireCors = classConfiguration.RequireCors || methodConfiguration.RequireCors; + var corsPolicyName = methodConfiguration.CorsPolicyName ?? classConfiguration.CorsPolicyName; + var requireRateLimiting = classConfiguration.RequireRateLimiting || methodConfiguration.RequireRateLimiting; + var rateLimitingPolicyName = methodConfiguration.RateLimitingPolicyName ?? classConfiguration.RateLimitingPolicyName; + var shortCircuit = classConfiguration.ShortCircuit || methodConfiguration.ShortCircuit; + var disableValidation = classConfiguration.DisableValidation || methodConfiguration.DisableValidation; + var disableRequestTimeout = classConfiguration.DisableRequestTimeout || methodConfiguration.DisableRequestTimeout; + var withRequestTimeout = classConfiguration.WithRequestTimeout || methodConfiguration.WithRequestTimeout; + string? requestTimeoutPolicyName = null; + if (methodConfiguration.WithRequestTimeout) + requestTimeoutPolicyName = methodConfiguration.RequestTimeoutPolicyName; + else if (classConfiguration.WithRequestTimeout) + requestTimeoutPolicyName = classConfiguration.RequestTimeoutPolicyName; + + if (disableRequestTimeout) + { + withRequestTimeout = false; + requestTimeoutPolicyName = null; + } + + var order = methodConfiguration.Order ?? classConfiguration.Order; + var endpointGroupName = methodConfiguration.EndpointGroupName ?? classConfiguration.EndpointGroupName; + + return new EndpointConfiguration(metadata, requireAuthorization, authorizationPolicies, disableAntiforgery, allowAnonymous, requireCors, corsPolicyName, + requiredHosts, requireRateLimiting, rateLimitingPolicyName, endpointFilterTypes, shortCircuit, disableValidation, disableRequestTimeout, + withRequestTimeout, requestTimeoutPolicyName, order, endpointGroupName + ); + } + + private static RequestHandlerMetadata MergeRequestHandlerMetadata(RequestHandlerMetadata classMetadata, RequestHandlerMetadata methodMetadata) + { + return new RequestHandlerMetadata(methodMetadata.Name ?? classMetadata.Name, methodMetadata.DisplayName ?? classMetadata.DisplayName, + methodMetadata.Summary ?? classMetadata.Summary, methodMetadata.Description ?? classMetadata.Description, + MergeDistinctStrings(classMetadata.Tags, methodMetadata.Tags), ConcatEquatable(classMetadata.Accepts, methodMetadata.Accepts), + ConcatEquatable(classMetadata.Produces, methodMetadata.Produces), ConcatEquatable(classMetadata.ProducesProblem, methodMetadata.ProducesProblem), + ConcatEquatable(classMetadata.ProducesValidationProblem, methodMetadata.ProducesValidationProblem), + classMetadata.ExcludeFromDescription || methodMetadata.ExcludeFromDescription + ); + } + + private static EquatableImmutableArray? MergeDistinctStrings(EquatableImmutableArray? first, EquatableImmutableArray? second) + { + if (first is not { Count: > 0 }) + return second; + if (second is not { Count: > 0 }) + return first; + + var merged = MergeUnion(first, second.Value); + return merged.Count > 0 ? merged : null; + } + + private static EquatableImmutableArray? ConcatEquatable(EquatableImmutableArray? first, EquatableImmutableArray? second) + { + if (first is not { Count: > 0 }) + return second; + if (second is not { Count: > 0 }) + return first; + + var builder = ImmutableArray.CreateBuilder(first.Value.Count + second.Value.Count); + builder.AddRange(first.Value); + builder.AddRange(second.Value); + return builder.ToEquatableImmutableArray(); + } + + private static string? GetMapMethodSuffix(string httpMethod) + { + return httpMethod switch + { + "GET" => "Get", + "POST" => "Post", + "PUT" => "Put", + "DELETE" => "Delete", + "PATCH" => "Patch", + _ => null, + }; } - private static string GetBindingSourceAttribute(BindingSource source, string? key) + private static string GetBindingSourceAttribute(BindingSource source, string? key, string? bindingName) { return source switch { BindingSource.None => "", - BindingSource.FromRoute => "[FromRoute] ", - BindingSource.FromQuery => "[FromQuery] ", - BindingSource.FromHeader => "[FromHeader] ", - BindingSource.FromBody => "[FromBody] ", - BindingSource.FromForm => "[FromForm] ", + BindingSource.FromRoute => FormatBindingAttribute("FromRoute", bindingName), + BindingSource.FromQuery => FormatBindingAttribute("FromQuery", bindingName), + BindingSource.FromHeader => FormatBindingAttribute("FromHeader", bindingName), + BindingSource.FromBody => FormatBindingAttribute("FromBody", bindingName), + BindingSource.FromForm => FormatBindingAttribute("FromForm", bindingName), BindingSource.FromServices => "[FromServices] ", BindingSource.FromKeyedServices => $"[FromKeyedServices({key})] ", BindingSource.AsParameters => "[AsParameters] ", @@ -824,53 +1795,27 @@ private static string GetBindingSourceAttribute(BindingSource source, string? ke }; } - private static StringBuilder GetUseEndpointHandlersStringBuilder(ImmutableArray requestHandlers) + private static string FormatBindingAttribute(string attributeName, string? bindingName) { - var estimate = 1024; - - foreach (var rh in requestHandlers) - { - var cost = 160; - - cost += 2 + rh.Pattern.Length; - cost += rh.Class.Name.Length + rh.Method.Name.Length; - - var parameters = rh.Method.Parameters; - foreach (var p in parameters) - cost += 12 + p.Type.Length + p.Name.Length; - - var (name, summary, description, tags) = rh.Metadata; - if (name is { Length: > 0 }) - cost += 22 + name.Length; - if (summary is { Length: > 0 }) - cost += 24 + summary.Length; - if (description is { Length: > 0 }) - cost += 28 + description.Length; - - if (tags is { Count: > 0 }) - cost += tags.Value.Sum(tag => 6 + tag.Length); + if (bindingName is null) + return $"[{attributeName}] "; - if (rh.RequireAuthorization) - cost += 24; - if (rh.AuthorizationPolicies is { Count: > 0 }) - cost += rh.AuthorizationPolicies.Value.Sum(p => 6 + p.Length); - if (rh.DisableAntiforgery) - cost += 24; + return $"[{attributeName}(Name = {StringLiteral(bindingName)})] "; + } - estimate += cost; - } + private static StringBuilder GetUseEndpointHandlersStringBuilder(ImmutableArray requestHandlers) + { + const int baseSize = 4096; + const int perHandler = 512; - estimate += Math.Max(256, requestHandlers.Length * 16); - estimate = (int)(estimate * 1.12); + var handlerCount = Math.Max(requestHandlers.Length, 0); + var estimate = baseSize + (long)perHandler * handlerCount; + estimate = (long)(estimate * 1.10); - estimate = estimate switch - { - < 4096 => 4096, - > 65536 => 65536, - _ => estimate, - }; + if (estimate > int.MaxValue) + estimate = int.MaxValue; - return new StringBuilder(estimate); + return StringBuilderPool.Get((int)Math.Max(baseSize, estimate)); } [SuppressMessage("Globalization", "CA1308: Normalize strings to uppercase", Justification = "C# boolean literals must be lowercase.")] @@ -937,10 +1882,28 @@ private static string StringLiteral(string? value) if (value is null) return "null"; - var sb = new StringBuilder(value.Length + 2); + var firstEscapeIndex = -1; + for (var i = 0; i < value.Length; i++) + { + var c = value[i]; + if (c == '\"' || c == '\\' || c == '\n' || c == '\r' || c == '\t' || c == '\0' || char.IsControl(c)) + { + firstEscapeIndex = i; + break; + } + } + + if (firstEscapeIndex < 0) + return string.Concat("\"", value, "\""); + + var sb = StringBuilderPool.Get(value.Length + 2); sb.Append('"'); - foreach (var c in value) + if (firstEscapeIndex > 0) + sb.Append(value, 0, firstEscapeIndex); + + for (var i = firstEscapeIndex; i < value.Length; i++) { + var c = value[i]; switch (c) { case '\"': @@ -967,11 +1930,48 @@ private static string StringLiteral(string? value) .Append(((int)c).ToString("x4", CultureInfo.InvariantCulture)); else sb.Append(c); + break; } } + sb.Append('"'); - return sb.ToString(); + return StringBuilderPool.ToStringAndReturn(sb); + } + + private static void AppendAdditionalContentTypes(StringBuilder source, EquatableImmutableArray? additionalContentTypes) + { + if (additionalContentTypes is not { Count: > 0 }) + return; + + foreach (var additional in additionalContentTypes.Value) + { + source.Append(", "); + source.Append(StringLiteral(additional)); + } + } + + private static void AppendCommaSeparatedLiterals(StringBuilder source, EquatableImmutableArray values) + { + if (values.Count == 0) + return; + + source.Append(StringLiteral(values[0])); + for (var i = 1; i < values.Count; i++) + { + source.Append(", "); + source.Append(StringLiteral(values[i])); + } + } + + private static void AppendOptionalContentTypes(StringBuilder source, string? contentType, EquatableImmutableArray? additionalContentTypes) + { + if (string.IsNullOrEmpty(contentType) && additionalContentTypes is not { Count: > 0 }) + return; + + source.Append(", "); + source.Append(contentType is { Length: > 0 } ? StringLiteral(contentType) : "null"); + AppendAdditionalContentTypes(source, additionalContentTypes); } private static string EscapeChar(char c) @@ -988,36 +1988,4 @@ _ when char.IsControl(c) => "\\u" + ((int)c).ToString("x4", CultureInfo.Invarian _ => c.ToString(), }; } - - private readonly record struct RequestHandler( - RequestHandlerClass Class, - RequestHandlerMethod Method, - string HttpMethod, - string Pattern, - RequestHandlerMetadata Metadata, - bool RequireAuthorization, - EquatableImmutableArray? AuthorizationPolicies, - bool DisableAntiforgery - ); - - private readonly record struct RequestHandlerClass(string Name, bool IsStatic); - - private readonly record struct RequestHandlerMethod(string Name, bool IsStatic, bool IsAwaitable, EquatableImmutableArray Parameters); - - private readonly record struct RequestHandlerMetadata(string? Name, string? Summary, string? Description, EquatableImmutableArray? Tags); - - private readonly record struct Parameter(string Name, string Type, BindingSource Source, string? Key); - - private enum BindingSource - { - None = 0, - FromRoute = 1, - FromQuery = 2, - FromHeader = 3, - FromBody = 4, - FromForm = 5, - FromServices = 6, - FromKeyedServices = 7, - AsParameters = 8, - } } diff --git a/tests/GeneratedEndpoints.Tests.Lab/GeneratedEndpoints.Tests.Lab.csproj b/tests/GeneratedEndpoints.Tests.Lab/GeneratedEndpoints.Tests.Lab.csproj new file mode 100644 index 0000000..7ab05ac --- /dev/null +++ b/tests/GeneratedEndpoints.Tests.Lab/GeneratedEndpoints.Tests.Lab.csproj @@ -0,0 +1,22 @@ + + + + net10.0 + enable + false + enable + latest + false + + + + + + + + + appsettings.json + + + + diff --git a/tests/GeneratedEndpoints.Tests.Lab/GetUserEndpoint.cs b/tests/GeneratedEndpoints.Tests.Lab/GetUserEndpoint.cs new file mode 100644 index 0000000..4452d06 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests.Lab/GetUserEndpoint.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Generated.Attributes; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; + +// ReSharper disable UnusedParameter.Global +#pragma warning disable CS9113 // Parameter is unread. + +namespace GeneratedEndpoints.Tests.Lab; + +[Tags("Users", "Profiles")] +[RequireAuthorization("Users.Read", "Administrators")] +[DisableAntiforgery] +internal sealed class GetUserEndpoint(IServiceProvider serviceProvider) +{ + [Tags("Featured")] + [AllowAnonymous] + [Accepts("application/json", "application/xml", RequestType = typeof(GetUserRequest))] + [Accepts("application/json", "application/xml", IsOptional = true)] + [ProducesResponse(StatusCodes.Status200OK, "application/json", ResponseType = typeof(UserProfile))] + [ProducesResponse(StatusCodes.Status202Accepted, "application/json")] + [ProducesProblem(StatusCodes.Status500InternalServerError, "application/problem+json")] + [ProducesValidationProblem(StatusCodes.Status400BadRequest, "application/problem+json")] + [DisplayName("User lookup endpoint")] + [Description("Gets a user by ID when the ID is greater than zero.")] + [Summary("Gets a user by ID.")] + [MapGet("/users/{id:int}", Name = nameof(GetUser))] + public Results, NotFound, ValidationProblem, ProblemHttpResult> GetUser( + [FromQuery] int id, + [FromKeyedServices(ServiceLifetime.Scoped)] IServiceCollection services + ) + { + if (id <= 0) + { + var errors = new Dictionary + { + [nameof(id)] = ["The ID must be greater than zero."], + }; + return TypedResults.ValidationProblem(errors); + } + + if (id == 13) + return TypedResults.Problem("User data is temporarily unavailable."); + + if (id == 404) + return TypedResults.NotFound(); + + var profile = new UserProfile(id, $"User {id}", $"user{id}@example.com"); + return TypedResults.Ok(profile); + } + + public static void Configure(TBuilder builder) + where TBuilder : IEndpointConventionBuilder + { + } +} + +internal sealed record GetUserRequest(int Id); + +internal sealed record GetUserMetadata(string RequestedBy, string Purpose); + +internal sealed record UserProfile(int Id, string DisplayName, string Email); diff --git a/tests/GeneratedEndpoints.Tests.Lab/Program.cs b/tests/GeneratedEndpoints.Tests.Lab/Program.cs new file mode 100644 index 0000000..fc11c97 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests.Lab/Program.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Generated.Routing; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddEndpointHandlers(); + +var app = builder.Build(); + +app.MapEndpointHandlers(); + +app.Run(); diff --git a/tests/GeneratedEndpoints.Tests.Lab/Properties/launchSettings.json b/tests/GeneratedEndpoints.Tests.Lab/Properties/launchSettings.json new file mode 100644 index 0000000..93b571a --- /dev/null +++ b/tests/GeneratedEndpoints.Tests.Lab/Properties/launchSettings.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "http://localhost:5271", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": false, + "applicationUrl": "https://localhost:7127;http://localhost:5271", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/tests/GeneratedEndpoints.Tests.Lab/appsettings.Development.json b/tests/GeneratedEndpoints.Tests.Lab/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/tests/GeneratedEndpoints.Tests.Lab/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/tests/GeneratedEndpoints.Tests.Lab/appsettings.json b/tests/GeneratedEndpoints.Tests.Lab/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests.Lab/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.AcceptsAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.AcceptsAttribute.verified.txt new file mode 100644 index 0000000..d4d0ac4 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.AcceptsAttribute.verified.txt @@ -0,0 +1,90 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies the request type and content types accepted by the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class AcceptsAttribute : global::System.Attribute +{ + /// + /// Gets the request type accepted by the endpoint. + /// + public global::System.Type? RequestType { get; init; } + + /// + /// Gets a value indicating whether the request body is optional. + /// + public bool IsOptional { get; init; } + + /// + /// Gets the primary content type accepted by the endpoint. + /// + public string ContentType { get; } + + /// + /// Gets the additional content types accepted by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The primary content type accepted by the endpoint. + /// Additional content types accepted by the endpoint. + public AcceptsAttribute(string contentType = "application/json", params string[] additionalContentTypes) + { + ContentType = string.IsNullOrWhiteSpace(contentType) ? "application/json" : contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } +} + +/// +/// Specifies the request type using a generic argument and the content types accepted by the annotated endpoint or class. +/// +/// The CLR type of the request body. +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class AcceptsAttribute : global::System.Attribute +{ + /// + /// Gets the request type accepted by the endpoint. + /// + public global::System.Type RequestType => typeof(TRequest); + + /// + /// Gets a value indicating whether the request body is optional. + /// + public bool IsOptional { get; init; } + + /// + /// Gets the primary content type accepted by the endpoint. + /// + public string ContentType { get; } + + /// + /// Gets the additional content types accepted by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the generic Accepts attribute class. + /// + /// The primary content type accepted by the endpoint. + /// Additional content types accepted by the endpoint. + public AcceptsAttribute(string contentType = "application/json", params string[] additionalContentTypes) + { + ContentType = string.IsNullOrWhiteSpace(contentType) ? "application/json" : contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableAntiforgeryAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableAntiforgeryAttribute.verified.txt new file mode 100644 index 0000000..4ee8f6c --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableAntiforgeryAttribute.verified.txt @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Disables antiforgery protection for the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class DisableAntiforgeryAttribute : global::System.Attribute +{ +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableRequestTimeoutAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableRequestTimeoutAttribute.verified.txt new file mode 100644 index 0000000..1b5b5e6 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableRequestTimeoutAttribute.verified.txt @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Disables the request timeout for the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class DisableRequestTimeoutAttribute : global::System.Attribute +{ +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableValidationAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableValidationAttribute.verified.txt new file mode 100644 index 0000000..d4329f5 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.DisableValidationAttribute.verified.txt @@ -0,0 +1,23 @@ +#if NET10_0_OR_GREATER +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Disables request validation for the annotated endpoint or class when targeting .NET 10 or later. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class DisableValidationAttribute : global::System.Attribute +{ +} +#endif diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.EndpointFilterAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.EndpointFilterAttribute.verified.txt new file mode 100644 index 0000000..e96674f --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.EndpointFilterAttribute.verified.txt @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies an endpoint filter type to apply to the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class EndpointFilterAttribute : global::System.Attribute +{ + /// + /// Gets the CLR type of the endpoint filter. + /// + public global::System.Type FilterType { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The CLR type of the endpoint filter. + public EndpointFilterAttribute(global::System.Type filterType) + { + FilterType = filterType ?? throw new global::System.ArgumentNullException(nameof(filterType)); + } +} + +/// +/// Specifies an endpoint filter type using a generic argument. +/// +/// The CLR type of the endpoint filter. +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class EndpointFilterAttribute : global::System.Attribute +{ + /// + /// Gets the CLR type of the endpoint filter. + /// + public global::System.Type FilterType => typeof(TFilter); +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapConnectAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapConnectAttribute.verified.txt new file mode 100644 index 0000000..0d2d237 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapConnectAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP CONNECT minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapConnectAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapConnectAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapDeleteAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapDeleteAttribute.verified.txt new file mode 100644 index 0000000..e4b8449 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapDeleteAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP DELETE minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapDeleteAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapDeleteAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapFallbackAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapFallbackAttribute.verified.txt new file mode 100644 index 0000000..560ee77 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapFallbackAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP fallback minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapFallbackAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string? Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapFallbackAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string? pattern = null) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapGetAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapGetAttribute.verified.txt new file mode 100644 index 0000000..f769cb7 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapGetAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP GET minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapGetAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapGetAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapGroupAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapGroupAttribute.verified.txt new file mode 100644 index 0000000..b089593 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapGroupAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies the route group for the annotated class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class, Inherited = false, AllowMultiple = false)] +internal sealed class MapGroupAttribute : global::System.Attribute +{ + /// + /// Gets the route group pattern. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint group name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route group pattern to apply. + public MapGroupAttribute(string pattern) + { + Pattern = pattern; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapHeadAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapHeadAttribute.verified.txt new file mode 100644 index 0000000..6c7e980 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapHeadAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP HEAD minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapHeadAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapHeadAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapOptionsAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapOptionsAttribute.verified.txt new file mode 100644 index 0000000..b873462 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapOptionsAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP OPTIONS minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapOptionsAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapOptionsAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPatchAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPatchAttribute.verified.txt new file mode 100644 index 0000000..8a13fd5 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPatchAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP PATCH minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapPatchAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapPatchAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPostAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPostAttribute.verified.txt new file mode 100644 index 0000000..0afbe37 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPostAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP POST minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapPostAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapPostAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPutAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPutAttribute.verified.txt new file mode 100644 index 0000000..92762a0 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapPutAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP PUT minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapPutAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapPutAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapQueryAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapQueryAttribute.verified.txt new file mode 100644 index 0000000..ec47f1f --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapQueryAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP QUERY minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapQueryAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapQueryAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapTraceAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapTraceAttribute.verified.txt new file mode 100644 index 0000000..7d354c1 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.MapTraceAttribute.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Identifies a method as an HTTP TRACE minimal API endpoint with the specified route pattern. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class MapTraceAttribute : global::System.Attribute +{ + /// + /// Gets the route pattern for the endpoint. + /// + public string Pattern { get; } + + /// + /// Gets or sets the endpoint name. + /// + public string? Name { get; init; } + + /// + /// Initializes a new instance of the class. + /// + /// The route pattern for the endpoint. + public MapTraceAttribute([global::System.Diagnostics.CodeAnalysis.StringSyntax("Route")] string pattern) + { + Pattern = pattern; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.OrderAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.OrderAttribute.verified.txt new file mode 100644 index 0000000..add300d --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.OrderAttribute.verified.txt @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies the order for the annotated endpoint when building conventions. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class OrderAttribute : global::System.Attribute +{ + /// + /// Gets the order that will be applied to the endpoint. + /// + public int Order { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The order value to apply to the endpoint. + public OrderAttribute(int order) + { + Order = order; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesProblemAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesProblemAttribute.verified.txt new file mode 100644 index 0000000..516fc6f --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesProblemAttribute.verified.txt @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies that the endpoint produces a problem details payload. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class ProducesProblemAttribute : global::System.Attribute +{ + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public ProducesProblemAttribute(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status500InternalServerError, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesResponseAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesResponseAttribute.verified.txt new file mode 100644 index 0000000..e5d6748 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesResponseAttribute.verified.txt @@ -0,0 +1,94 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies a response type, status code, and content types produced by the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class ProducesResponseAttribute : global::System.Attribute +{ +/// +/// Gets the response type produced by the endpoint. +/// +public global::System.Type? ResponseType { get; init; } + + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public ProducesResponseAttribute(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status200OK, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } +} + +/// +/// Specifies a response type using a generic argument along with status code and content types produced by the annotated endpoint or class. +/// +/// The CLR type of the response body. +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class ProducesResponseAttribute : global::System.Attribute +{ + /// + /// Gets the response type produced by the endpoint. + /// + public global::System.Type ResponseType => typeof(TResponse); + + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the generic Produces attribute class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public ProducesResponseAttribute(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status200OK, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesValidationProblemAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesValidationProblemAttribute.verified.txt new file mode 100644 index 0000000..9d0ddd6 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ProducesValidationProblemAttribute.verified.txt @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies that the endpoint produces a validation problem details payload. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)] +internal sealed class ProducesValidationProblemAttribute : global::System.Attribute +{ + /// + /// Gets the HTTP status code returned by the endpoint. + /// + public int StatusCode { get; } + + /// + /// Gets the primary content type produced by the endpoint. + /// + public string? ContentType { get; } + + /// + /// Gets the additional content types produced by the endpoint. + /// + public string[] AdditionalContentTypes { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The HTTP status code returned by the endpoint. + /// The primary content type produced by the endpoint. + /// Additional content types produced by the endpoint. + public ProducesValidationProblemAttribute(int statusCode = global::Microsoft.AspNetCore.Http.StatusCodes.Status400BadRequest, string? contentType = null, params string[] additionalContentTypes) + { + StatusCode = statusCode; + ContentType = contentType; + AdditionalContentTypes = additionalContentTypes ?? []; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequestTimeoutAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequestTimeoutAttribute.verified.txt new file mode 100644 index 0000000..dee02d0 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequestTimeoutAttribute.verified.txt @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Applies the request timeout metadata to the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class RequestTimeoutAttribute : global::System.Attribute +{ + /// + /// Gets the optional request timeout policy name. + /// + public string? PolicyName { get; init; } + + /// + /// Applies the default request timeout behavior. + /// + public RequestTimeoutAttribute() + { + } + + /// + /// Applies the specified request timeout policy. + /// + /// The request timeout policy name. + public RequestTimeoutAttribute(string policyName) + { + PolicyName = policyName; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireAuthorizationAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireAuthorizationAttribute.verified.txt new file mode 100644 index 0000000..cf3e247 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireAuthorizationAttribute.verified.txt @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies that authorization is required for the annotated endpoint or class. +/// Optionally restricts access to the specified authorization policies. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class RequireAuthorizationAttribute : global::System.Attribute +{ + /// + /// Gets the policy names that the endpoint or class requires. + /// + public string[] PolicyNames { get; } + + /// + /// Marks the endpoint or class as requiring authorization. + /// + public RequireAuthorizationAttribute() + { + PolicyNames = []; + } + + /// + /// Marks the endpoint or class as requiring authorization with one or more policies. + /// + public RequireAuthorizationAttribute(params string[] policyNames) + { + PolicyNames = policyNames ?? []; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireCorsAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireCorsAttribute.verified.txt new file mode 100644 index 0000000..ad8377c --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireCorsAttribute.verified.txt @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies that the annotated endpoint requires a configured CORS policy. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class RequireCorsAttribute : global::System.Attribute +{ + /// + /// Gets the optional CORS policy name. + /// + public string? PolicyName { get; } + + /// + /// Marks the endpoint or class as requiring the default CORS policy. + /// + public RequireCorsAttribute() + { + } + + /// + /// Marks the endpoint or class as requiring the specified named CORS policy. + /// + public RequireCorsAttribute(string policyName) + { + PolicyName = policyName; + } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireHostAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireHostAttribute.verified.txt new file mode 100644 index 0000000..2303b72 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireHostAttribute.verified.txt @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies the allowed hosts for the annotated endpoint or class. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class RequireHostAttribute : global::System.Attribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The hosts that are allowed to access the endpoint. + public RequireHostAttribute(params string[] hosts) + { + Hosts = hosts ?? []; + } + + /// + /// Gets the allowed hosts. + /// + public string[] Hosts { get; } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireRateLimitingAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireRateLimitingAttribute.verified.txt new file mode 100644 index 0000000..678d330 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.RequireRateLimitingAttribute.verified.txt @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies that the annotated endpoint requires the provided rate limiting policy. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class RequireRateLimitingAttribute : global::System.Attribute +{ + /// + /// Initializes a new instance of the class. + /// + /// The rate limiting policy to apply. + public RequireRateLimitingAttribute(string policyName) + { + PolicyName = policyName; + } + + /// + /// Gets the rate limiting policy name. + /// + public string PolicyName { get; } +} \ No newline at end of file diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ShortCircuitAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ShortCircuitAttribute.verified.txt new file mode 100644 index 0000000..fd75bc0 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.ShortCircuitAttribute.verified.txt @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Marks the annotated endpoint or class to short-circuit the request pipeline. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class ShortCircuitAttribute : global::System.Attribute +{ +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.SummaryAttribute.verified.txt b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.SummaryAttribute.verified.txt new file mode 100644 index 0000000..2fccdce --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.SummaryAttribute.verified.txt @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +namespace Microsoft.AspNetCore.Generated.Attributes; + +/// +/// Specifies the summary metadata for the annotated endpoint. +/// +[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +internal sealed class SummaryAttribute : global::System.Attribute +{ + /// + /// Gets the summary value for the endpoint. + /// + public string Summary { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The summary to apply to the endpoint. + public SummaryAttribute(string summary) + { + Summary = summary; + } +} diff --git a/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.cs b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.cs new file mode 100644 index 0000000..1831f55 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/AttributeGenerationTests.cs @@ -0,0 +1,133 @@ +using GeneratedEndpoints.Tests.Common; +using Microsoft.CodeAnalysis; +using SourceGeneratorTestHelpers.XUnit; + +namespace GeneratedEndpoints.Tests; + +[UsesVerify] +public class AttributeGenerationTests +{ + private const string AttributeTestSource = "internal static class AttributeTestEndpoints { }"; + private static readonly GeneratorDriverRunResult GeneratorResult = + TestHelpers.RunGenerator(TestHelpers.GetSources(AttributeTestSource, withNamespace: true)); + + public AttributeGenerationTests() + { + ModuleInitializer.Initialize(); + } + + [Fact] + public Task MapGetAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapGetAttribute.gs.cs"); + + [Fact] + public Task MapPostAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapPostAttribute.gs.cs"); + + [Fact] + public Task MapPutAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapPutAttribute.gs.cs"); + + [Fact] + public Task MapPatchAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapPatchAttribute.gs.cs"); + + [Fact] + public Task MapDeleteAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapDeleteAttribute.gs.cs"); + + [Fact] + public Task MapOptionsAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapOptionsAttribute.gs.cs"); + + [Fact] + public Task MapHeadAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapHeadAttribute.gs.cs"); + + [Fact] + public Task MapQueryAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapQueryAttribute.gs.cs"); + + [Fact] + public Task MapTraceAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapTraceAttribute.gs.cs"); + + [Fact] + public Task MapConnectAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapConnectAttribute.gs.cs"); + + [Fact] + public Task MapFallbackAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapFallbackAttribute.gs.cs"); + + [Fact] + public Task RequireAuthorizationAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.RequireAuthorizationAttribute.gs.cs"); + + [Fact] + public Task RequireCorsAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.RequireCorsAttribute.gs.cs"); + + [Fact] + public Task RequireRateLimitingAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.RequireRateLimitingAttribute.gs.cs"); + + [Fact] + public Task RequireHostAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.RequireHostAttribute.gs.cs"); + + [Fact] + public Task DisableAntiforgeryAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.DisableAntiforgeryAttribute.gs.cs"); + + [Fact] + public Task ShortCircuitAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.ShortCircuitAttribute.gs.cs"); + + [Fact] + public Task DisableRequestTimeoutAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.DisableRequestTimeoutAttribute.gs.cs"); + + [Fact] + public Task DisableValidationAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.DisableValidationAttribute.gs.cs"); + + [Fact] + public Task RequestTimeoutAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.RequestTimeoutAttribute.gs.cs"); + + [Fact] + public Task OrderAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.OrderAttribute.gs.cs"); + + [Fact] + public Task MapGroupAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.MapGroupAttribute.gs.cs"); + + [Fact] + public Task SummaryAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.SummaryAttribute.gs.cs"); + + [Fact] + public Task AcceptsAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.AcceptsAttribute.gs.cs"); + + [Fact] + public Task EndpointFilterAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.EndpointFilterAttribute.gs.cs"); + + [Fact] + public Task ProducesResponseAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.ProducesResponseAttribute.gs.cs"); + + [Fact] + public Task ProducesProblemAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.ProducesProblemAttribute.gs.cs"); + + [Fact] + public Task ProducesValidationProblemAttribute() + => VerifyAttributeAsync("Microsoft.AspNetCore.Generated.Attributes.ProducesValidationProblemAttribute.gs.cs"); + + private static Task VerifyAttributeAsync(string fileName) + => GeneratorResult.VerifyAsync(fileName); +} diff --git a/tests/GeneratedEndpoints.Tests/Common/ScenarioNamer.cs b/tests/GeneratedEndpoints.Tests/Common/ScenarioNamer.cs new file mode 100644 index 0000000..db7d771 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/Common/ScenarioNamer.cs @@ -0,0 +1,40 @@ +using System.Security.Cryptography; +using System.Text; + +namespace GeneratedEndpoints.Tests.Common; + +public static class ScenarioNamer +{ + public static string Create(string prefix, params (string Name, object? Value)[] parts) + { + var descriptor = new StringBuilder(); + + foreach (var (name, value) in parts) + { + descriptor.Append(name); + descriptor.Append('='); + descriptor.Append(Sanitize(value)); + descriptor.Append(';'); + } + + using var sha256 = SHA256.Create(); + var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(descriptor.ToString())); + var hash = Convert.ToHexString(bytes.AsSpan(0, 6)); + return $"{prefix}_{hash}"; + } + + private static string Sanitize(object? value) + { + if (value is null) + { + return "None"; + } + + return value switch + { + bool b => b ? "On" : "Off", + string s => s, + _ => value.ToString() ?? "Value" + }; + } +} diff --git a/tests/GeneratedEndpoints.Tests/Common/SourceFactory.cs b/tests/GeneratedEndpoints.Tests/Common/SourceFactory.cs new file mode 100644 index 0000000..ac721c9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/Common/SourceFactory.cs @@ -0,0 +1,479 @@ +using System.Text; + +namespace GeneratedEndpoints.Tests.Common; + +public static class SourceFactory +{ + public static string BuildFallbackSource(bool includeDefault, bool includeCustom, string? customRoute) + { + var builder = new StringBuilder(); + builder.AppendLine("internal static class FallbackEndpoints"); + builder.AppendLine("{"); + + if (includeDefault) + { + builder.AppendLine(" [MapFallback]"); + builder.AppendLine(" public static Ok Default() => TypedResults.Ok();"); + builder.AppendLine(); + } + + if (includeCustom) + { + var route = customRoute ?? "/custom"; + builder.AppendLine($" [MapFallback(\"{route}\")]"); + builder.AppendLine(" public static Ok Custom() => TypedResults.Ok();"); + builder.AppendLine(); + } + + builder.AppendLine("}"); + return builder.ToString(); + } + + public static string BuildAuthorizationMatrixSource( + bool classAllowAnonymous, + bool methodAllowAnonymous, + bool classRequireAuthorization, + bool methodRequireAuthorization, + bool classTags, + bool methodTags, + string? classHost, + string? methodHost, + bool classRequireCors, + string? classCorsPolicy, + bool methodRequireCors, + string? methodCorsPolicy, + bool requireRateLimiting, + string? rateLimitingPolicy, + bool applyShortCircuit, + bool applyRequestTimeout, + string? requestTimeoutPolicy, + bool disableRequestTimeout, + int orderValue, + string? groupName, + bool excludeFromDescription, + string? mapGroupPattern = null, + bool classDisableValidation = false, + bool methodDisableValidation = false) + { + var builder = new StringBuilder(); + + if (classAllowAnonymous) + { + builder.AppendLine("[AllowAnonymous]"); + } + + if (classRequireAuthorization) + { + builder.AppendLine("[RequireAuthorization(\"ClassPolicy\")]"); + } + + if (classTags) + { + builder.AppendLine("[Tags(\"Class\", \"Matrix\")]"); + } + + if (!string.IsNullOrWhiteSpace(classHost)) + { + builder.AppendLine($"[RequireHost(\"{classHost}\")]"); + } + + if (classRequireCors) + { + var cors = string.IsNullOrWhiteSpace(classCorsPolicy) ? "" : $"(\"{classCorsPolicy}\")"; + builder.AppendLine($"[RequireCors{cors}]"); + } + + if (!string.IsNullOrWhiteSpace(groupName) && mapGroupPattern is null) + { + mapGroupPattern = string.Empty; + } + + if (mapGroupPattern is not null) + { + var mapGroupAttribute = new StringBuilder(); + mapGroupAttribute.Append($"[MapGroup(\"{mapGroupPattern}\""); + if (!string.IsNullOrWhiteSpace(groupName)) + { + mapGroupAttribute.Append($", Name = \"{groupName}\""); + } + + mapGroupAttribute.Append(")]"); + builder.AppendLine(mapGroupAttribute.ToString()); + } + + if (applyShortCircuit) + { + builder.AppendLine("[ShortCircuit]"); + } + + if (classDisableValidation) + { + builder.AppendLine("[DisableValidation]"); + } + + if (applyRequestTimeout) + { + var timeoutArgument = string.IsNullOrWhiteSpace(requestTimeoutPolicy) + ? string.Empty + : $"(\"{requestTimeoutPolicy}\")"; + builder.AppendLine($"[RequestTimeout{timeoutArgument}]"); + } + + if (disableRequestTimeout) + { + builder.AppendLine("[DisableRequestTimeout]"); + } + + if (orderValue != 0) + { + builder.AppendLine($"[Order({orderValue})]"); + } + + if (excludeFromDescription) + { + builder.AppendLine("[ExcludeFromDescription]"); + } + + builder.AppendLine("internal sealed class AuthorizationMatrixEndpoints"); + builder.AppendLine("{"); + builder.AppendLine(" [MapGet(\"/matrix/{id:int}\", Name = \"GetMatrix\")]"); + + if (methodAllowAnonymous) + { + builder.AppendLine(" [AllowAnonymous]"); + } + + if (methodRequireAuthorization) + { + builder.AppendLine(" [RequireAuthorization(\"MethodPolicy\")]"); + } + + if (methodTags) + { + builder.AppendLine(" [Tags(\"Method\", \"Matrix\")]"); + } + + if (!string.IsNullOrWhiteSpace(methodHost)) + { + builder.AppendLine($" [RequireHost(\"{methodHost}\", \"contoso.com\")]"); + } + + if (methodRequireCors) + { + var methodCors = string.IsNullOrWhiteSpace(methodCorsPolicy) ? string.Empty : $"(\"{methodCorsPolicy}\")"; + builder.AppendLine($" [RequireCors{methodCors}]"); + } + + if (requireRateLimiting) + { + var rateLimit = string.IsNullOrWhiteSpace(rateLimitingPolicy) ? string.Empty : $"(\"{rateLimitingPolicy}\")"; + builder.AppendLine($" [RequireRateLimiting{rateLimit}]"); + } + + if (methodDisableValidation) + { + builder.AppendLine(" [DisableValidation]"); + } + + builder.AppendLine(" public static Ok Handle(int id) => id >= 0 ? TypedResults.Ok() : TypedResults.Ok();"); + + if (!string.IsNullOrWhiteSpace(mapGroupPattern)) + { + builder.AppendLine(); + builder.AppendLine(" [MapDelete(\"/matrix/{id:int}\")]"); + builder.AppendLine(" public static Results Delete(int id)"); + builder.AppendLine(" => id >= 0 ? TypedResults.NoContent() : TypedResults.NotFound();"); + } + + builder.AppendLine("}"); + return builder.ToString(); + } + + public static string BuildConfigureAndFiltersSource( + bool configureWithServiceProvider, + bool configureAddsMetadata, + bool includeClassLevelFilter, + bool includeMethodLevelFilter, + bool includeGenericFilter, + bool configureRegistersFilter, + string metadataValue) + { + var builder = new StringBuilder(); + builder.AppendLine("using Microsoft.AspNetCore.Builder;"); + builder.AppendLine(); + + if (includeClassLevelFilter) + { + builder.AppendLine("[EndpointFilter(typeof(TimingFilter))]"); + } + + builder.AppendLine("internal static class ConfigureFilterEndpoints"); + builder.AppendLine("{"); + builder.AppendLine(" [MapGet(\"/configure-filters\")]"); + + if (includeMethodLevelFilter) + { + builder.AppendLine(" [EndpointFilter(typeof(ValidationFilter))]"); + } + + if (includeGenericFilter) + { + builder.AppendLine(" [EndpointFilter]"); + } + + builder.AppendLine(" public static Ok Handle() => TypedResults.Ok();"); + builder.AppendLine(); + builder.AppendLine(" public static void Configure(TBuilder builder" + (configureWithServiceProvider ? ", IServiceProvider services" : string.Empty) + ")"); + builder.AppendLine(" where TBuilder : IEndpointConventionBuilder"); + builder.AppendLine(" {"); + builder.AppendLine(" _ = builder;"); + + if (configureWithServiceProvider) + { + builder.AppendLine(" _ = services;"); + } + + if (configureAddsMetadata) + { + builder.AppendLine($" builder.WithMetadata(\"{metadataValue}\");"); + } + + if (configureRegistersFilter) + { + builder.AppendLine(" builder.AddEndpointFilterFactory((context, next) => next);"); + } + + builder.AppendLine(" }"); + builder.AppendLine("}"); + builder.AppendLine(); + builder.AppendLine("internal sealed class TimingFilter : IEndpointFilter"); + builder.AppendLine("{"); + builder.AppendLine(" public ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) => next(context);"); + builder.AppendLine("}"); + builder.AppendLine(); + builder.AppendLine("internal sealed class ValidationFilter : IEndpointFilter"); + builder.AppendLine("{"); + builder.AppendLine(" public ValueTask InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) => next(context);"); + builder.AppendLine("}"); + + return builder.ToString(); + } + + public static string BuildHttpMethodMatrixSource( + bool includeGet, + bool includePost, + bool includePut, + bool includeDelete, + bool includeOptions, + bool includeHead, + bool includePatch, + bool includeQuery, + bool includeTrace, + bool includeConnect, + bool includeMethodNameCollision) + { + var builder = new StringBuilder(); + builder.AppendLine("using Microsoft.AspNetCore.Mvc;"); + builder.AppendLine(); + builder.AppendLine("internal static class HttpMethodEndpoints"); + builder.AppendLine("{"); + + if (includeGet) + { + builder.AppendLine(" [MapGet(\"/matrix\")] public static Ok Get() => TypedResults.Ok();"); + } + + if (includePost) + { + builder.AppendLine(" [MapPost(\"/matrix\")] public static Created Post() => TypedResults.Created(\"/matrix/1\", \"Created\");"); + } + + if (includePut) + { + builder.AppendLine(" [MapPut(\"/matrix/{id:int}\")] public static Results Put(int id) => id > 0 ? TypedResults.NoContent() : TypedResults.NotFound();"); + } + + if (includeDelete) + { + builder.AppendLine(" [MapDelete(\"/matrix/{id:int}\")] public static IResult Delete(int id) => TypedResults.Ok();"); + } + + if (includeOptions) + { + builder.AppendLine(" [MapOptions(\"/matrix\")] public static IResult Options() => TypedResults.Ok();"); + } + + if (includeHead) + { + builder.AppendLine(" [MapHead(\"/matrix\")] public static IResult Head() => TypedResults.Ok();"); + } + + if (includePatch) + { + builder.AppendLine(" [MapPatch(\"/matrix/{id:int}\")] public static IResult Patch(int id) => TypedResults.Ok();"); + } + + if (includeQuery) + { + builder.AppendLine(" [MapQuery(\"/matrix/query\")] public static IResult Query([FromQuery] string value) => TypedResults.Ok(value);"); + } + + if (includeTrace) + { + builder.AppendLine(" [MapTrace(\"/matrix\")] public static IResult Trace() => TypedResults.Ok();"); + } + + if (includeConnect) + { + builder.AppendLine(" [MapConnect(\"/matrix\")] public static IResult Connect() => TypedResults.Ok();"); + } + + builder.AppendLine("}"); + + if (includeMethodNameCollision) + { + builder.AppendLine(); + builder.AppendLine("internal static class AlternateEndpoints"); + builder.AppendLine("{"); + builder.AppendLine(" [MapGet(\"/alternate\")] public static Ok Get() => TypedResults.Ok();"); + builder.AppendLine(" [MapPost(\"/alternate\")] public static IResult Post() => TypedResults.Ok();"); + builder.AppendLine("}"); + } + + return builder.ToString(); + } + + public static string BuildContractsAndBindingSource( + bool includeBindingNames, + bool includeAsParameters, + bool includeFromServices, + bool includeFromKeyedServices, + bool includeAccepts, + bool includeGenericAccepts, + bool includeProducesResponse, + bool includeProducesProblem, + bool includeProducesValidationProblem, + bool includeSummaryAndDescription, + bool includeDisplayName, + bool includeTags, + bool excludeFromDescription, + bool allowAnonymous, + bool methodRequiresAuthorization, + string? acceptsContentType1, + string? acceptsContentType2, + string? producesContentType1, + string? producesContentType2) + { + var builder = new StringBuilder(); + builder.AppendLine("using Microsoft.AspNetCore.Mvc;"); + builder.AppendLine("using Microsoft.Extensions.DependencyInjection;"); + builder.AppendLine(); + builder.AppendLine("internal sealed class ContractEndpoints"); + builder.AppendLine("{"); + + if (includeSummaryAndDescription) + { + builder.AppendLine(" [Summary(\"Gets detailed content.\")]"); + builder.AppendLine(" [Description(\"Shows binding and contract combinations.\")]"); + } + + if (includeDisplayName) + { + builder.AppendLine(" [DisplayName(\"Contract endpoint\")]"); + } + + if (includeTags) + { + builder.AppendLine(" [Tags(\"Contracts\", \"Bindings\")]"); + } + + if (excludeFromDescription) + { + builder.AppendLine(" [ExcludeFromDescription]"); + } + + if (allowAnonymous) + { + builder.AppendLine(" [AllowAnonymous]"); + } + + if (methodRequiresAuthorization) + { + builder.AppendLine(" [RequireAuthorization(\"ContractsPolicy\")]"); + } + + builder.AppendLine(" [MapGet(\"/contracts/{id:int}\")]"); + + if (includeAccepts) + { + var secondContentType = string.IsNullOrWhiteSpace(acceptsContentType2) ? string.Empty : $", \"{acceptsContentType2}\""; + builder.AppendLine($" [Accepts(\"{acceptsContentType1 ?? "application/json"}\"{secondContentType})]"); + } + + if (includeGenericAccepts) + { + builder.AppendLine($" [Accepts(\"{acceptsContentType1 ?? "application/json"}\")]"); + } + + if (includeProducesResponse) + { + var secondProduces = string.IsNullOrWhiteSpace(producesContentType2) ? string.Empty : $", \"{producesContentType2}\""; + builder.AppendLine($" [ProducesResponse(200, \"{producesContentType1 ?? "application/json"}\"{secondProduces}, ResponseType = typeof(ResponseRecord))]"); + } + + if (includeProducesProblem) + { + builder.AppendLine($" [ProducesProblem(500, \"{producesContentType1 ?? "application/problem+json"}\")]"); + } + + if (includeProducesValidationProblem) + { + builder.AppendLine($" [ProducesValidationProblem(422, \"{producesContentType1 ?? "application/problem+json"}\")]"); + } + + builder.AppendLine(" public static async Task, NotFound>> Handle("); + builder.AppendLine(includeBindingNames + ? " [FromRoute(Name = \"route-id\")] int id," + : " [FromRoute] int id,"); + builder.AppendLine(includeBindingNames + ? " [FromQuery(Name = \"filter-term\")] string? filter," + : " [FromQuery] string? filter,"); + builder.AppendLine(includeBindingNames + ? " [FromHeader(Name = \"x-trace-id\")] string? traceId," + : " [FromHeader] string? traceId,"); + builder.AppendLine(" [FromBody] RequestRecord request,"); + + if (includeAsParameters) + { + builder.AppendLine(" [AsParameters] AdditionalParameters parameters,"); + } + + if (includeFromServices) + { + builder.AppendLine(" [FromServices] IServiceProvider services,"); + } + + if (includeFromKeyedServices) + { + builder.AppendLine(" [FromKeyedServices(\"special\")] object keyed,"); + } + + builder.AppendLine(" CancellationToken cancellationToken)"); + builder.AppendLine(" {"); + builder.AppendLine(" await Task.Yield();"); + builder.AppendLine(" cancellationToken.ThrowIfCancellationRequested();"); + builder.AppendLine(" return id > 0 ? TypedResults.Ok(new ResponseRecord(id)) : TypedResults.NotFound();"); + builder.AppendLine(" }"); + builder.AppendLine("}"); + builder.AppendLine(); + builder.AppendLine("internal sealed record RequestRecord(int Value);"); + builder.AppendLine("internal sealed record ResponseRecord(int Value);"); + + if (includeAsParameters) + { + builder.AppendLine("internal sealed record AdditionalParameters(string? Search, int? Page);"); + } + + return builder.ToString(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/Common/TestHelpers.cs b/tests/GeneratedEndpoints.Tests/Common/TestHelpers.cs index bfc4486..8771b24 100644 --- a/tests/GeneratedEndpoints.Tests/Common/TestHelpers.cs +++ b/tests/GeneratedEndpoints.Tests/Common/TestHelpers.cs @@ -9,22 +9,28 @@ public static class TestHelpers { public static GeneratorDriverRunResult RunGenerator(IEnumerable sources) { - var cSharpParseOptions = new CSharpParseOptions(LanguageVersion.CSharp11).WithPreprocessorSymbols("NET7_0_OR_GREATER"); + var cSharpParseOptions = new CSharpParseOptions(LanguageVersion.CSharp11).WithPreprocessorSymbols("NET10_0_OR_GREATER"); var cSharpCompilationOptions = new CSharpCompilationOptions(OutputKind.NetModule).WithNullableContextOptions(NullableContextOptions.Enable); - return IncrementalGenerator.Run(sources, cSharpParseOptions, ReferenceAssemblies.Net80, cSharpCompilationOptions); + var (_, result) = IncrementalGenerator.RunWithDiagnostics(sources, cSharpParseOptions, AspNet100.References.All, cSharpCompilationOptions); + return result; } public static IEnumerable GetSources(string source, bool withNamespace) { const string usingStatements = """ - + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Generated.Attributes; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Http.HttpResults; + using Microsoft.AspNetCore.Routing; + using System.ComponentModel; """; if (withNamespace) yield return $""" {usingStatements} - namespace EntityFrameworkGeneratorTests; + namespace GeneratedEndpointsTests; {source} """; diff --git a/tests/GeneratedEndpoints.Tests/GeneratedEndpoints.Tests.csproj b/tests/GeneratedEndpoints.Tests/GeneratedEndpoints.Tests.csproj index 3f873a6..1f74d48 100644 --- a/tests/GeneratedEndpoints.Tests/GeneratedEndpoints.Tests.csproj +++ b/tests/GeneratedEndpoints.Tests/GeneratedEndpoints.Tests.csproj @@ -1,7 +1,7 @@ - net9.0 + net10.0 enable enable latest @@ -10,25 +10,24 @@ - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + @@ -39,103 +38,4 @@ - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - DbContextTests - ServiceLifetimeTests.cs - - - diff --git a/tests/GeneratedEndpoints.Tests/GeneratedEndpointsTests.cs b/tests/GeneratedEndpoints.Tests/GeneratedEndpointsTests.cs deleted file mode 100644 index 9cd63d6..0000000 --- a/tests/GeneratedEndpoints.Tests/GeneratedEndpointsTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using GeneratedEndpoints.Tests.Common; -using SourceGeneratorTestHelpers.XUnit; - -namespace GeneratedEndpoints.Tests; - -[UsesVerify] -public class GeneratedEndpointsTests -{ - public GeneratedEndpointsTests() - { - ModuleInitializer.Initialize(); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task MapGet(bool withNamespace) - { - var sources = TestHelpers.GetSources( - """ - - """, - withNamespace - ); - var result = TestHelpers.RunGenerator(sources); - - //await result.VerifyAsync("GeneratedSource.g.cs").UseMethodName($"{nameof(UsingDbSets)}_With{(withNamespace ? "" : "out")}Namespace"); - } -} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_257E8A8FA30F_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_257E8A8FA30F_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_257E8A8FA30F_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_257E8A8FA30F_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_257E8A8FA30F_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..31c3fd8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_257E8A8FA30F_MapEndpointHandlers.verified.txt @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.RateLimiting; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + var _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group = builder.MapGroup("") + .WithGroupName("Docs") + .WithOrder(-5) + .ExcludeFromDescription() + .RequireCors() + .RequireHost("api.alt.com") + .DisableRequestTimeout(); + + _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithTags("Method", "Matrix") + .RequireAuthorization("MethodPolicy") + .RequireCors("MethodCors") + .RequireRateLimiting("BurstPolicy") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_25B2AC35B582_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_25B2AC35B582_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_25B2AC35B582_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_25B2AC35B582_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_25B2AC35B582_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..4397c69 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_25B2AC35B582_MapEndpointHandlers.verified.txt @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.RateLimiting; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + var _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group = builder.MapGroup("") + .WithGroupName("Reporting") + .WithOrder(5) + .ExcludeFromDescription() + .WithTags("Class", "Matrix") + .RequireAuthorization("ClassPolicy") + .RequireCors("NamedCorsPolicy") + .RequireHost("*.contoso.com") + .AllowAnonymous() + .ShortCircuit() + .WithRequestTimeout("TimeoutPolicy"); + + _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithTags("Method", "Matrix") + .RequireHost("api.contoso.com", "contoso.com") + .RequireRateLimiting("RatePolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_4F441534B0BD_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_4F441534B0BD_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_4F441534B0BD_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_4F441534B0BD_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_4F441534B0BD_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..ae4b564 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_4F441534B0BD_MapEndpointHandlers.verified.txt @@ -0,0 +1,43 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + var _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group = builder.MapGroup("") + .WithGroupName("Operations") + .ExcludeFromDescription() + .WithTags("Class", "Matrix") + .RequireAuthorization("ClassPolicy") + .RequireCors() + .RequireHost("*.example.com") + .AllowAnonymous() + .DisableRequestTimeout(); + + _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireAuthorization("MethodPolicy") + .RequireCors() + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_6F94B85A7155_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_6F94B85A7155_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..82cb438 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_6F94B85A7155_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_6F94B85A7155_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_6F94B85A7155_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..ed92292 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_6F94B85A7155_MapEndpointHandlers.verified.txt @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithOrder(-1) + .WithTags("Method", "Matrix") + .RequireAuthorization("MethodPolicy") + .RequireCors("MethodCors") + .RequireHost("services.contoso.com", "contoso.com") + .AllowAnonymous() + .DisableRequestTimeout(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_9D6575ECE261_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_9D6575ECE261_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..82cb438 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_9D6575ECE261_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_9D6575ECE261_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_9D6575ECE261_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..158db91 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.AuthorizationAndMetadataMatrix_9D6575ECE261_MapEndpointHandlers.verified.txt @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithOrder(10) + .WithTags("Class", "Matrix") + .RequireAuthorization("ClassPolicy") + .RequireHost("*.alt.com", "contoso.com") + .ShortCircuit(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_25B08C7DE832_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_25B08C7DE832_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_25B08C7DE832_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_25B08C7DE832_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_25B08C7DE832_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d1abab8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_25B08C7DE832_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + .AddEndpointFilter(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_401A05F2C177_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_401A05F2C177_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_401A05F2C177_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_401A05F2C177_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_401A05F2C177_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d1abab8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_401A05F2C177_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + .AddEndpointFilter(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_A172502B995B_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_A172502B995B_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_A172502B995B_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_A172502B995B_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_A172502B995B_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..addcc95 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_A172502B995B_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_B46DF1784969_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_B46DF1784969_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_B46DF1784969_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_B46DF1784969_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_B46DF1784969_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..146556a --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_B46DF1784969_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/configure-filters", global::ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_EFC1A0B7E7CE_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_EFC1A0B7E7CE_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_EFC1A0B7E7CE_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_EFC1A0B7E7CE_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_EFC1A0B7E7CE_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..f5054db --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ConfigureAndFiltersMatrix_EFC1A0B7E7CE_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_8330CA9A1CFC_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_8330CA9A1CFC_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_8330CA9A1CFC_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_8330CA9A1CFC_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_8330CA9A1CFC_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..493d722 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_8330CA9A1CFC_MapEndpointHandlers.verified.txt @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .WithDisplayName("Contract endpoint") + .WithSummary("Gets detailed content.") + .WithDescription("Shows binding and contract combinations.") + .Accepts("application/json") + .ProducesValidationProblem(422, "application/problem+json") + .RequireAuthorization("ContractsPolicy") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_89F17B97AFD0_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_89F17B97AFD0_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..7a6643b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_89F17B97AFD0_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_89F17B97AFD0_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_89F17B97AFD0_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..429595c --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_89F17B97AFD0_MapEndpointHandlers.verified.txt @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::ContractEndpoints.Handle) + .WithName("Handle") + .ExcludeFromDescription() + .WithTags("Contracts", "Bindings") + .Produces(200, "application/problem+json") + .ProducesProblem(500, "application/problem+json") + .RequireAuthorization("ContractsPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F5FE6E1F139_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F5FE6E1F139_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F5FE6E1F139_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F5FE6E1F139_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F5FE6E1F139_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..70f58ad --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F5FE6E1F139_MapEndpointHandlers.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .WithDisplayName("Contract endpoint") + .WithSummary("Gets detailed content.") + .WithDescription("Shows binding and contract combinations.") + .WithTags("Contracts", "Bindings") + .Accepts("application/xml") + .Produces(200, "application/json", "text/json") + .ProducesProblem(500, "application/json") + .ProducesValidationProblem(422, "application/json") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F7075874154_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F7075874154_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..7a6643b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F7075874154_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F7075874154_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F7075874154_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..810b914 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_9F7075874154_MapEndpointHandlers.verified.txt @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::ContractEndpoints.Handle) + .WithName("Handle") + .WithDisplayName("Contract endpoint") + .ExcludeFromDescription() + .Produces(200, "application/json") + .ProducesValidationProblem(422, "application/json") + .RequireAuthorization("ContractsPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_DDC9B964FDBC_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_DDC9B964FDBC_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_DDC9B964FDBC_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_DDC9B964FDBC_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_DDC9B964FDBC_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..f4393e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.ContractsAndBindingMatrix_DDC9B964FDBC_MapEndpointHandlers.verified.txt @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .WithSummary("Gets detailed content.") + .WithDescription("Shows binding and contract combinations.") + .WithTags("Contracts", "Bindings") + .Accepts("application/json") + .ProducesProblem(500, "application/problem+json") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_346DFFBCB949_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_346DFFBCB949_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_346DFFBCB949_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_346DFFBCB949_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_346DFFBCB949_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..aaac7d8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_346DFFBCB949_MapEndpointHandlers.verified.txt @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/alternate", global::GeneratedEndpointsTests.AlternateEndpoints.Get) + .WithName("GeneratedEndpointsTests.AlternateEndpoints.Get"); + + builder.MapPost("/alternate", global::GeneratedEndpointsTests.AlternateEndpoints.Post) + .WithName("Post"); + + builder.MapMethods("/matrix", new[] { "CONNECT" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Connect) + .WithName("Connect"); + + builder.MapDelete("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Delete) + .WithName("Delete"); + + builder.MapGet("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Get) + .WithName("GeneratedEndpointsTests.HttpMethodEndpoints.Get"); + + builder.MapMethods("/matrix", new[] { "HEAD" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Head) + .WithName("Head"); + + builder.MapMethods("/matrix/query", new[] { "QUERY" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Query) + .WithName("Query"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_434E7BEC9B3F_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_434E7BEC9B3F_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_434E7BEC9B3F_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_434E7BEC9B3F_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_434E7BEC9B3F_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..05e9faf --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_434E7BEC9B3F_MapEndpointHandlers.verified.txt @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix", new[] { "CONNECT" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Connect) + .WithName("Connect"); + + builder.MapDelete("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Delete) + .WithName("Delete"); + + builder.MapGet("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Get) + .WithName("Get"); + + builder.MapMethods("/matrix", new[] { "HEAD" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Head) + .WithName("Head"); + + builder.MapMethods("/matrix", new[] { "OPTIONS" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Options) + .WithName("Options"); + + builder.MapPatch("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Patch) + .WithName("Patch"); + + builder.MapPost("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Post) + .WithName("Post"); + + builder.MapPut("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Put) + .WithName("Put"); + + builder.MapMethods("/matrix/query", new[] { "QUERY" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Query) + .WithName("Query"); + + builder.MapMethods("/matrix", new[] { "TRACE" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Trace) + .WithName("Trace"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_541EF512DD7F_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_541EF512DD7F_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_541EF512DD7F_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_541EF512DD7F_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_541EF512DD7F_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..01e9c67 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_541EF512DD7F_MapEndpointHandlers.verified.txt @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix", new[] { "OPTIONS" }, global::HttpMethodEndpoints.Options) + .WithName("Options"); + + builder.MapPatch("/matrix/{id:int}", global::HttpMethodEndpoints.Patch) + .WithName("Patch"); + + builder.MapPost("/matrix", global::HttpMethodEndpoints.Post) + .WithName("Post"); + + builder.MapPut("/matrix/{id:int}", global::HttpMethodEndpoints.Put) + .WithName("Put"); + + builder.MapMethods("/matrix", new[] { "TRACE" }, global::HttpMethodEndpoints.Trace) + .WithName("Trace"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_DC18F4695C80_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_DC18F4695C80_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_DC18F4695C80_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_DC18F4695C80_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_DC18F4695C80_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..9569a2a --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_DC18F4695C80_MapEndpointHandlers.verified.txt @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/alternate", global::AlternateEndpoints.Get) + .WithName("AlternateEndpoints.Get"); + + builder.MapPost("/alternate", global::AlternateEndpoints.Post) + .WithName("Post"); + + builder.MapMethods("/matrix", new[] { "CONNECT" }, global::HttpMethodEndpoints.Connect) + .WithName("Connect"); + + builder.MapDelete("/matrix/{id:int}", global::HttpMethodEndpoints.Delete) + .WithName("Delete"); + + builder.MapGet("/matrix", global::HttpMethodEndpoints.Get) + .WithName("HttpMethodEndpoints.Get"); + + builder.MapMethods("/matrix", new[] { "HEAD" }, global::HttpMethodEndpoints.Head) + .WithName("Head"); + + builder.MapMethods("/matrix/query", new[] { "QUERY" }, global::HttpMethodEndpoints.Query) + .WithName("Query"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_F1EDE56BC773_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_F1EDE56BC773_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_F1EDE56BC773_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_F1EDE56BC773_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_F1EDE56BC773_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..1d6e6bc --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.HttpMethodMatrix_F1EDE56BC773_MapEndpointHandlers.verified.txt @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/alternate", global::GeneratedEndpointsTests.AlternateEndpoints.Get) + .WithName("Get"); + + builder.MapPost("/alternate", global::GeneratedEndpointsTests.AlternateEndpoints.Post) + .WithName("GeneratedEndpointsTests.AlternateEndpoints.Post"); + + builder.MapMethods("/matrix", new[] { "OPTIONS" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Options) + .WithName("Options"); + + builder.MapPatch("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Patch) + .WithName("Patch"); + + builder.MapPost("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Post) + .WithName("GeneratedEndpointsTests.HttpMethodEndpoints.Post"); + + builder.MapPut("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Put) + .WithName("Put"); + + builder.MapMethods("/matrix", new[] { "TRACE" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Trace) + .WithName("Trace"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_370EBA0910FD_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_370EBA0910FD_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_370EBA0910FD_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_370EBA0910FD_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_370EBA0910FD_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..0b8b70e --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_370EBA0910FD_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapFallback(global::FallbackEndpoints.Default) + .WithName("Default"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_50C6E889EAF2_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_50C6E889EAF2_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_50C6E889EAF2_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_50C6E889EAF2_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_50C6E889EAF2_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..52cf3bb --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_50C6E889EAF2_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapFallback("/alternate-fallback", global::GeneratedEndpointsTests.FallbackEndpoints.Custom) + .WithName("Custom"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_517225B7419F_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_517225B7419F_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_517225B7419F_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_517225B7419F_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_517225B7419F_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..58b2353 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_517225B7419F_MapEndpointHandlers.verified.txt @@ -0,0 +1,28 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_61D3AB7FBEBA_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_61D3AB7FBEBA_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_61D3AB7FBEBA_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_61D3AB7FBEBA_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_61D3AB7FBEBA_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..0740514 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_61D3AB7FBEBA_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapFallback("/custom-fallback", global::GeneratedEndpointsTests.FallbackEndpoints.Custom) + .WithName("Custom"); + + builder.MapFallback(global::GeneratedEndpointsTests.FallbackEndpoints.Default) + .WithName("Default"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_A7D17F3BAD82_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_A7D17F3BAD82_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_A7D17F3BAD82_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_A7D17F3BAD82_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_A7D17F3BAD82_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..9a20c14 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.MapFallbackScenarios_A7D17F3BAD82_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapFallback("/custom-only", global::FallbackEndpoints.Custom) + .WithName("Custom"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.cs b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.cs new file mode 100644 index 0000000..430d05b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/GeneratedSourceTests.cs @@ -0,0 +1,294 @@ +using GeneratedEndpoints.Tests.Common; +using SourceGeneratorTestHelpers.XUnit; + +namespace GeneratedEndpoints.Tests; + +[UsesVerify] +public class GeneratedSourceTests +{ + public GeneratedSourceTests() + { + ModuleInitializer.Initialize(); + } + + [Theory] + [InlineData(true, true, true, "/custom-fallback")] + [InlineData(false, true, false, null)] + [InlineData(true, false, true, "/alternate-fallback")] + [InlineData(false, false, true, "/custom-only")] + [InlineData(true, false, false, null)] + public async Task MapFallbackScenarios(bool withNamespace, bool includeDefaultFallback, bool includeCustomFallback, string? customRoute) + { + var sources = TestHelpers.GetSources(SourceFactory.BuildFallbackSource(includeDefaultFallback, includeCustomFallback, customRoute), withNamespace); + var result = TestHelpers.RunGenerator(sources); + var scenario = ScenarioNamer.Create(nameof(MapFallbackScenarios), + ("Namespace", withNamespace), + ("Default", includeDefaultFallback), + ("Custom", includeCustomFallback), + ("Route", customRoute ?? "default")); + + await result.VerifyAsync("AddEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_AddEndpointHandlers"); + + await result.VerifyAsync("MapEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_MapEndpointHandlers"); + } + + [Theory] + [InlineData(true, true, false, true, false, true, true, "*.contoso.com", "api.contoso.com", true, "NamedCorsPolicy", false, null, true, "RatePolicy", true, true, "TimeoutPolicy", false, 5, "Reporting", true)] + [InlineData(false, false, true, false, true, false, true, null, "services.contoso.com", false, null, true, "MethodCors", true, null, false, false, null, true, -1, null, false)] + [InlineData(true, true, true, true, true, true, false, "*.example.com", null, true, null, true, null, false, null, false, true, null, true, 0, "Operations", true)] + [InlineData(false, false, false, true, false, true, false, null, "*.alt.com", false, "CorsDefault", false, null, false, null, true, false, null, false, 10, null, false)] + [InlineData(true, false, true, false, true, false, true, "api.alt.com", null, true, null, true, "MethodCors", true, "BurstPolicy", false, true, "TimeoutPolicy", true, -5, "Docs", true)] + public async Task AuthorizationAndMetadataMatrix( + bool withNamespace, + bool classAllowAnonymous, + bool methodAllowAnonymous, + bool classRequireAuthorization, + bool methodRequireAuthorization, + bool classTags, + bool methodTags, + string? classHost, + string? methodHost, + bool classRequireCors, + string? classCorsPolicy, + bool methodRequireCors, + string? methodCorsPolicy, + bool requireRateLimiting, + string? rateLimitingPolicy, + bool applyShortCircuit, + bool applyRequestTimeout, + string? requestTimeoutPolicy, + bool disableRequestTimeout, + int orderValue, + string? groupName, + bool excludeFromDescription) + { + var source = SourceFactory.BuildAuthorizationMatrixSource( + classAllowAnonymous, + methodAllowAnonymous, + classRequireAuthorization, + methodRequireAuthorization, + classTags, + methodTags, + classHost, + methodHost, + classRequireCors, + classCorsPolicy, + methodRequireCors, + methodCorsPolicy, + requireRateLimiting, + rateLimitingPolicy, + applyShortCircuit, + applyRequestTimeout, + requestTimeoutPolicy, + disableRequestTimeout, + orderValue, + groupName, + excludeFromDescription); + + var sources = TestHelpers.GetSources(source, withNamespace); + var result = TestHelpers.RunGenerator(sources); + var scenario = ScenarioNamer.Create(nameof(AuthorizationAndMetadataMatrix), + ("Namespace", withNamespace), + ("ClassAnon", classAllowAnonymous), + ("MethodAnon", methodAllowAnonymous), + ("ClassAuth", classRequireAuthorization), + ("MethodAuth", methodRequireAuthorization), + ("ClassTags", classTags), + ("MethodTags", methodTags), + ("ClassHost", classHost ?? "none"), + ("MethodHost", methodHost ?? "none"), + ("ClassCors", classRequireCors), + ("MethodCors", methodRequireCors), + ("RateLimit", requireRateLimiting), + ("ShortCircuit", applyShortCircuit), + ("RequestTimeout", applyRequestTimeout), + ("DisableTimeout", disableRequestTimeout), + ("Order", orderValue), + ("Group", groupName ?? "none"), + ("Exclude", excludeFromDescription)); + + await result.VerifyAsync("AddEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_AddEndpointHandlers"); + + await result.VerifyAsync("MapEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_MapEndpointHandlers"); + } + + [Theory] + [InlineData(true, true, true, true, true, true, true, "configured")] + [InlineData(false, false, true, false, true, false, true, "timed")] + [InlineData(true, true, false, true, false, true, false, "metadata")] + [InlineData(false, true, false, false, false, true, false, "analytics")] + [InlineData(true, false, false, true, false, false, true, "telemetry")] + public async Task ConfigureAndFiltersMatrix( + bool withNamespace, + bool configureWithServiceProvider, + bool configureAddsMetadata, + bool includeClassLevelFilter, + bool includeMethodLevelFilter, + bool includeGenericFilter, + bool configureRegistersFilter, + string metadataValue) + { + var source = SourceFactory.BuildConfigureAndFiltersSource( + configureWithServiceProvider, + configureAddsMetadata, + includeClassLevelFilter, + includeMethodLevelFilter, + includeGenericFilter, + configureRegistersFilter, + metadataValue); + + var sources = TestHelpers.GetSources(source, withNamespace); + var result = TestHelpers.RunGenerator(sources); + var scenario = ScenarioNamer.Create(nameof(ConfigureAndFiltersMatrix), + ("Namespace", withNamespace), + ("SvcProvider", configureWithServiceProvider), + ("Metadata", configureAddsMetadata), + ("ClassFilter", includeClassLevelFilter), + ("MethodFilter", includeMethodLevelFilter), + ("GenericFilter", includeGenericFilter), + ("ConfigureFilter", configureRegistersFilter), + ("Value", metadataValue)); + + await result.VerifyAsync("AddEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_AddEndpointHandlers"); + + await result.VerifyAsync("MapEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_MapEndpointHandlers"); + } + + [Theory] + [InlineData(true, true, true, true, true, true, true, true, true, true, true, false)] + [InlineData(false, true, false, false, true, false, true, false, true, false, true, true)] + [InlineData(true, false, true, true, false, true, false, true, false, true, false, true)] + [InlineData(false, false, true, true, false, true, false, true, false, true, false, false)] + [InlineData(true, true, false, false, true, false, true, false, true, false, true, true)] + public async Task HttpMethodMatrix( + bool withNamespace, + bool includeGet, + bool includePost, + bool includePut, + bool includeDelete, + bool includeOptions, + bool includeHead, + bool includePatch, + bool includeQuery, + bool includeTrace, + bool includeConnect, + bool includeMethodNameCollision) + { + var source = SourceFactory.BuildHttpMethodMatrixSource( + includeGet, + includePost, + includePut, + includeDelete, + includeOptions, + includeHead, + includePatch, + includeQuery, + includeTrace, + includeConnect, + includeMethodNameCollision); + + var sources = TestHelpers.GetSources(source, withNamespace); + var result = TestHelpers.RunGenerator(sources); + var scenario = ScenarioNamer.Create(nameof(HttpMethodMatrix), + ("Namespace", withNamespace), + ("Get", includeGet), + ("Post", includePost), + ("Put", includePut), + ("Delete", includeDelete), + ("Options", includeOptions), + ("Head", includeHead), + ("Patch", includePatch), + ("Query", includeQuery), + ("Trace", includeTrace), + ("Connect", includeConnect), + ("Collision", includeMethodNameCollision)); + + await result.VerifyAsync("AddEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_AddEndpointHandlers"); + + await result.VerifyAsync("MapEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_MapEndpointHandlers"); + } + + [Theory] + [InlineData(true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, false, "application/xml", "text/xml", "application/json", "text/json")] + [InlineData(false, false, true, false, false, true, false, true, true, false, false, false, true, true, false, true, "application/custom", null, "application/problem+json", null)] + [InlineData(true, true, false, true, true, false, true, false, false, true, true, true, false, false, true, true, null, null, null, null)] + [InlineData(false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, "application/xml", null, "application/json", null)] + [InlineData(true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false, null, "text/plain", null, "text/plain")] + public async Task ContractsAndBindingMatrix( + bool withNamespace, + bool includeBindingNames, + bool includeAsParameters, + bool includeFromServices, + bool includeFromKeyedServices, + bool includeAccepts, + bool includeGenericAccepts, + bool includeProducesResponse, + bool includeProducesProblem, + bool includeProducesValidationProblem, + bool includeSummaryAndDescription, + bool includeDisplayName, + bool includeTags, + bool excludeFromDescription, + bool allowAnonymous, + bool methodRequiresAuthorization, + string? acceptsContentType1, + string? acceptsContentType2, + string? producesContentType1, + string? producesContentType2) + { + var source = SourceFactory.BuildContractsAndBindingSource( + includeBindingNames, + includeAsParameters, + includeFromServices, + includeFromKeyedServices, + includeAccepts, + includeGenericAccepts, + includeProducesResponse, + includeProducesProblem, + includeProducesValidationProblem, + includeSummaryAndDescription, + includeDisplayName, + includeTags, + excludeFromDescription, + allowAnonymous, + methodRequiresAuthorization, + acceptsContentType1, + acceptsContentType2, + producesContentType1, + producesContentType2); + + var sources = TestHelpers.GetSources(source, withNamespace); + var result = TestHelpers.RunGenerator(sources); + var scenario = ScenarioNamer.Create(nameof(ContractsAndBindingMatrix), + ("Namespace", withNamespace), + ("BindingNames", includeBindingNames), + ("AsParameters", includeAsParameters), + ("Services", includeFromServices), + ("KeyedServices", includeFromKeyedServices), + ("Accepts", includeAccepts), + ("GenericAccepts", includeGenericAccepts), + ("Produces", includeProducesResponse), + ("Problem", includeProducesProblem), + ("Validation", includeProducesValidationProblem), + ("Summary", includeSummaryAndDescription), + ("DisplayName", includeDisplayName), + ("Tags", includeTags), + ("Exclude", excludeFromDescription), + ("AllowAnon", allowAnonymous), + ("MethodAuth", methodRequiresAuthorization)); + + await result.VerifyAsync("AddEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_AddEndpointHandlers"); + + await result.VerifyAsync("MapEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_MapEndpointHandlers"); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsAttribute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsAttribute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsAttribute_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsAttribute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsAttribute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d8a37e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsAttribute_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsMultipleContentTypes_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsMultipleContentTypes_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsMultipleContentTypes_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsMultipleContentTypes_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsMultipleContentTypes_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d8a37e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AcceptsMultipleContentTypes_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AsParameters_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AsParameters_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AsParameters_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AsParameters_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AsParameters_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d8a37e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AsParameters_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AsyncMethodVariants_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AsyncMethodVariants_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..fe15aef --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AsyncMethodVariants_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.AsyncMethodVariants_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.AsyncMethodVariants_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..2d957e5 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.AsyncMethodVariants_MapEndpointHandlers.verified.txt @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/task", static ([FromServices] global::GeneratedEndpointsTests.AsyncHandlerEndpoints handler) => handler.TaskOnly()) + .WithName("TaskOnly"); + + builder.MapGet("/task-result", static async ([FromServices] global::GeneratedEndpointsTests.AsyncHandlerEndpoints handler, int id) => await handler.TaskWithResult(id)) + .WithName("TaskWithResult"); + + builder.MapPost("/valuetask", static ([FromServices] global::GeneratedEndpointsTests.AsyncHandlerEndpoints handler) => handler.ValueTaskOnly()) + .WithName("ValueTaskOnly"); + + builder.MapPost("/valuetask-result", static async ([FromServices] global::GeneratedEndpointsTests.AsyncHandlerEndpoints handler, int id) => await handler.ValueTaskWithResult(id)) + .WithName("ValueTaskWithResult"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.BindingNames_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.BindingNames_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.BindingNames_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.BindingNames_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.BindingNames_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d8a37e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.BindingNames_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassAllowAnonymous_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassAllowAnonymous_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassAllowAnonymous_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassAllowAnonymous_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassAllowAnonymous_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..b915326 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassAllowAnonymous_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassDisableValidation_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassDisableValidation_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassDisableValidation_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassDisableValidation_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassDisableValidation_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..e00e76c --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassDisableValidation_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .DisableValidation() +; + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassEndpointFilter_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassEndpointFilter_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassEndpointFilter_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassEndpointFilter_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassEndpointFilter_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..f5054db --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassEndpointFilter_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassMapGroup_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassMapGroup_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassMapGroup_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassMapGroup_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassMapGroup_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..ca2a016 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassMapGroup_MapEndpointHandlers.verified.txt @@ -0,0 +1,46 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + var _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group = builder.MapGroup("/individuals") + .WithGroupName("ClassGroup") + .WithOrder(2) + .ExcludeFromDescription() + .WithTags("Class", "Matrix") + .RequireAuthorization("ClassPolicy") + .RequireCors("ClassCors") + .RequireHost("*.individual.com") + .ShortCircuit() + .WithRequestTimeout("ClassTimeout"); + + _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group.MapDelete("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Delete) + .WithName("Delete"); + + _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithTags("Method", "Matrix") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireAuthorization_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireAuthorization_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireAuthorization_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireAuthorization_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireAuthorization_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..b9fafc7 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireAuthorization_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireAuthorization("ClassPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCorsWithPolicy_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCorsWithPolicy_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCorsWithPolicy_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCorsWithPolicy_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCorsWithPolicy_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..a8be8e1 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCorsWithPolicy_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireCors("ClassPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCors_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCors_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCors_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCors_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCors_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d51e223 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireCors_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireCors(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireHost_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireHost_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireHost_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireHost_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireHost_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..f92ec88 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassRequireHost_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireHost("*.individual.com"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassTags_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassTags_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassTags_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ClassTags_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassTags_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..b0d8c5b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ClassTags_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithTags("Class", "Matrix"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureAddsMetadata_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureAddsMetadata_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureAddsMetadata_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureAddsMetadata_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureAddsMetadata_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..c9d22a2 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureAddsMetadata_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureRegistersFilter_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureRegistersFilter_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureRegistersFilter_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureRegistersFilter_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureRegistersFilter_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..c9d22a2 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureRegistersFilter_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureWithServiceProvider_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureWithServiceProvider_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureWithServiceProvider_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureWithServiceProvider_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureWithServiceProvider_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..f2d6a1e --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ConfigureWithServiceProvider_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractAllowAnonymous_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractAllowAnonymous_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractAllowAnonymous_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractAllowAnonymous_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractAllowAnonymous_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..b57ea21 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractAllowAnonymous_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractExcludeFromDescription_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractExcludeFromDescription_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractExcludeFromDescription_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractExcludeFromDescription_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractExcludeFromDescription_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..4eef24f --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractExcludeFromDescription_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .ExcludeFromDescription(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractRequireAuthorization_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractRequireAuthorization_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractRequireAuthorization_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractRequireAuthorization_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractRequireAuthorization_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..bbf9302 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractRequireAuthorization_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .RequireAuthorization("ContractsPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractTags_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractTags_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractTags_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ContractTags_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractTags_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..ec5e1f1 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ContractTags_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .WithTags("Contracts", "Bindings"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.CustomFallbackRoute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.CustomFallbackRoute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.CustomFallbackRoute_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.CustomFallbackRoute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.CustomFallbackRoute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..ae10c4a --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.CustomFallbackRoute_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapFallback("/custom-individual", global::GeneratedEndpointsTests.FallbackEndpoints.Custom) + .WithName("Custom"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.DefaultFallbackOnly_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.DefaultFallbackOnly_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.DefaultFallbackOnly_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.DefaultFallbackOnly_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.DefaultFallbackOnly_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..24a42e8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.DefaultFallbackOnly_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapFallback(global::GeneratedEndpointsTests.FallbackEndpoints.Default) + .WithName("Default"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.DisableRequestTimeout_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.DisableRequestTimeout_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.DisableRequestTimeout_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.DisableRequestTimeout_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.DisableRequestTimeout_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..a6e6acc --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.DisableRequestTimeout_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .DisableRequestTimeout(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.DisplayNameAttribute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.DisplayNameAttribute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.DisplayNameAttribute_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.DisplayNameAttribute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.DisplayNameAttribute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..2d0e525 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.DisplayNameAttribute_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .WithDisplayName("Contract endpoint"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ExcludeFromDescription_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ExcludeFromDescription_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ExcludeFromDescription_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ExcludeFromDescription_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ExcludeFromDescription_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..dd3f8e8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ExcludeFromDescription_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .ExcludeFromDescription(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.FromKeyedServices_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.FromKeyedServices_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.FromKeyedServices_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.FromKeyedServices_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.FromKeyedServices_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d8a37e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.FromKeyedServices_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.FromServices_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.FromServices_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.FromServices_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.FromServices_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.FromServices_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d8a37e9 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.FromServices_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.GenericAcceptsAttribute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericAcceptsAttribute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericAcceptsAttribute_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.GenericAcceptsAttribute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericAcceptsAttribute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..dd03570 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericAcceptsAttribute_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .Accepts("application/vnd.generic"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.GenericEndpointFilter_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericEndpointFilter_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericEndpointFilter_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.GenericEndpointFilter_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericEndpointFilter_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..3fddf3b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.GenericEndpointFilter_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.GroupName_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.GroupName_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.GroupName_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.GroupName_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.GroupName_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..32df90b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.GroupName_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + var _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group = builder.MapGroup("") + .WithGroupName("IndividualGroup"); + + _GeneratedEndpointsTests_AuthorizationMatrixEndpoints_Group.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapConnectEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapConnectEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapConnectEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapConnectEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapConnectEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..7b99827 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapConnectEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix", new[] { "CONNECT" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Connect) + .WithName("Connect"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapDeleteEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapDeleteEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapDeleteEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapDeleteEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapDeleteEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..0dc8dd0 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapDeleteEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapDelete("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Delete) + .WithName("Delete"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapGetEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapGetEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapGetEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapGetEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapGetEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..80f6ec1 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapGetEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Get) + .WithName("Get"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapHeadEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapHeadEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapHeadEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapHeadEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapHeadEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..caa75d1 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapHeadEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix", new[] { "HEAD" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Head) + .WithName("Head"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapOptionsEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapOptionsEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapOptionsEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapOptionsEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapOptionsEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..df2fad8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapOptionsEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix", new[] { "OPTIONS" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Options) + .WithName("Options"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapPatchEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPatchEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPatchEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapPatchEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPatchEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..58b9366 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPatchEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapPatch("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Patch) + .WithName("Patch"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapPostEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPostEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPostEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapPostEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPostEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..786383c --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPostEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapPost("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Post) + .WithName("Post"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapPutEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPutEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPutEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapPutEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPutEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..eaaf7c8 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapPutEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapPut("/matrix/{id:int}", global::GeneratedEndpointsTests.HttpMethodEndpoints.Put) + .WithName("Put"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapQueryEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapQueryEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapQueryEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapQueryEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapQueryEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..e1a9b68 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapQueryEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix/query", new[] { "QUERY" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Query) + .WithName("Query"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapTraceEndpoint_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapTraceEndpoint_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapTraceEndpoint_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MapTraceEndpoint_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MapTraceEndpoint_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..32e2e0e --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MapTraceEndpoint_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapMethods("/matrix", new[] { "TRACE" }, global::GeneratedEndpointsTests.HttpMethodEndpoints.Trace) + .WithName("Trace"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodAllowAnonymous_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodAllowAnonymous_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodAllowAnonymous_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodAllowAnonymous_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodAllowAnonymous_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..b915326 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodAllowAnonymous_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .AllowAnonymous(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodDisableValidation_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodDisableValidation_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodDisableValidation_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodDisableValidation_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodDisableValidation_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..e00e76c --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodDisableValidation_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .DisableValidation() +; + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodEndpointFilter_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodEndpointFilter_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodEndpointFilter_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodEndpointFilter_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodEndpointFilter_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..3fddf3b --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodEndpointFilter_MapEndpointHandlers.verified.txt @@ -0,0 +1,33 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Configure( + builder.MapGet("/configure-filters", global::GeneratedEndpointsTests.ConfigureFilterEndpoints.Handle) + .WithName("Handle") + .AddEndpointFilter() + ); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodNameCollision_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodNameCollision_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..64b4329 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodNameCollision_AddEndpointHandlers.verified.txt @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodNameCollision_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodNameCollision_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..e6a1d98 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodNameCollision_MapEndpointHandlers.verified.txt @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/alternate", global::GeneratedEndpointsTests.AlternateEndpoints.Get) + .WithName("GeneratedEndpointsTests.AlternateEndpoints.Get"); + + builder.MapPost("/alternate", global::GeneratedEndpointsTests.AlternateEndpoints.Post) + .WithName("Post"); + + builder.MapGet("/matrix", global::GeneratedEndpointsTests.HttpMethodEndpoints.Get) + .WithName("GeneratedEndpointsTests.HttpMethodEndpoints.Get"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireAuthorization_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireAuthorization_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireAuthorization_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireAuthorization_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireAuthorization_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..7c0dc47 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireAuthorization_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireAuthorization("MethodPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCorsWithPolicy_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCorsWithPolicy_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCorsWithPolicy_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCorsWithPolicy_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCorsWithPolicy_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..55b13d3 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCorsWithPolicy_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireCors("MethodPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCors_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCors_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCors_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCors_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCors_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..d51e223 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireCors_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireCors(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireHost_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireHost_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireHost_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireHost_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireHost_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..f61eb7d --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodRequireHost_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireHost("api.individual.com", "contoso.com"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodTags_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodTags_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodTags_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.MethodTags_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodTags_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..369ba78 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.MethodTags_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithTags("Method", "Matrix"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.OrderMetadata_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.OrderMetadata_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.OrderMetadata_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.OrderMetadata_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.OrderMetadata_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..9d860d0 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.OrderMetadata_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithOrder(7); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesProblemAttribute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesProblemAttribute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesProblemAttribute_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesProblemAttribute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesProblemAttribute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..97a1421 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesProblemAttribute_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .ProducesProblem(500, "application/problem+json"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseAttribute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseAttribute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseAttribute_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseAttribute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseAttribute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..8a60c59 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseAttribute_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .Produces(200, "application/json"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseMultipleContentTypes_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseMultipleContentTypes_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseMultipleContentTypes_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseMultipleContentTypes_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseMultipleContentTypes_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..25fbbdb --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesResponseMultipleContentTypes_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .Produces(200, "application/json", "text/json"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesValidationProblemAttribute_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesValidationProblemAttribute_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesValidationProblemAttribute_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesValidationProblemAttribute_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesValidationProblemAttribute_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..c8c4590 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ProducesValidationProblemAttribute_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .ProducesValidationProblem(422, "application/problem+json"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeoutWithPolicy_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeoutWithPolicy_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeoutWithPolicy_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeoutWithPolicy_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeoutWithPolicy_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..b41ef8e --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeoutWithPolicy_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithRequestTimeout("TimeoutPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeout_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeout_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeout_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeout_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeout_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..233bfe0 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequestTimeout_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .WithRequestTimeout(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimitingWithPolicy_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimitingWithPolicy_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimitingWithPolicy_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimitingWithPolicy_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimitingWithPolicy_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..447c1c6 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimitingWithPolicy_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.RateLimiting; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .RequireRateLimiting("BurstPolicy"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimiting_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimiting_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimiting_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimiting_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimiting_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..1fbd462 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.RequireRateLimiting_MapEndpointHandlers.verified.txt @@ -0,0 +1,30 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix"); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ShortCircuit_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ShortCircuit_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..c6b5484 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ShortCircuit_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.ShortCircuit_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.ShortCircuit_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..e36dfde --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.ShortCircuit_MapEndpointHandlers.verified.txt @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/matrix/{id:int}", global::GeneratedEndpointsTests.AuthorizationMatrixEndpoints.Handle) + .WithName("GetMatrix") + .ShortCircuit(); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.SummaryAndDescriptionAttributes_AddEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.SummaryAndDescriptionAttributes_AddEndpointHandlers.verified.txt new file mode 100644 index 0000000..6e79c25 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.SummaryAndDescriptionAttributes_AddEndpointHandlers.verified.txt @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointServicesExtensions +{ + internal static void AddEndpointHandlers(this IServiceCollection services) + { + services.TryAddScoped(); + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.SummaryAndDescriptionAttributes_MapEndpointHandlers.verified.txt b/tests/GeneratedEndpoints.Tests/IndividualTests.SummaryAndDescriptionAttributes_MapEndpointHandlers.verified.txt new file mode 100644 index 0000000..4e910aa --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.SummaryAndDescriptionAttributes_MapEndpointHandlers.verified.txt @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// +// This code was generated by MinimalApiGenerator which can be found +// in the GeneratedEndpoints namespace. +// +// Changes to this file may cause incorrect behavior +// and will be lost if the code is regenerated. +// +//----------------------------------------------------------------------------- + +#nullable enable + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.AspNetCore.Generated.Routing; + +internal static class EndpointRouteBuilderExtensions +{ + internal static IEndpointRouteBuilder MapEndpointHandlers(this IEndpointRouteBuilder builder) + { + builder.MapGet("/contracts/{id:int}", global::GeneratedEndpointsTests.ContractEndpoints.Handle) + .WithName("Handle") + .WithSummary("Gets detailed content.") + .WithDescription("Shows binding and contract combinations."); + + return builder; + } +} diff --git a/tests/GeneratedEndpoints.Tests/IndividualTests.cs b/tests/GeneratedEndpoints.Tests/IndividualTests.cs new file mode 100644 index 0000000..e6c0265 --- /dev/null +++ b/tests/GeneratedEndpoints.Tests/IndividualTests.cs @@ -0,0 +1,638 @@ +using GeneratedEndpoints.Tests.Common; +using SourceGeneratorTestHelpers.XUnit; + +namespace GeneratedEndpoints.Tests; + +[UsesVerify] +public class IndividualTests +{ + public IndividualTests() + { + ModuleInitializer.Initialize(); + } + + [Fact] + public async Task DefaultFallbackOnly() + { + var source = FallbackScenario(includeDefault: true); + await VerifyIndividualAsync(source, nameof(DefaultFallbackOnly)); + } + + [Fact] + public async Task CustomFallbackRoute() + { + var source = FallbackScenario(includeCustom: true, customRoute: "/custom-individual"); + await VerifyIndividualAsync(source, nameof(CustomFallbackRoute)); + } + + [Fact] + public async Task ClassAllowAnonymous() + { + var source = AuthorizationScenario(classAllowAnonymous: true); + await VerifyIndividualAsync(source, nameof(ClassAllowAnonymous)); + } + + [Fact] + public async Task MethodAllowAnonymous() + { + var source = AuthorizationScenario(methodAllowAnonymous: true); + await VerifyIndividualAsync(source, nameof(MethodAllowAnonymous)); + } + + [Fact] + public async Task ClassRequireAuthorization() + { + var source = AuthorizationScenario(classRequireAuthorization: true); + await VerifyIndividualAsync(source, nameof(ClassRequireAuthorization)); + } + + [Fact] + public async Task MethodRequireAuthorization() + { + var source = AuthorizationScenario(methodRequireAuthorization: true); + await VerifyIndividualAsync(source, nameof(MethodRequireAuthorization)); + } + + [Fact] + public async Task ClassTags() + { + var source = AuthorizationScenario(classTags: true); + await VerifyIndividualAsync(source, nameof(ClassTags)); + } + + [Fact] + public async Task MethodTags() + { + var source = AuthorizationScenario(methodTags: true); + await VerifyIndividualAsync(source, nameof(MethodTags)); + } + + [Fact] + public async Task ClassRequireHost() + { + var source = AuthorizationScenario(classHost: "*.individual.com"); + await VerifyIndividualAsync(source, nameof(ClassRequireHost)); + } + + [Fact] + public async Task MethodRequireHost() + { + var source = AuthorizationScenario(methodHost: "api.individual.com"); + await VerifyIndividualAsync(source, nameof(MethodRequireHost)); + } + + [Fact] + public async Task ClassRequireCors() + { + var source = AuthorizationScenario(classRequireCors: true); + await VerifyIndividualAsync(source, nameof(ClassRequireCors)); + } + + [Fact] + public async Task ClassRequireCorsWithPolicy() + { + var source = AuthorizationScenario(classRequireCors: true, classCorsPolicy: "ClassPolicy"); + await VerifyIndividualAsync(source, nameof(ClassRequireCorsWithPolicy)); + } + + [Fact] + public async Task MethodRequireCors() + { + var source = AuthorizationScenario(methodRequireCors: true); + await VerifyIndividualAsync(source, nameof(MethodRequireCors)); + } + + [Fact] + public async Task MethodRequireCorsWithPolicy() + { + var source = AuthorizationScenario(methodRequireCors: true, methodCorsPolicy: "MethodPolicy"); + await VerifyIndividualAsync(source, nameof(MethodRequireCorsWithPolicy)); + } + + [Fact] + public async Task RequireRateLimiting() + { + var source = AuthorizationScenario(requireRateLimiting: true); + await VerifyIndividualAsync(source, nameof(RequireRateLimiting)); + } + + [Fact] + public async Task RequireRateLimitingWithPolicy() + { + var source = AuthorizationScenario(requireRateLimiting: true, rateLimitingPolicy: "BurstPolicy"); + await VerifyIndividualAsync(source, nameof(RequireRateLimitingWithPolicy)); + } + + [Fact] + public async Task ShortCircuit() + { + var source = AuthorizationScenario(applyShortCircuit: true); + await VerifyIndividualAsync(source, nameof(ShortCircuit)); + } + + [Fact] + public async Task ClassDisableValidation() + { + var source = AuthorizationScenario(classDisableValidation: true); + await VerifyIndividualAsync(source, nameof(ClassDisableValidation)); + } + + [Fact] + public async Task MethodDisableValidation() + { + var source = AuthorizationScenario(methodDisableValidation: true); + await VerifyIndividualAsync(source, nameof(MethodDisableValidation)); + } + + [Fact] + public async Task RequestTimeout() + { + var source = AuthorizationScenario(applyRequestTimeout: true); + await VerifyIndividualAsync(source, nameof(RequestTimeout)); + } + + [Fact] + public async Task RequestTimeoutWithPolicy() + { + var source = AuthorizationScenario(applyRequestTimeout: true, requestTimeoutPolicy: "TimeoutPolicy"); + await VerifyIndividualAsync(source, nameof(RequestTimeoutWithPolicy)); + } + + [Fact] + public async Task DisableRequestTimeout() + { + var source = AuthorizationScenario(disableRequestTimeout: true); + await VerifyIndividualAsync(source, nameof(DisableRequestTimeout)); + } + + [Fact] + public async Task OrderMetadata() + { + var source = AuthorizationScenario(orderValue: 7); + await VerifyIndividualAsync(source, nameof(OrderMetadata)); + } + + [Fact] + public async Task GroupName() + { + var source = AuthorizationScenario(groupName: "IndividualGroup"); + await VerifyIndividualAsync(source, nameof(GroupName)); + } + + [Fact] + public async Task ClassMapGroup() + { + var source = AuthorizationScenario( + classRequireAuthorization: true, + classTags: true, + classHost: "*.individual.com", + classRequireCors: true, + classCorsPolicy: "ClassCors", + applyShortCircuit: true, + applyRequestTimeout: true, + requestTimeoutPolicy: "ClassTimeout", + orderValue: 2, + groupName: "ClassGroup", + excludeFromDescription: true, + methodAllowAnonymous: true, + methodTags: true, + mapGroupPattern: "/individuals" + ); + await VerifyIndividualAsync(source, nameof(ClassMapGroup)); + } + + [Fact] + public async Task ExcludeFromDescription() + { + var source = AuthorizationScenario(excludeFromDescription: true); + await VerifyIndividualAsync(source, nameof(ExcludeFromDescription)); + } + + [Fact] + public async Task ClassEndpointFilter() + { + var source = ConfigureScenario(includeClassLevelFilter: true); + await VerifyIndividualAsync(source, nameof(ClassEndpointFilter)); + } + + [Fact] + public async Task MethodEndpointFilter() + { + var source = ConfigureScenario(includeMethodLevelFilter: true); + await VerifyIndividualAsync(source, nameof(MethodEndpointFilter)); + } + + [Fact] + public async Task GenericEndpointFilter() + { + var source = ConfigureScenario(includeGenericFilter: true); + await VerifyIndividualAsync(source, nameof(GenericEndpointFilter)); + } + + [Fact] + public async Task ConfigureWithServiceProvider() + { + var source = ConfigureScenario(configureWithServiceProvider: true); + await VerifyIndividualAsync(source, nameof(ConfigureWithServiceProvider)); + } + + [Fact] + public async Task ConfigureAddsMetadata() + { + var source = ConfigureScenario(configureAddsMetadata: true, metadataValue: "IndividualMetadata"); + await VerifyIndividualAsync(source, nameof(ConfigureAddsMetadata)); + } + + [Fact] + public async Task ConfigureRegistersFilter() + { + var source = ConfigureScenario(configureRegistersFilter: true); + await VerifyIndividualAsync(source, nameof(ConfigureRegistersFilter)); + } + + [Fact] + public async Task MapGetEndpoint() + { + var source = HttpMethodScenario(includeGet: true); + await VerifyIndividualAsync(source, nameof(MapGetEndpoint)); + } + + [Fact] + public async Task MapPostEndpoint() + { + var source = HttpMethodScenario(includePost: true); + await VerifyIndividualAsync(source, nameof(MapPostEndpoint)); + } + + [Fact] + public async Task MapPutEndpoint() + { + var source = HttpMethodScenario(includePut: true); + await VerifyIndividualAsync(source, nameof(MapPutEndpoint)); + } + + [Fact] + public async Task MapDeleteEndpoint() + { + var source = HttpMethodScenario(includeDelete: true); + await VerifyIndividualAsync(source, nameof(MapDeleteEndpoint)); + } + + [Fact] + public async Task MapOptionsEndpoint() + { + var source = HttpMethodScenario(includeOptions: true); + await VerifyIndividualAsync(source, nameof(MapOptionsEndpoint)); + } + + [Fact] + public async Task MapHeadEndpoint() + { + var source = HttpMethodScenario(includeHead: true); + await VerifyIndividualAsync(source, nameof(MapHeadEndpoint)); + } + + [Fact] + public async Task MapPatchEndpoint() + { + var source = HttpMethodScenario(includePatch: true); + await VerifyIndividualAsync(source, nameof(MapPatchEndpoint)); + } + + [Fact] + public async Task MapQueryEndpoint() + { + var source = HttpMethodScenario(includeQuery: true); + await VerifyIndividualAsync(source, nameof(MapQueryEndpoint)); + } + + [Fact] + public async Task MapTraceEndpoint() + { + var source = HttpMethodScenario(includeTrace: true); + await VerifyIndividualAsync(source, nameof(MapTraceEndpoint)); + } + + [Fact] + public async Task MapConnectEndpoint() + { + var source = HttpMethodScenario(includeConnect: true); + await VerifyIndividualAsync(source, nameof(MapConnectEndpoint)); + } + + [Fact] + public async Task MethodNameCollision() + { + var source = HttpMethodScenario(includeGet: true, includeMethodNameCollision: true); + await VerifyIndividualAsync(source, nameof(MethodNameCollision)); + } + + [Fact] + public async Task BindingNames() + { + var source = ContractScenario(includeBindingNames: true); + await VerifyIndividualAsync(source, nameof(BindingNames)); + } + + [Fact] + public async Task AsParameters() + { + var source = ContractScenario(includeAsParameters: true); + await VerifyIndividualAsync(source, nameof(AsParameters)); + } + + [Fact] + public async Task FromServices() + { + var source = ContractScenario(includeFromServices: true); + await VerifyIndividualAsync(source, nameof(FromServices)); + } + + [Fact] + public async Task FromKeyedServices() + { + var source = ContractScenario(includeFromKeyedServices: true); + await VerifyIndividualAsync(source, nameof(FromKeyedServices)); + } + + [Fact] + public async Task AcceptsAttribute() + { + var source = ContractScenario(includeAccepts: true, acceptsContentType1: "application/custom"); + await VerifyIndividualAsync(source, nameof(AcceptsAttribute)); + } + + [Fact] + public async Task AcceptsMultipleContentTypes() + { + var source = ContractScenario(includeAccepts: true, acceptsContentType1: "application/json", acceptsContentType2: "text/json"); + await VerifyIndividualAsync(source, nameof(AcceptsMultipleContentTypes)); + } + + [Fact] + public async Task GenericAcceptsAttribute() + { + var source = ContractScenario(includeGenericAccepts: true, acceptsContentType1: "application/vnd.generic"); + await VerifyIndividualAsync(source, nameof(GenericAcceptsAttribute)); + } + + [Fact] + public async Task ProducesResponseAttribute() + { + var source = ContractScenario(includeProducesResponse: true, producesContentType1: "application/json"); + await VerifyIndividualAsync(source, nameof(ProducesResponseAttribute)); + } + + [Fact] + public async Task ProducesResponseMultipleContentTypes() + { + var source = ContractScenario(includeProducesResponse: true, producesContentType1: "application/json", producesContentType2: "text/json"); + await VerifyIndividualAsync(source, nameof(ProducesResponseMultipleContentTypes)); + } + + [Fact] + public async Task ProducesProblemAttribute() + { + var source = ContractScenario(includeProducesProblem: true, producesContentType1: "application/problem+json"); + await VerifyIndividualAsync(source, nameof(ProducesProblemAttribute)); + } + + [Fact] + public async Task ProducesValidationProblemAttribute() + { + var source = ContractScenario(includeProducesValidationProblem: true); + await VerifyIndividualAsync(source, nameof(ProducesValidationProblemAttribute)); + } + + [Fact] + public async Task SummaryAndDescriptionAttributes() + { + var source = ContractScenario(includeSummaryAndDescription: true); + await VerifyIndividualAsync(source, nameof(SummaryAndDescriptionAttributes)); + } + + [Fact] + public async Task DisplayNameAttribute() + { + var source = ContractScenario(includeDisplayName: true); + await VerifyIndividualAsync(source, nameof(DisplayNameAttribute)); + } + + [Fact] + public async Task ContractTags() + { + var source = ContractScenario(includeTags: true); + await VerifyIndividualAsync(source, nameof(ContractTags)); + } + + [Fact] + public async Task ContractExcludeFromDescription() + { + var source = ContractScenario(excludeFromDescription: true); + await VerifyIndividualAsync(source, nameof(ContractExcludeFromDescription)); + } + + [Fact] + public async Task ContractAllowAnonymous() + { + var source = ContractScenario(allowAnonymous: true); + await VerifyIndividualAsync(source, nameof(ContractAllowAnonymous)); + } + + [Fact] + public async Task ContractRequireAuthorization() + { + var source = ContractScenario(methodRequiresAuthorization: true); + await VerifyIndividualAsync(source, nameof(ContractRequireAuthorization)); + } + + [Fact] + public async Task AsyncMethodVariants() + { + var source = AsyncHandlerScenario(); + await VerifyIndividualAsync(source, nameof(AsyncMethodVariants)); + } + + private static async Task VerifyIndividualAsync(string source, string scenario, bool withNamespace = true) + { + var sources = TestHelpers.GetSources(source, withNamespace); + var result = TestHelpers.RunGenerator(sources); + + await result.VerifyAsync("AddEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_AddEndpointHandlers"); + + await result.VerifyAsync("MapEndpointHandlers.g.cs") + .UseMethodName($"{scenario}_MapEndpointHandlers"); + } + + private static string FallbackScenario(bool includeDefault = false, bool includeCustom = false, string? customRoute = null) + => SourceFactory.BuildFallbackSource(includeDefault, includeCustom, customRoute); + + private static string AuthorizationScenario( + bool classAllowAnonymous = false, + bool methodAllowAnonymous = false, + bool classRequireAuthorization = false, + bool methodRequireAuthorization = false, + bool classTags = false, + bool methodTags = false, + string? classHost = null, + string? methodHost = null, + bool classRequireCors = false, + string? classCorsPolicy = null, + bool methodRequireCors = false, + string? methodCorsPolicy = null, + bool requireRateLimiting = false, + string? rateLimitingPolicy = null, + bool applyShortCircuit = false, + bool applyRequestTimeout = false, + string? requestTimeoutPolicy = null, + bool disableRequestTimeout = false, + int orderValue = 0, + string? groupName = null, + bool excludeFromDescription = false, + string? mapGroupPattern = null, + bool classDisableValidation = false, + bool methodDisableValidation = false) + => SourceFactory.BuildAuthorizationMatrixSource( + classAllowAnonymous, + methodAllowAnonymous, + classRequireAuthorization, + methodRequireAuthorization, + classTags, + methodTags, + classHost, + methodHost, + classRequireCors, + classCorsPolicy, + methodRequireCors, + methodCorsPolicy, + requireRateLimiting, + rateLimitingPolicy, + applyShortCircuit, + applyRequestTimeout, + requestTimeoutPolicy, + disableRequestTimeout, + orderValue, + groupName, + excludeFromDescription, + mapGroupPattern, + classDisableValidation, + methodDisableValidation); + + private static string ConfigureScenario( + bool configureWithServiceProvider = false, + bool configureAddsMetadata = false, + bool includeClassLevelFilter = false, + bool includeMethodLevelFilter = false, + bool includeGenericFilter = false, + bool configureRegistersFilter = false, + string metadataValue = "Individual") + => SourceFactory.BuildConfigureAndFiltersSource( + configureWithServiceProvider, + configureAddsMetadata, + includeClassLevelFilter, + includeMethodLevelFilter, + includeGenericFilter, + configureRegistersFilter, + metadataValue); + + private static string HttpMethodScenario( + bool includeGet = false, + bool includePost = false, + bool includePut = false, + bool includeDelete = false, + bool includeOptions = false, + bool includeHead = false, + bool includePatch = false, + bool includeQuery = false, + bool includeTrace = false, + bool includeConnect = false, + bool includeMethodNameCollision = false) + => SourceFactory.BuildHttpMethodMatrixSource( + includeGet, + includePost, + includePut, + includeDelete, + includeOptions, + includeHead, + includePatch, + includeQuery, + includeTrace, + includeConnect, + includeMethodNameCollision); + + private static string ContractScenario( + bool includeBindingNames = false, + bool includeAsParameters = false, + bool includeFromServices = false, + bool includeFromKeyedServices = false, + bool includeAccepts = false, + bool includeGenericAccepts = false, + bool includeProducesResponse = false, + bool includeProducesProblem = false, + bool includeProducesValidationProblem = false, + bool includeSummaryAndDescription = false, + bool includeDisplayName = false, + bool includeTags = false, + bool excludeFromDescription = false, + bool allowAnonymous = false, + bool methodRequiresAuthorization = false, + string? acceptsContentType1 = null, + string? acceptsContentType2 = null, + string? producesContentType1 = null, + string? producesContentType2 = null) + => SourceFactory.BuildContractsAndBindingSource( + includeBindingNames, + includeAsParameters, + includeFromServices, + includeFromKeyedServices, + includeAccepts, + includeGenericAccepts, + includeProducesResponse, + includeProducesProblem, + includeProducesValidationProblem, + includeSummaryAndDescription, + includeDisplayName, + includeTags, + excludeFromDescription, + allowAnonymous, + methodRequiresAuthorization, + acceptsContentType1, + acceptsContentType2, + producesContentType1, + producesContentType2); + + private static string AsyncHandlerScenario() + => """ + using System.Threading.Tasks; + + internal sealed class AsyncHandlerEndpoints + { + [MapGet("/task")] + public async Task TaskOnly() + { + await Task.Yield(); + } + + [MapGet("/task-result")] + public async Task, NotFound>> TaskWithResult(int id) + { + await Task.Yield(); + return id >= 0 ? TypedResults.Ok("task") : TypedResults.NotFound(); + } + + [MapPost("/valuetask")] + public async ValueTask ValueTaskOnly() + { + await Task.Yield(); + } + + [MapPost("/valuetask-result")] + public async ValueTask, NotFound>> ValueTaskWithResult(int id) + { + await Task.Yield(); + return id >= 0 ? TypedResults.Ok("value") : TypedResults.NotFound(); + } + } + """; +}