Skip to content

Commit

Permalink
Re-factored the endpoint group naming. (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgernand committed May 24, 2024
1 parent 49bebd6 commit 36ecb89
Show file tree
Hide file tree
Showing 29 changed files with 135 additions and 340 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ the endppoint name id the class name of the endpoint.

This default conventions can be overridden by using attributes athe endpoints class level.

- ```[EndpointGroupName("GroupName")]```
- ```[EndpointGroup("GroupName")]```

The name of the group this endpoint belongs to.

Expand Down
3 changes: 2 additions & 1 deletion samples/SampleApplication/Endpoints/Customers/GetCustomer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
using MadEyeMatt.AspNetCore.Endpoints;

[PublicAPI]
[EndpointGroup("Customers")]
public sealed class GetCustomer : EndpointBase
{
/// <inheritdoc />
public override void Map(IEndpointRouteBuilder endpoints)
{
endpoints
.MapGet(this.Execute, "{id}")
.MapGet(this.Execute, "customers/{id}")
.Produces<Customer>(200, "application/json");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
using MadEyeMatt.AspNetCore.Endpoints;

[PublicAPI]
[EndpointGroup("Customers")]
public sealed class GetCustomers : EndpointBase
{
/// <inheritdoc />
public override void Map(IEndpointRouteBuilder endpoints)
{
endpoints
.MapGet(this.Execute)
.MapGet(this.Execute, "customers")
.Produces<Customer>(200, "application/json");
}

Expand Down
23 changes: 23 additions & 0 deletions samples/SampleApplication/Endpoints/GetDiagnostics.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace SampleApplication.Endpoints
{
using JetBrains.Annotations;
using MadEyeMatt.AspNetCore.Endpoints;

[PublicAPI]
[EndpointGroup("Diagnostics")]
public sealed class GetDiagnostics : EndpointBase
{
/// <inheritdoc />
public override void Map(IEndpointRouteBuilder endpoints)
{
endpoints
.MapGet(this.Execute, "diag")
.Produces<string>(200, "application/json");
}

public async Task<IResult> Execute(HttpContext httpContext)
{
return Results.Ok("Diagnostics");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
using MadEyeMatt.AspNetCore.Endpoints;

[PublicAPI]
[EndpointName("SomeOtherName")]
[EndpointGroupName("weather_forecast")]
[EndpointName("Weather")]
public sealed class GetWeatherForecasts : EndpointBase
{
private string[] summaries = new string[]
Expand All @@ -16,7 +15,7 @@ public sealed class GetWeatherForecasts : EndpointBase
/// <inheritdoc />
public override void Map(IEndpointRouteBuilder endpoints)
{
endpoints.MapGet(this.Execute);
endpoints.MapGet(this.Execute, "weather");
}

public async Task<IEnumerable<WeatherForecast>> Execute(HttpContext httpContext)
Expand Down
3 changes: 3 additions & 0 deletions samples/SampleApplication/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public static void Main(string[] args)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// Add the endpoints as services.
builder.Services.AddEndpoints();

// Add services to the container.
builder.Services.AddAuthorization();

Expand Down
4 changes: 2 additions & 2 deletions samples/SampleApplication/SampleApplication.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" Condition="'$(TargetFramework)' == 'net8.0'" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions samples/SampleApplication/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
"Default": "Debug",
"Microsoft.AspNetCore": "Debug"
}
}
}
21 changes: 0 additions & 21 deletions src/AspNetCore.Endpoints/EndpointBase.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
namespace MadEyeMatt.AspNetCore.Endpoints
{
using System;
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Routing;

Expand All @@ -12,24 +9,6 @@
[PublicAPI]
public abstract class EndpointBase : IEndpoint
{
/// <summary>
/// Initializes a new instance of the <see cref="EndpointBase"/> type.
/// </summary>
protected EndpointBase()
{
Type groupType = this.GetType();

string groupName = groupType.GetCustomAttribute<EndpointGroupNameAttribute>()?.GroupName?.Trim() ??
groupType.Namespace?.Split('.', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).Last();

this.Group = new EndpointGroup(groupName);
}

/// <summary>
/// Gets the endpoint group.
/// </summary>
public EndpointGroup Group { get; }

/// <summary>
/// Maps the endpoint.
/// </summary>
Expand Down
67 changes: 0 additions & 67 deletions src/AspNetCore.Endpoints/EndpointGroup.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@
/// </summary>
[PublicAPI]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class EndpointGroupNameAttribute : Attribute
public sealed class EndpointGroupAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="EndpointGroupNameAttribute"/> type.
/// Initializes a new instance of the <see cref="EndpointGroupAttribute"/> type.
/// </summary>
/// <param name="groupName"></param>
public EndpointGroupNameAttribute(string groupName)
/// <param name="group"></param>
public EndpointGroupAttribute(string group)
{
this.GroupName = groupName;
ArgumentException.ThrowIfNullOrEmpty(group);

this.Group = group;
}

/// <summary>
/// Gets the group name.
/// </summary>
public string GroupName { get; }
public string Group { get; }
}
}
8 changes: 5 additions & 3 deletions src/AspNetCore.Endpoints/EndpointNameAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ public sealed class EndpointNameAttribute : Attribute
/// <summary>
/// Initializes a new instance of the <see cref="EndpointNameAttribute"/> type.
/// </summary>
/// <param name="handlerName"></param>
public EndpointNameAttribute(string handlerName)
/// <param name="name"></param>
public EndpointNameAttribute(string name)
{
this.Name = handlerName;
ArgumentException.ThrowIfNullOrEmpty(name);

this.Name = name;
}

/// <summary>
Expand Down
70 changes: 34 additions & 36 deletions src/AspNetCore.Endpoints/EndpointRouteBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
Expand Down Expand Up @@ -38,13 +39,14 @@ public static IEndpointRouteBuilder MapEndpoints(this IEndpointRouteBuilder buil
endpoints.Add(endpoint);
}

foreach (IGrouping<EndpointGroup, EndpointBase> grouping in endpoints.GroupBy(x => x.Group))
EndpointsOptions options = builder.ServiceProvider.GetRequiredService<IOptions<EndpointsOptions>>().Value;
string globalPrefix = options.EndpointsRoutePrefix?.Trim('/') ?? "api";

RouteGroupBuilder groupBuilder = builder.MapGroup(globalPrefix);

foreach (EndpointBase endpoint in endpoints)
{
RouteGroupBuilder groupEndpoints = builder.MapGroup(grouping.Key);
foreach (EndpointBase endpoint in grouping)
{
endpoint.Map(groupEndpoints);
}
endpoint.Map(groupBuilder);
}

return builder;
Expand All @@ -67,7 +69,8 @@ public static RouteHandlerBuilder MapGet(this IEndpointRouteBuilder endpoints, D

return endpoints
.MapGet(pattern, handler)
.WithName(handler.Method.GetEndpointName());
.WithName(handler)
.WithTags(handler);
}

/// <summary>
Expand All @@ -87,7 +90,8 @@ public static RouteHandlerBuilder MapPost(this IEndpointRouteBuilder endpoints,

return endpoints
.MapPost(pattern, handler)
.WithName(handler.Method.GetEndpointName());
.WithName(handler)
.WithTags(handler);
}

/// <summary>
Expand All @@ -107,7 +111,8 @@ public static RouteHandlerBuilder MapPut(this IEndpointRouteBuilder endpoints, D

return endpoints
.MapPut(pattern, handler)
.WithName(handler.Method.GetEndpointName());
.WithName(handler)
.WithTags(handler);
}

/// <summary>
Expand All @@ -127,7 +132,8 @@ public static RouteHandlerBuilder MapPatch(this IEndpointRouteBuilder endpoints,

return endpoints
.MapPatch(pattern, handler)
.WithName(handler.Method.GetEndpointName());
.WithName(handler)
.WithTags(handler);
}

/// <summary>
Expand All @@ -147,27 +153,8 @@ public static RouteHandlerBuilder MapDelete(this IEndpointRouteBuilder endpoints

return endpoints
.MapDelete(pattern, handler)
.WithName(handler.Method.GetEndpointName());
}

private static RouteGroupBuilder MapGroup(this IEndpointRouteBuilder builder, EndpointGroup group)
{
ArgumentNullException.ThrowIfNull(group);

EndpointsOptions options = builder.ServiceProvider.GetRequiredService<IOptions<EndpointsOptions>>().Value;
string globalPrefix = options.EndpointsRoutePrefix?.Trim('/');

string prefix = string.IsNullOrWhiteSpace(globalPrefix)
? $"/{group.Name.ToLowerInvariant()}"
: $"/{globalPrefix}/{group.Name.ToLowerInvariant()}";

RouteGroupBuilder groupBuilder = builder
.MapGroup(prefix)
.WithTags(group.Name);

options.MapGroup?.Invoke(groupBuilder);

return groupBuilder;
.WithName(handler)
.WithTags(handler);
}

private static bool IsAnonymous(this MethodInfo method)
Expand All @@ -176,14 +163,25 @@ private static bool IsAnonymous(this MethodInfo method)
return method.Name.Any(invalidChars.Contains);
}

private static string GetEndpointName(this MethodInfo method)
private static RouteHandlerBuilder WithName(this RouteHandlerBuilder builder, Delegate handler)
{
Type declaringType = method.DeclaringType;
EndpointNameAttribute endpointNameAttribute = handler.Method.DeclaringType?.GetCustomAttribute<EndpointNameAttribute>();
string name = endpointNameAttribute is not null
? endpointNameAttribute.Name
: handler.Method.DeclaringType?.Name ?? "Endpoints";

ArgumentNullException.ThrowIfNull(declaringType);
return builder.WithName(name);
}

string name = declaringType.GetCustomAttribute<EndpointNameAttribute>()?.Name ?? declaringType.Name;
return name;
private static RouteHandlerBuilder WithTags(this RouteHandlerBuilder builder, Delegate handler)
{
EndpointGroupAttribute endpointGroupAttribute = handler.Method.DeclaringType?.GetCustomAttribute<EndpointGroupAttribute>();
if (endpointGroupAttribute is not null)
{
builder = builder.WithTags(endpointGroupAttribute.Group);
}

return builder;
}
}
}
Loading

0 comments on commit 36ecb89

Please sign in to comment.