dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.58k stars 10.06k forks source link

Blazor: Accessing HttpContext in a Client Project #58593

Closed sbwalker closed 3 weeks ago

sbwalker commented 1 month ago

Is there an existing issue for this?

Describe the bug

When building a Blazor application you may want to create all of your components in the Client project, as this provides the flexibility to be able to use the components in any render mode or hosting model (as long as they are developed in a client/server manner). Some of these components may need to access HttpContext (if they are expected to run on the server at run-time ie. as part of pre-rendering). HttpContext is not available in a Client project by default... and adding a dependency to Microsoft.AspNetCore.Http results in a critical severity vulnerability compilation warning in .NET 9.

Expected Behavior

I would expect that there should be a way to access HttpContext in a Blazor Client project in .NET 9 that does not result in a critical severity vulnerability issue.

Steps To Reproduce

Exceptions (if any)

No response

.NET Version

9.0.0-rc.2.24473.5

Anything else?

In .NET 8 the Microsoft.AspNetCore.Http package is flagged as deprecated, however it does not indicate that it contains a critical severity vulnerability. Since the version of the package has not changed in .NET 9 it seems very strange that it is now reporting a critical severity vulnerability (although the CVE referenced is from 2021).

martincostello commented 1 month ago

NuGet packages for ASP.NET Core 2.2 are no longer supported as .NET Core 2.2 reached end-of-life in December 2019, hence all the seemingly-unpatched CVE warnings.

There are no newer packages available as these packages are now instead part of the ASP.NET Core Shared Framework since the release of .NET Core 3.0.

You should remove all references to these packages and instead add a single FrameworkReference:

<ItemGroup>
  <FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

This will make the APIs in the previously independently-shipped NuGet packages still available to your code.

<end-saved-reply/>

It could be that for Blazor that guidance isn't 100% accurate, but that's what you'd do for a "normal" assembly.

sbwalker commented 1 month ago

The FrameworkReference solution does not work for a Blazor Client project. It throws a compiler error:

error NETSDK1082: There was no runtime pack for Microsoft.AspNetCore.App available for the specified RuntimeIdentifier 'browser-wasm'.

UDATE: adding the following to the Blazor Client project resolves the compilation error (https://stackoverflow.com/questions/63993294/there-was-no-runtime-pack-for-microsoft-aspnetcore-app-available-for-the-specifi)

<Target Name="AllowUsingAspNetCoreInBlazorWasm" AfterTargets="ProcessFrameworkReferences" >
    <ItemGroup>
        <UnavailableRuntimePack Remove="Microsoft.AspNetCore.App" />
    </ItemGroup>
</Target>

However when you run the app it will randomly throw Blazor unhandled exceptions when you navigate away from a page which contains an interactive component - these are the errors from the browser console:

Error deserializing root component operations: System.InvalidOperationException: No root component exists with SSR component ID 7. [blazor.web.js:1:158943](https://localhost:7115/_framework/blazor.web.js)
   at Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer.WebRootComponentManager.GetRequiredWebRootComponent(Int32 ssrComponentId) [blazor.web.js:1:158943](https://localhost:7115/_framework/blazor.web.js)
   at Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer.WebRootComponentManager.RemoveRootComponent(Int32 ssrComponentId) [blazor.web.js:1:158943](https://localhost:7115/_framework/blazor.web.js)
   at Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer.OnUpdateRootComponents(RootComponentOperationBatch batch) [blazor.web.js:1:158943](https://localhost:7115/_framework/blazor.web.js)
   at Microsoft.AspNetCore.Components.WebAssembly.Services.DefaultWebAssemblyJSRuntime.UpdateRootComponentsCore(String operationsJson)
javiercn commented 1 month ago

@sbwalker the way to do this is defining an interface on the .Client project and providing an implementation for it on the Server project to be used during prerendering. It's not possible to have a FrameworkReference to ASP.NET Core in the Client project.

This is one of the reasons why we were pursuing multi-targeting. It allows you to have different set of dependencies as well as avoid additional abstractions when you need to target multiple environments.

sbwalker commented 1 month ago

Thank you @javiercn. Is there an example I could review to see a practical implementation of this pattern you are describing?

The confusing aspect of this issue is that the standard development approach of simply adding a Nuget package dependency for the Microsoft.AspNetCore.Http package works perfectly as it delivers the desired functionality to the Client project in all render modes and hosting models. The only problem is that the package is deprecated (and now has a vulnerability flagged in .NET 9 - which makes no sense).

martincostello commented 1 month ago

Maybe the 2.3 packages will help once they ship with regards to the vulnerability warnings: https://github.com/dotnet/aspnetcore/issues/58598

sbwalker commented 1 month ago

@martincostello I am not sure if that will help as the 2.3 packages are only intended to be used with .NET Framework.

martincostello commented 1 month ago

I'm just speculating, but if they still targeted netstandard2.0 then they'd be the same as using 2.1-era packages? Thus they'd be usable like 2.1 or 2.2, but minus the CVEs.

javiercn commented 1 month ago

@sbwalker look at the implementation for NavigationManager.

There's a NavigationManager defined in Microsoft.AspNetCore.Components.Web and an HttpNavigationManager that's implemented in the pieces that use ASP.NET abstractions.

For everyone else interested, please stop trying to find ways to make this work. It's not meant to and even if you manage it's a pit of failure. This is the type of reason for which we wanted to have the netx.0-browser TFM so you don't have to create abstractions all over the place.

[!CAUTION] Do not reference Microsoft.AspNetCore.Http in WebAssembly or razor class libraries. This is pointing to an obsolete and unsupported version and will bring in a lot of unnecessary dependencies bloating the size of your app. Your webassembly app or any dependency that it has can't reference ASP.NET Core abstractions, you need to wrap those in an abstraction.

dotnet-policy-service[bot] commented 1 month ago

Hi @sbwalker. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

dotnet-policy-service[bot] commented 1 month ago

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. If it is closed, feel free to comment when you are able to provide the additional information and we will re-investigate.

See our Issue Management Policies for more information.