Move IFeatureCollection to new Extensions.Features assembly #32043
Conversation
src/Http/Http.Features/src/Microsoft.AspNetCore.Http.Features.csproj
Outdated
Show resolved
Hide resolved
@BrennanConroy please measure signalr impact |
Microsoft.AspNetCore.SignalR.Client -> What other impact are you interested in? |
New client on old asp.net core apps. Old client in new apps. |
|
Why is changing dependencies breaking? |
Are we keeping Http.Features as a package targeting netstandard? |
No, that's the main reason for this change, and the reason it's breaking. |
Lets consider this then: App (.NET 6) -> Package1 -> Http.Features 3.1 (for IFeatureCollection) Consider App is a console app and then App as an ASP.NET Core app. Do you get a source time type conflict? |
Keep in mind that Http.Features and Extensions.Features are also both in the shared framework and should unify to the latest version (needs verification). A standalone publish should also be able to resolve the conflict (needs verification). To really get into trouble I expect you'd need to not be using the shared framework. I'll do some experiments. |
I just want to explore the breaks so we can document them and anticipate what and how packages will snap |
Is a layering issue for DIMs if want to do the same thing with the FeatureCollection itself to get the same benefits as Headers? So would maybe need to introduce a derived type IHttpFeatureCollection : IFeatureCollection
{
IRouteValuesFeature RouteValuesFeature => Get<IRouteValuesFeature>();
// ...
} Which would then go viral and As I assume you wouldn't want to add Http DIMs to a more general non-Http IFeatures collection in Extensions? |
That's correct. |
But an issue is if a HttpFeatureCollection : IHttpFeatureCollection
{
private IFeatureCollection _collection;
public HttpFeatureCollection(IFeatureCollection collection)
{
_collection = collection;
}
IRouteValuesFeature RouteValuesFeature =>
_collection is IHttpFeatureCollection httpCollection ?
httpCollection.RouteValuesFeature :
_collection.Get<IRouteValuesFeature>();
// ...
} Or do it in contructor and then HttpFeatureCollection : IHttpFeatureCollection
{
private IHttpFeatureCollection _httpCollection;
private IFeatureCollection _collection;
public HttpFeatureCollection(IFeatureCollection collection)
{
if (collection is IHttpFeatureCollection _httpCollection)
{
_httpCollection = collection;
}
else
{
_collection = collection;
}
}
IRouteValuesFeature RouteValuesFeature =>
_httpCollection is not null ?
_httpCollection.RouteValuesFeature :
_collection.Get<IRouteValuesFeature>();
// ...
} Ofc its more complicated as there are othertypes of IFeatureCollection in use; like the ITransportFeatureCollection : IFeatureCollection
{
IConnectionLifetimeFeature ConnectionLifetimeFeature=> Get<IConnectionLifetimeFeature>();
// ...
}
IHttpFeatureCollection : ITransportFeatureCollection
{
IRouteValuesFeature RouteValuesFeature => Get<IRouteValuesFeature>();
// ...
} Then accept that Http was always over a connection (it probably is); but then that's quite a formal api heirachy using DIMs vs it being a bit more fluid currently (although is a guess if the featureCollection will resolve the type as its not guaranteeing types via contract; whereas the DIMs would be strongly suggesting it) Just wondering if there is an opperturnity for DIMs over the IFeatureCollection itself; how that would work and what type Or would it not work? |
I don't think it would work with the layering we want. At least, not with the way that we want to push feature collection down into the stack. It feels bad to attempt to use the same trick here. We would need to replat everything on top of a more specific one and do the type check. |
I was able to contrive a setup like this to produce the error. Console App net6.0
Interestingly I only get the error at compile time when I directly reference Workaround: In the base App add a direct reference to Microsoft.AspNetCore.Http.Features 6.0 to lift the dependency and include the type forward. Note this works with in-repo references, we'll want to confirm it after we have a full build and real packages. I get the same results testing a web app in-repo, but I think that's because it's not using the shared framework. I'll need to re-test after we have a full build. I don't see anything surprising or blocking here. I'll plan to re-test after it's merged and we have a build. @davidfowl is that enough coverage for us to proceed? |
This is why I wanted to ask if we should ship a package with type forwards for 6.0 as a way to bridge the gap until 7. |
Draft Announcement: Microsoft.AspNetCore.Http.Features split, no longer shipped as a packageMicrosoft.AspNetCore.Http.Features is being split into two assemblies, Microsoft.AspNetCore.Http.Features and Microsoft.Extensions.Features. Version introduced6.0 Old behaviorMicrosoft.AspNetCore.Http.Features 5.0 shipped both in the ASP.NET shared framework and as a nuget package. Microsoft.AspNetCore.Http.Features 5.0 targeted .NET 4.6.1, .NET Standard 2.0, and .NET 5.0 New behaviorMicrosoft.AspNetCore.Http.Features 6.0 will ship only in the ASP.NET shared framework, not as a nuget package. Microsoft.AspNetCore.Http.Features 6.0 will target .NET 6.0 only. Microsoft.Extensions.Features 6.0 will ship both in the ASP.NET shared framework and as a nuget package. Microsoft.Extensions.Features 6.0 will target .NET 4.6.1, .NET Standard 2.0, and .NET 6.0 The following types will move to the new assembly. The namespaces will not be changed and type forwards will be added for compatibility.
Reason for changeThis allows these core types to be shared more broadly across components, while also allowing the remaining Http specific components in Microsoft.AspNetCore.Http.Features to take advantage of new runtime and language features. Recommended actionWhen upgrading to ASP.NET 6.0 remove any packages references for Class libraries that need to consume the types from
Libraries with out of date references may encounter a
This can be mitigated by adding the FrameworkReference shown above to any of the affected projects. CategoryASP.NET Affected APIsIFeatureCollection Issue metadata
|
I had to add a TypeForwards in the Headers (as it is currently) 9bc7c11 with a |
Fair point. I wonder if the FrameworkReference will work just as well. I won't be able to test that until there's a real build. |
@benaadams after this PR you should be able to reverse that dependency you added and avoid moving any types. I'll follow up with you on that PR. |
The external Grpc tests were failing for me as they ref'd the previous framework (5.0) and the auto-update to 6.0 broke because the type moved, so a type forwards is probably recommended |
For the announcement, technically it's every API in the current package, not just the few. |
@pranavkm true, but the template calls for specific links. Any suggestions for an abbreviated format to cover the others? The docs don't list APIs by assembly, only namespace, and it's not a one-to-one match. |
Yeah, I'm not super sure there's a good way to present it. @JamesNK any suggestions? |
Sorry, I'm not sure what the question for me is.
So with the change in this PR, the package |
Shouldn't do; the TypeFowarders are there, was just pointing out they were necessary
Think its about the announcement? #32043 (comment)
|
@Tratcher that looks good. I think we should also mention the types of errors that can show up:
And likely a TypeLoadException runtime error because the type moved and you're missing the reference? |
Updated. Actually getting a TypeLoadException would be tough, I wasn't able to trigger one in testing. If you had a nuget dependency you would at least have the old type. You'd have to manually copy your old library dll to a project that only referenced the new Extensions.Features and not the shared framework. |
Reviewers: This should be ready. We think the Code Check issue is a false positive that @JunTaoLuo will review and override as needed. |
I imagine testing just how breaking this is will be easier after we merge it. We can adjust/revert later. |
Right, we just need to document all the things. |
@@ -0,0 +1,2 @@ | |||
#nullable enable |
halter73
Apr 23, 2021
Member
Why? Nothing has shipped yet in this assembly. Did you think this was src/Http/Http.Features/
? I wonder if we should rename the folders. That tripped me up earlier in the review too.
halter73
Apr 23, 2021
Member
Well CodeCheck agrees with you. I guess it doesn't like the file at all even if empty. Still think the folder names are confusing.
Tratcher
Apr 23, 2021
Author
Contributor
@JunTaoLuo? This is a new assembly and the tools failed if it didn't have this file.
benaadams
Apr 23, 2021
Member
Why? Nothing has shipped yet in this assembly.
That's why I was asking why it was changing
Tratcher
Apr 23, 2021
Author
Contributor
Note Code Check is complaining about different files because they were deleted:
error : Modified API baseline files:
error : src/Http/Http.Features/src/PublicAPI/net6.0/PublicAPI.Shipped.txt
error : src/Http/Http.Features/src/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt
dougbu
Apr 23, 2021
Contributor
Once you get the CI to green ignoring the Code Check job, let @dotnet/aspnet-build know and we'll override the required checks to squishy-merge your change.
dougbu
Apr 23, 2021
Contributor
From build perspective, the changes here make sense and simplify our PublicAPI files.
@@ -0,0 +1,2 @@ | |||
#nullable enable |
dougbu
Apr 23, 2021
Contributor
From build perspective, the changes here make sense and simplify our PublicAPI files.
<ItemGroup> | ||
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Shipped.txt" /> | ||
<AdditionalFiles Include="PublicAPI/$(TargetFramework)/PublicAPI.Unshipped.txt" /> | ||
</ItemGroup> |
Not exactly a "false positive" but a case where the error should be overridden. Now that I think about it, is / are the relevant PublicAPI.Shipped.txt file or files moving along with the existing assembly name |
/azp run |
Azure Pipelines successfully started running 2 pipeline(s). |
These files: Were recently added in 6.0 by #31625. We're removing them now that we've found a better solution. The 5.0 APIs are still covered by src/PublicAPI.Shipped.txt @JunTaoLuo @dougbu this is ready to merge. |
fc1f919
into
dotnet:main
Contributes #31723
This allows us to use new language features like DIMs in Http.Features without cross compiling.
#31495
#31625