-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedold-area-web-frameworks-do-not-use*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels
Milestone
Description
Background and Motivation
Results
and TypedResults
have methods that use reflection to create route values. These have all been annotated as unsafe.
public static partial class Results
{
[RequiresUnreferencedCode(RouteValueDictionaryTrimmerWarning.Warning)]
public static IResult CreatedAtRoute(string? routeName = null, object? routeValues = null, object? value = null);
}
We have previously worked around this problem by adding overloads that take RouteValueDictionary
. Values can be explicitly added to the dictionary, and the dictionary is then passed to routing. This is a trimming and AOT-safe alternative.
Proposed API
namespace Microsoft.AspNetCore.Http;
public static partial class Results
{
+ public static IResult RedirectToRoute(string? routeName, RouteValueDictionary? routeValues, bool permanent = false, bool preserveMethod = false, string? fragment = null);
+ public static IResult CreatedAtRoute(string? routeName, RouteValueDictionary routeValues, object? value = null);
+ public static IResult CreatedAtRoute<TValue>(string? routeName, RouteValueDictionary routeValues, TValue? value = default);
+ public static IResult AcceptedAtRoute(string? routeName, RouteValueDictionary routeValues, object? value = null);
+ public static IResult AcceptedAtRoute<TValue>(string? routeName, RouteValueDictionary routeValues, TValue? value = default);
}
public static partial class TypedResults
{
+ public static RedirectToRouteHttpResult RedirectToRoute(string? routeName, RouteValueDictionary? routeValues, bool permanent = false, bool preserveMethod = false, string? fragment = null);
+ public static CreatedAtRoute CreatedAtRoute(string? routeName, RouteValueDictionary routeValues);
+ public static CreatedAtRoute<TValue> CreatedAtRoute<TValue>(TValue? value, string? routeName, RouteValueDictionary routeValues);
+ public static AcceptedAtRoute AcceptedAtRoute(string? routeName, RouteValueDictionary routeValues);
+ public static AcceptedAtRoute<TValue> AcceptedAtRoute<TValue>(TValue? value, string? routeName, RouteValueDictionary routeValues);
}
Usage Examples
app.MapGet("/old-path", () => Results.CreatedAtRoute("RouteName", new RouteValueDictionary { ["routeValue1"] = "value!" }));
Alternative Designs
Generic type parameter for route values was explored in #46082. For example:
public static partial class Results
{
+ public static IResult CreatedAtRoute<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TRouteValues>(string? routeName, TRouteValues routeValues, object? value = null);
}
It doesn't require converting the route values object into a RouteValueDictionary
, but it has some problems:
- It doesn't work with polymorphism. Property values are gotten from the route value type based on its runtime type. If the route value instance is cast to
object
and then used withCreatedAtRoute<TRouteValues>
, its properties aren't preserved. - It could be a source-breaking change. There will now be a
CreatedAtRoute<TRouteValues>
overload and aCreatedAtRoute<TValue>
overload. Code that explicitly specifies the generic type when callingCreatedAtRoute
could cause an ambiguous method compiler error.
For example:
return Results.CreatedAtRoute<object>("RouteName", new { param1 = "param1Value" }, new User());
Risks
There are a lot of overloads, optional parameters and nullable types. It is possible to create method overloads that are ambiguous.
To avoid that:
RouteValueDictionary
args never have a default value. It must be specified.- Tests for methods must be extensive.
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedold-area-web-frameworks-do-not-use*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels*DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels