Skip to content

Commit 1a3fd3a

Browse files
authored
Rename Produces attribute to ProducesResponse (#14)
1 parent be9a365 commit 1a3fd3a

File tree

4 files changed

+18
-18
lines changed

4 files changed

+18
-18
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ by keeping endpoint definitions inside their features while generating the boile
1414
injection.
1515
* **Metadata composition** – mix class-level and method-level attributes for tags, authorization requirements, content
1616
negotiation, and antiforgery/anonymous settings. The generator merges everything into the produced endpoint builder.
17-
* **Rich request/response contracts** – describe the shape of your API surface with `[Accepts]`, `[Produces]`, `[ProducesProblem]`,
17+
* **Rich request/response contracts** – describe the shape of your API surface with `[Accepts]`, `[ProducesResponse]`, `[ProducesProblem]`,
1818
and `[ProducesValidationProblem]` so OpenAPI and client tooling stay accurate.
1919
* **Minimal boilerplate**`AddEndpointHandlers` auto-registers instance handlers with DI, and `MapEndpointHandlers`
2020
registers every attribute-decorated method.
@@ -216,7 +216,7 @@ public sealed class CreateTodo
216216

217217
The method is only generated once per handler class, so any conventions you add will automatically flow to all endpoints defined within that class.
218218

219-
### 5. Describe contracts with `Accepts` and `Produces`
219+
### 5. Describe contracts with `Accepts` and `ProducesResponse`
220220

221221
GeneratedEndpoints ships with helper attributes for request and response metadata. Apply them to either a handler class or
222222
individual methods to keep your OpenAPI description in sync with the implementation. Attributes on the class are merged into
@@ -229,7 +229,7 @@ using Microsoft.AspNetCore.Http.HttpResults;
229229
namespace Todos.Features;
230230

231231
[Accepts<CreateTodoRequest>("application/json", "application/xml")]
232-
[Produces<Todo>(StatusCodes.Status201Created)]
232+
[ProducesResponse<Todo>(StatusCodes.Status201Created)]
233233
[ProducesProblem(StatusCodes.Status500InternalServerError)]
234234
public sealed class CreateTodo
235235
{
@@ -253,7 +253,7 @@ calls on the endpoint builder.
253253
| `[AllowAnonymous]` | Class or method | Explicitly opts a method (or all methods in a class) into anonymous access, overriding `[RequireAuthorization]`. |
254254
| `[DisableAntiforgery]` | Class or method | Calls `.DisableAntiforgery()` on the generated endpoint, matching the ASP.NET Core extension. |
255255
| `[Accepts]` / `[Accepts<TRequest>]` | Class or method | Emits `.Accepts<TRequest>(contentType, additionalContentTypes...)` to document supported request bodies. Multiple attributes are allowed per endpoint. |
256-
| `[Produces]` / `[Produces<TResponse>]` | Class or method | Emits `.Produces<TResponse>(statusCode, contentTypes...)` for each documented response type. Multiple attributes are allowed. |
256+
| `[ProducesResponse]` / `[ProducesResponse<TResponse>]` | Class or method | Emits `.Produces<TResponse>(statusCode, contentTypes...)` for each documented response type. Multiple attributes are allowed. |
257257
| `[ProducesProblem]` | Class or method | Emits `.ProducesProblem(statusCode, contentTypes...)` for endpoints that return RFC 7807 problem details. |
258258
| `[ProducesValidationProblem]` | Class or method | Emits `.ProducesValidationProblem(statusCode, contentTypes...)` when validation failures are returned. |
259259

src/GeneratedEndpoints/MinimalApiGenerator.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ public sealed class MinimalApiGenerator : IIncrementalGenerator
7373
private const string AcceptsAttributeFullyQualifiedName = $"{AttributesNamespace}.{AcceptsAttributeName}";
7474
private const string AcceptsAttributeHint = $"{AcceptsAttributeFullyQualifiedName}.gs.cs";
7575

76-
private const string ProducesAttributeName = "ProducesAttribute";
77-
private const string ProducesAttributeFullyQualifiedName = $"{AttributesNamespace}.{ProducesAttributeName}";
78-
private const string ProducesAttributeHint = $"{ProducesAttributeFullyQualifiedName}.gs.cs";
76+
private const string ProducesResponseAttributeName = "ProducesResponseAttribute";
77+
private const string ProducesResponseAttributeFullyQualifiedName = $"{AttributesNamespace}.{ProducesResponseAttributeName}";
78+
private const string ProducesResponseAttributeHint = $"{ProducesResponseAttributeFullyQualifiedName}.gs.cs";
7979

8080
private const string ProducesProblemAttributeName = "ProducesProblemAttribute";
8181
private const string ProducesProblemAttributeFullyQualifiedName = $"{AttributesNamespace}.{ProducesProblemAttributeName}";
@@ -353,7 +353,7 @@ namespace {{AttributesNamespace}};
353353
/// Specifies a response type, status code, and content types produced by the annotated endpoint or class.
354354
/// </summary>
355355
[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
356-
internal sealed class {{ProducesAttributeName}} : global::System.Attribute
356+
internal sealed class {{ProducesResponseAttributeName}} : global::System.Attribute
357357
{
358358
/// <summary>
359359
/// Gets the response type produced by the endpoint.
@@ -376,13 +376,13 @@ internal sealed class {{ProducesAttributeName}} : global::System.Attribute
376376
public string[] AdditionalContentTypes { get; }
377377
378378
/// <summary>
379-
/// Initializes a new instance of the <see cref="{{ProducesAttributeName}}"/> class.
379+
/// Initializes a new instance of the <see cref="{{ProducesResponseAttributeName}}"/> class.
380380
/// </summary>
381381
/// <param name="responseType">The CLR type of the response body.</param>
382382
/// <param name="statusCode">The HTTP status code returned by the endpoint.</param>
383383
/// <param name="contentType">The primary content type produced by the endpoint.</param>
384384
/// <param name="additionalContentTypes">Additional content types produced by the endpoint.</param>
385-
public {{ProducesAttributeName}}(global::System.Type responseType, int statusCode = 200, string? contentType = null, params string[] additionalContentTypes)
385+
public {{ProducesResponseAttributeName}}(global::System.Type responseType, int statusCode = 200, string? contentType = null, params string[] additionalContentTypes)
386386
{
387387
ResponseType = responseType ?? throw new global::System.ArgumentNullException(nameof(responseType));
388388
StatusCode = statusCode;
@@ -396,7 +396,7 @@ internal sealed class {{ProducesAttributeName}} : global::System.Attribute
396396
/// </summary>
397397
/// <typeparam name="TResponse">The CLR type of the response body.</typeparam>
398398
[global::System.AttributeUsage(global::System.AttributeTargets.Class | global::System.AttributeTargets.Method, Inherited = false, AllowMultiple = true)]
399-
internal sealed class {{ProducesAttributeName}}<TResponse> : global::System.Attribute
399+
internal sealed class {{ProducesResponseAttributeName}}<TResponse> : global::System.Attribute
400400
{
401401
/// <summary>
402402
/// Gets the response type produced by the endpoint.
@@ -424,7 +424,7 @@ internal sealed class {{ProducesAttributeName}}<TResponse> : global::System.Attr
424424
/// <param name="statusCode">The HTTP status code returned by the endpoint.</param>
425425
/// <param name="contentType">The primary content type produced by the endpoint.</param>
426426
/// <param name="additionalContentTypes">Additional content types produced by the endpoint.</param>
427-
public {{ProducesAttributeName}}(int statusCode = 200, string? contentType = null, params string[] additionalContentTypes)
427+
public {{ProducesResponseAttributeName}}(int statusCode = 200, string? contentType = null, params string[] additionalContentTypes)
428428
{
429429
StatusCode = statusCode;
430430
ContentType = contentType;
@@ -433,7 +433,7 @@ internal sealed class {{ProducesAttributeName}}<TResponse> : global::System.Attr
433433
}
434434
435435
""";
436-
context.AddSource(ProducesAttributeHint, SourceText.From(producesSource, Encoding.UTF8));
436+
context.AddSource(ProducesResponseAttributeHint, SourceText.From(producesSource, Encoding.UTF8));
437437

438438
// ProducesProblem
439439
var producesProblemSource = $$"""
@@ -776,7 +776,7 @@ ref List<ProducesValidationProblemMetadata>? producesValidationProblem
776776
continue;
777777
}
778778

779-
if (IsGeneratedAttribute(fullyQualifiedName, ProducesAttributeName))
779+
if (IsGeneratedAttribute(fullyQualifiedName, ProducesResponseAttributeName))
780780
{
781781
TryAddProducesMetadata(attribute, attributeClass, ref produces);
782782
continue;

tests/GeneratedEndpoints.Tests.Lab/GetUserEndpoint.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ internal static class GetUserEndpoint
1616
[AllowAnonymous]
1717
[Accepts(typeof(GetUserRequest), "application/json", "application/xml")]
1818
[Accepts<GetUserMetadata>("application/json", "application/xml")]
19-
[Produces(typeof(UserProfile), StatusCodes.Status200OK, "application/json")]
20-
[Produces<UserProfile>(StatusCodes.Status202Accepted, "application/json")]
19+
[ProducesResponse(typeof(UserProfile), StatusCodes.Status200OK, "application/json")]
20+
[ProducesResponse<UserProfile>(StatusCodes.Status202Accepted, "application/json")]
2121
[ProducesProblem(StatusCodes.Status500InternalServerError, "application/problem+json")]
2222
[ProducesValidationProblem(StatusCodes.Status400BadRequest, "application/problem+json")]
2323
[MapGet("/users/{id:int}", Name = nameof(GetUser), Summary = "Gets a user by ID.", Description = "Gets a user by ID when the ID is greater than zero.")]

tests/GeneratedEndpoints.Tests/GeneratedEndpointsTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public async Task MapAllAttributesAndHttpMethods(bool withNamespace)
116116
[RequireAuthorization("PolicyA", "PolicyB")]
117117
[DisableAntiforgery]
118118
[Accepts(typeof(ClassLevelRequest), "application/xml", "text/xml")]
119-
[Microsoft.AspNetCore.Generated.Attributes.Produces(typeof(ClassLevelResponse), 201, "application/json", "text/json")]
119+
[Microsoft.AspNetCore.Generated.Attributes.ProducesResponse(typeof(ClassLevelResponse), 201, "application/json", "text/json")]
120120
[ProducesProblem(503, "application/problem+json")]
121121
[ProducesValidationProblem(409, "application/problem+json", "text/plain")]
122122
internal sealed class ComplexEndpoints
@@ -138,7 +138,7 @@ public static void Configure<TBuilder>(TBuilder builder, IServiceProvider servic
138138
[Tags("MethodLevel")]
139139
[RequireAuthorization("MethodPolicy")]
140140
[Accepts<GetRequest>("application/custom", "text/custom")]
141-
[Microsoft.AspNetCore.Generated.Attributes.Produces<GetResponse>(200, "application/json", "text/json")]
141+
[Microsoft.AspNetCore.Generated.Attributes.ProducesResponse<GetResponse>(200, "application/json", "text/json")]
142142
[ProducesProblem(400, "application/problem+json", "text/plain")]
143143
[ProducesValidationProblem(422, "application/problem+json", "text/plain")]
144144
public async Task<Results<Ok<GetResponse>, NotFound>> GetComplex(

0 commit comments

Comments
 (0)