Methods were covariant return types applies does not inherit attributes
#92.047 aperta il 14 set 2023
Metriche repository
- Star
- (17.886 star)
- Metriche merge PR
- (Merge medio 12g 11h) (661 PR mergiate in 30 g)
Descrizione
Description
Today my coworker encountered an issue with Asp.Net Core 7.0 were an abstract controller base class contained an endpoint which return type were just Task. The controller that implemented it was returning Task<IActionResult>, but the endpoint was not being found. When i slapped the HttpPostAttribute on the overriden method it suddenly worked.
In the reproduction steps i have prepared a simple example code which shows, that GetCustomAttributes(inherit: true) is not giving the attribute. I assume this is the reason, why Asp.Net Core does not find it. I expect this is not an bug in Asp.Net Core, but more in the compiler or GetCustomAttributes implementation.
I have not found any hint in all dotnet repositories, that for covariant return types all attributes of the method of the base class must be omitted. So i think the actual behavior is not by design. If this is by design, should libraries and user code manually find the overriden methods and pick the attributes from there?
Reproduction Steps
Here is an example code which demonstrates it. I have prepared an example sharplab.io for it.
using System;
using System.Linq;
using System.Threading.Tasks;
Console.WriteLine("Does AController.PostThis have HttpPost attribute? "
+ typeof(AController).GetMethod("PostThis")!.GetCustomAttributes(true).OfType<HttpPostAttribute>().Any());
Console.WriteLine("Does BController.PostThis have HttpPost attribute? "
+ typeof(BController).GetMethod("PostThis")!.GetCustomAttributes(true).OfType<HttpPostAttribute>().Any());
abstract class BaseController
{
[HttpPost]
public abstract Task PostThis();
}
class AController : BaseController
{
public override Task<object?> PostThis()
{
return Task.FromResult<object?>(null);
}
}
class BController : BaseController
{
public override Task PostThis()
{
return Task.FromResult<object?>(null);
}
}
class HttpPostAttribute : Attribute
{
}
Expected behavior
I expected following output
Does AController.PostThis have HttpPost attribute? True
Does BController.PostThis have HttpPost attribute? True
Actual behavior
But it was following output
Does AController.PostThis have HttpPost attribute? False
Does BController.PostThis have HttpPost attribute? True
Regression?
I think this is like this since the first release of the covariant return type feature.
Known Workarounds
- Not using the covariant return type feature when using attributes.
- Copy all attributes over to every implementation.
Configuration
.NET 7.0 x86 and x64 on Windows 10 but as you can see is also on sharplab.io reproducible.
Other information
No response