Skip to content

Add support for RouteHandlerInvocationContext<> overloads #41406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.AspNetCore.Http;

/// <summary>
/// Provides a default implementation for wrapping the <see cref="HttpContext"/> and parameters
/// provided to a route handler.
/// </summary>
public class DefaultRouteHandlerInvocationContext : RouteHandlerInvocationContext
{
/// <summary>
/// Creates a new instance of the <see cref="DefaultRouteHandlerInvocationContext"/> for a given request.
/// </summary>
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <param name="arguments">A list of parameters provided in the current request.</param>
public DefaultRouteHandlerInvocationContext(HttpContext httpContext, params object[] arguments)
{
HttpContext = httpContext;
Arguments = arguments;
}

/// <inheritdoc />
public override HttpContext HttpContext { get; }

/// <inheritdoc />
public override IList<object?> Arguments { get; }

/// <inheritdoc />
public override T GetArgument<T>(int index)
{
return (T)Arguments[index]!;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,26 @@ Microsoft.AspNetCore.Http.HttpResponse</Description>

<ItemGroup>
<InternalsVisibleTo Include="Microsoft.AspNetCore.Http.Abstractions.Microbenchmarks" />
<InternalsVisibleTo Include="Microsoft.AspNetCore.Http.Extensions" />
</ItemGroup>

<ItemGroup>
<None Update="RouteHandlerInvocationContextOfT.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>RouteHandlerInvocationContextOfT.Generated.cs</LastGenOutput>
</None>
</ItemGroup>

<ItemGroup>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can include this in the global directory.props

cc @dougbu

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean notice a project contains a .tt file and add the <Service /> element @davidfowl❔ That may work but VS would rewrite it the next time someone opens the project IIRC.

We only have 3 projects containing this <Service /> after this PR. How big an issue is this❔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not an issue, I would just like to clean it up as we plan to code generate more things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's up to you @davidfowl whether to centralize things in this PR. I recommend testing if the code in our root Directory.Build.props prevents VS rewriting the project to list the <Service/>. If "Save All" is fine after adding a new .tt file, you're good to go. Otherwise, the extra code will become redundant and something we'll end up fighting.

The specific approach would be something like

<ItemGroup>
  <_GeneratorSources Include="$(MSBuildProjectDirectory)\**\*.tt" />
</ItemGroup>
<ItemGroup>
  <Service Condition=" '@(_GeneratorSources->Count()) ' != '0' " Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

<ItemGroup>
<Compile Update="RouteHandlerInvocationContextOfT.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>RouteHandlerInvocationContextOfT.Generated.tt</DependentUpon>
</Compile>
</ItemGroup>

</Project>
12 changes: 9 additions & 3 deletions src/Http/Http.Abstractions/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*REMOVED*Microsoft.AspNetCore.Http.EndpointMetadataCollection.Enumerator.Current.get -> object?
Microsoft.AspNetCore.Builder.EndpointBuilder.ServiceProvider.get -> System.IServiceProvider?
Microsoft.AspNetCore.Builder.EndpointBuilder.ServiceProvider.set -> void
Microsoft.AspNetCore.Http.DefaultRouteHandlerInvocationContext
Microsoft.AspNetCore.Http.DefaultRouteHandlerInvocationContext.DefaultRouteHandlerInvocationContext(Microsoft.AspNetCore.Http.HttpContext! httpContext, params object![]! arguments) -> void
Microsoft.AspNetCore.Http.EndpointMetadataCollection.Enumerator.Current.get -> object!
Microsoft.AspNetCore.Http.EndpointMetadataCollection.GetRequiredMetadata<T>() -> T!
Microsoft.AspNetCore.Http.IRouteHandlerFilter.InvokeAsync(Microsoft.AspNetCore.Http.RouteHandlerInvocationContext! context, Microsoft.AspNetCore.Http.RouteHandlerFilterDelegate! next) -> System.Threading.Tasks.ValueTask<object?>
Expand All @@ -14,9 +16,7 @@ Microsoft.AspNetCore.Http.RouteHandlerContext.MethodInfo.get -> System.Reflectio
Microsoft.AspNetCore.Http.RouteHandlerContext.RouteHandlerContext(System.Reflection.MethodInfo! methodInfo, Microsoft.AspNetCore.Http.EndpointMetadataCollection! endpointMetadata) -> void
Microsoft.AspNetCore.Http.RouteHandlerFilterDelegate
Microsoft.AspNetCore.Http.RouteHandlerInvocationContext
Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.HttpContext.get -> Microsoft.AspNetCore.Http.HttpContext!
Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.Parameters.get -> System.Collections.Generic.IList<object?>!
Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.RouteHandlerInvocationContext(Microsoft.AspNetCore.Http.HttpContext! httpContext, params object![]! parameters) -> void
Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.RouteHandlerInvocationContext() -> void
Microsoft.AspNetCore.Routing.RouteValueDictionary.RouteValueDictionary(Microsoft.AspNetCore.Routing.RouteValueDictionary? dictionary) -> void
Microsoft.AspNetCore.Routing.RouteValueDictionary.RouteValueDictionary(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, object?>>? values) -> void
Microsoft.AspNetCore.Routing.RouteValueDictionary.RouteValueDictionary(System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string!, string?>>? values) -> void
Expand All @@ -27,3 +27,9 @@ Microsoft.AspNetCore.Http.Metadata.IEndpointDescriptionMetadata
Microsoft.AspNetCore.Http.Metadata.IEndpointDescriptionMetadata.Description.get -> string!
Microsoft.AspNetCore.Http.Metadata.IEndpointSummaryMetadata
Microsoft.AspNetCore.Http.Metadata.IEndpointSummaryMetadata.Summary.get -> string!
abstract Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.Arguments.get -> System.Collections.Generic.IList<object?>!
abstract Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.GetArgument<T>(int index) -> T
abstract Microsoft.AspNetCore.Http.RouteHandlerInvocationContext.HttpContext.get -> Microsoft.AspNetCore.Http.HttpContext!
override Microsoft.AspNetCore.Http.DefaultRouteHandlerInvocationContext.Arguments.get -> System.Collections.Generic.IList<object?>!
override Microsoft.AspNetCore.Http.DefaultRouteHandlerInvocationContext.GetArgument<T>(int index) -> T
override Microsoft.AspNetCore.Http.DefaultRouteHandlerInvocationContext.HttpContext.get -> Microsoft.AspNetCore.Http.HttpContext!
31 changes: 14 additions & 17 deletions src/Http/Http.Abstractions/src/RouteHandlerInvocationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,29 @@
namespace Microsoft.AspNetCore.Http;

/// <summary>
/// Provides an abstraction for wrapping the <see cref="HttpContext"/> and parameters
/// Provides an abstraction for wrapping the <see cref="HttpContext"/> and arguments
/// provided to a route handler.
/// </summary>
public sealed class RouteHandlerInvocationContext
public abstract class RouteHandlerInvocationContext
{
/// <summary>
/// Creates a new instance of the <see cref="RouteHandlerInvocationContext"/> for a given request.
/// </summary>
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <param name="parameters">A list of parameters provided in the current request.</param>
public RouteHandlerInvocationContext(HttpContext httpContext, params object[] parameters)
{
HttpContext = httpContext;
Parameters = parameters;
}

/// <summary>
/// The <see cref="HttpContext"/> associated with the current request being processed by the filter.
/// </summary>
public HttpContext HttpContext { get; }
public abstract HttpContext HttpContext { get; }

/// <summary>
/// A list of parameters provided in the current request to the filter.
/// A list of arguments provided in the current request to the filter.
/// <remarks>
/// This list is not read-only to permit modifying of existing parameters by filters.
/// This list is not read-only to permit modifying of existing arguments by filters.
/// </remarks>
/// </summary>
public IList<object?> Parameters { get; }
public abstract IList<object?> Arguments { get; }

/// <summary>
/// Retrieve the argument given its position in the argument list.
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> of the resolved argument.</typeparam>
/// <param name="index">An integer representing the position of the argument in the argument list.</param>
/// <returns>The argument at a given <paramref name="index"/></returns>
public abstract T GetArgument<T>(int index);
}
Loading