Skip to content

Commit f08cd59

Browse files
committed
Route parameters do not support BindAsync
1 parent b616548 commit f08cd59

File tree

4 files changed

+25
-33
lines changed

4 files changed

+25
-33
lines changed

src/Framework/AspNetCoreAnalyzers/src/Analyzers/DiagnosticDescriptors.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,10 +161,10 @@ internal static class DiagnosticDescriptors
161161
isEnabledByDefault: true,
162162
helpLinkUri: "https://aka.ms/aspnet/analyzers");
163163

164-
internal static readonly DiagnosticDescriptor RouteParameterComplexTypeIsNotParsableOrBindable = new(
164+
internal static readonly DiagnosticDescriptor RouteParameterComplexTypeIsNotParsable = new(
165165
"ASP0020",
166166
"Complex types referenced by route parameters must be parsable",
167-
"Parameter '{0}' of type {1} should define a bool TryParse(string, IFormatProvider, out {1}) method, or implement IParsable<{1}>, or define a ValueTask<{1}> BindAsync(HttpContext), or implement IBindableFromHttpContext<{1}>.",
167+
"Parameter '{0}' of type {1} should define a bool TryParse(string, IFormatProvider, out {1}) method, or implement IParsable<{1}>.",
168168
"Usage",
169169
DiagnosticSeverity.Error,
170170
isEnabledByDefault: true,

src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteHandlers/DisallowNonParsableComplexTypesOnParameters.cs

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,11 @@ private static void DisallowNonParsableComplexTypesOnParameters(
6868
if (IsRouteParameter(routeUsage, handlerDelegateParameter))
6969
{
7070
var parsability = ParsabilityHelper.GetParsability(parameterTypeSymbol, wellKnownTypes);
71-
var bindability = ParsabilityHelper.GetBindability(parameterTypeSymbol, wellKnownTypes);
7271

73-
if (!(parsability == Parsability.Parsable || bindability == Bindability.Bindable))
72+
if (parsability != Parsability.Parsable)
7473
{
75-
var descriptor = SelectDescriptor(parsability, bindability);
76-
7774
context.ReportDiagnostic(Diagnostic.Create(
78-
descriptor,
75+
DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable,
7976
location,
8077
handlerDelegateParameter.Name,
8178
parameterTypeSymbol.Name
@@ -103,10 +100,8 @@ static bool ReportFromAttributeDiagnostic(OperationAnalysisContext context, Well
103100
var parsability = ParsabilityHelper.GetParsability(parameterTypeSymbol, wellKnownTypes);
104101
if (parameter.HasAttributeImplementingInterface(fromMetadataInterfaceTypeSymbol) && parsability != Parsability.Parsable)
105102
{
106-
var descriptor = SelectDescriptor(parsability, Bindability.NotBindable);
107-
108103
context.ReportDiagnostic(Diagnostic.Create(
109-
descriptor,
104+
DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable,
110105
location,
111106
parameter.Name,
112107
parameterTypeSymbol.Name
@@ -140,16 +135,5 @@ static bool ReportFromAttributeDiagnostic(OperationAnalysisContext context, Well
140135

141136
return parameterTypeSymbol;
142137
}
143-
144-
static DiagnosticDescriptor SelectDescriptor(Parsability parsability, Bindability bindability)
145-
{
146-
// This abomination is used to take the parsability and bindability and together figure
147-
// out what the most optimal diagnostic message is to give to our plucky user.
148-
return (parsability, bindability) switch
149-
{
150-
{ parsability: Parsability.NotParsable, bindability: Bindability.InvalidReturnType } => DiagnosticDescriptors.BindAsyncSignatureMustReturnValueTaskOfT,
151-
_ => DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsableOrBindable
152-
};
153-
}
154138
}
155139
}

src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteHandlers/RouteHandlerAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer
2525
DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers,
2626
DiagnosticDescriptors.DetectMisplacedLambdaAttribute,
2727
DiagnosticDescriptors.DetectMismatchedParameterOptionality,
28-
DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsableOrBindable,
28+
DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable,
2929
DiagnosticDescriptors.BindAsyncSignatureMustReturnValueTaskOfT,
3030
DiagnosticDescriptors.AmbiguousRouteHandlerRoute,
3131
DiagnosticDescriptors.AtMostOneFromBodyAttribute

src/Framework/AspNetCoreAnalyzers/test/RouteHandlers/DisallowNonParsableComplexTypesOnParametersTest.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ public class Customer
195195
}
196196
""";
197197

198-
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsableOrBindable)
198+
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable)
199199
.WithArguments("customer", "Customer")
200200
.WithLocation(0);
201201

@@ -218,7 +218,7 @@ public class Customer
218218
}
219219
""";
220220

221-
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsableOrBindable)
221+
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable)
222222
.WithArguments("customer", "Customer")
223223
.WithLocation(0);
224224

@@ -289,7 +289,7 @@ public static bool TryParse(string s, IFormatProvider provider, out Customer res
289289
}
290290

291291
[Fact]
292-
public async Task Route_Parameter_withBindAsyncMethodThatReturnsTask_of_T_Fails()
292+
public async Task Route_Parameter_withBindAsyncMethod_Fails()
293293
{
294294
// Arrange
295295
var source = $$"""
@@ -301,14 +301,14 @@ public async Task Route_Parameter_withBindAsyncMethodThatReturnsTask_of_T_Fails(
301301
302302
public class Customer
303303
{
304-
public async static Task<Customer> BindAsync(HttpContext context)
304+
public async static ValueTask<Customer> BindAsync(HttpContext context)
305305
{
306306
return new Customer();
307307
}
308308
}
309309
""";
310310

311-
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.BindAsyncSignatureMustReturnValueTaskOfT)
311+
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable)
312312
.WithArguments("customer", "Customer")
313313
.WithLocation(0);
314314

@@ -422,7 +422,7 @@ public static bool TryParse(string s, IFormatProvider provider, out Customer res
422422
}
423423

424424
[Fact]
425-
public async Task Route_Parameter_withHttpContextBindableComplexType_viaImplicitIBindableFromHttp_Works()
425+
public async Task Route_Parameter_withHttpContextBindableComplexType_viaImplicitIBindableFromHttp_Fails()
426426
{
427427
// Arrange
428428
var source = $$"""
@@ -433,7 +433,7 @@ public async Task Route_Parameter_withHttpContextBindableComplexType_viaImplicit
433433
using Microsoft.AspNetCore.Http;
434434
435435
var webApp = WebApplication.Create();
436-
webApp.MapGet("/customers/{customer}", (Customer customer) => {});
436+
webApp.MapGet("/customers/{customer}", ({|#0:Customer customer|}) => {});
437437
438438
public class Customer : IBindableFromHttpContext<Customer>
439439
{
@@ -444,12 +444,16 @@ public class Customer : IBindableFromHttpContext<Customer>
444444
}
445445
""";
446446

447+
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable)
448+
.WithArguments("customer", "Customer")
449+
.WithLocation(0);
450+
447451
// Act
448-
await VerifyCS.VerifyAnalyzerAsync(source);
452+
await VerifyCS.VerifyAnalyzerAsync(source, expectedDiagnostic);
449453
}
450454

451455
[Fact]
452-
public async Task Route_Parameter_withHttpContextBindableComplexType_viaExplicitIBindableFromHttp_Works()
456+
public async Task Route_Parameter_withHttpContextBindableComplexType_viaExplicitIBindableFromHttp_Fails()
453457
{
454458
// Arrange
455459
var source = $$"""
@@ -460,7 +464,7 @@ public async Task Route_Parameter_withHttpContextBindableComplexType_viaExplicit
460464
using Microsoft.AspNetCore.Http;
461465
462466
var webApp = WebApplication.Create();
463-
webApp.MapGet("/customers/{customer}", (Customer customer) => {});
467+
webApp.MapGet("/customers/{customer}", ({|#0:Customer customer|}) => {});
464468
465469
public class Customer : IBindableFromHttpContext<Customer>
466470
{
@@ -471,8 +475,12 @@ public class Customer : IBindableFromHttpContext<Customer>
471475
}
472476
""";
473477

478+
var expectedDiagnostic = new DiagnosticResult(DiagnosticDescriptors.RouteParameterComplexTypeIsNotParsable)
479+
.WithArguments("customer", "Customer")
480+
.WithLocation(0);
481+
474482
// Act
475-
await VerifyCS.VerifyAnalyzerAsync(source);
483+
await VerifyCS.VerifyAnalyzerAsync(source, expectedDiagnostic);
476484
}
477485

478486
[Fact]

0 commit comments

Comments
 (0)