-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Move ProtectedBrowserStorage to the shared fx #25557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| services.AddDataProtection(); | ||
|
|
||
| services.TryAddScoped<ProtectedLocalStorage>(); | ||
| services.TryAddScoped<ProtectedSessionStorage>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This surprises me a bit. Do we definitely want to include the protected storage services by default?
For non-core functionality like this it seems more idiomatic for the developer to call services.AddProtectedBrowserStorage() (or similar) themselves to opt in.
I suppose that is a bit of an arbitrary hoop we're giving them to jump through, but it does mean they are making more of a conscious choice to plug it into their application.
Perhaps this is a question for API review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but it does mean they are making more of a conscious choice to plug it into their application.
-
Users are making that choice by using these types. Having the service registration isn't a significant cost and we have precedence with MVC registering a whole bunch of optional features \ services in DI behind a single gesture.
-
Previously using these APIs required bringing in an optional dependency (DataProtection), which is no longer the case. I would have felt more strongly about a separate API if this required bringing in more optional services.
-
Generally our service registration chain in dependencies. In this case,
AddProtectedBrowserStoragewould only make sense if you had already calledAddServerSideBlazor. That would require us to either callAddServerSideBlazoron your behalf or use a builder pattern, both of which seem unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The difference is that libraries can start using this without the app developer knowing. I'm not sure if that's something we want, given that this will put data in the browser (even though is protected).
I can imagine it being hard to detect if an app brings in a library that starts making use of this "liberally".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll let @pranavkm decide. I don't feel strongly either, but I favor having an explicit gesture. We can always change that in the future, but we can't do it the other way around.
| var componentType = typeof(TComponent); | ||
| var componentTypeName = componentType.Assembly == typeof(BasicTestApp.Program).Assembly ? | ||
| componentType.FullName : | ||
| componentType.AssemblyQualifiedName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. Why is this change needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see it's related to ProtectedBrowserStorageUsageComponent being in the server project, however I'm still unsure of the necessity as per question https://github.com/dotnet/aspnetcore/pull/25557/files#r482820977.
|
|
||
| <option value="Components.TestServer.ProtectedBrowserStorageUsageComponent, @serverAssembly.FullName">Protected browser storage usage</option> | ||
| <option value="Components.TestServer.ProtectedBrowserStorageInjectionComponent, @serverAssembly.FullName">Protected browser storage injection</option> | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No doubt this is viable as-is, but if you feel like you have time to tweak it a bit more, I'd suggest it would be preferable not to have the @if statement, because then it would be really confusing if you were in the browser UI looking for something in the list that wasn't there because you accidentally loaded the wrong host environment and didn't realise some test cases are only available in some environments. It will also get pretty messy if we keep adding more conditional blocks like this in the future.
It would be much clearer if all the entries were present all the time, but if you picked a type that can't be found, we have an error message like "The type {name} could not be found. It might not be supported when running on this host environment.". This error could be triggered from Index.razor's SelectedComponentType getter, or just inline in the Razor UI logic when SelectedComponentTypeName is nonempty but SelectedComponentType is null.
Also rather than using assembly qualified names, what stops it from working just having the type name (independently of the assembly)? The logic in Index.razor's SelectedComponentType uses Type.GetType - doesn't that look at all the loaded assemblies?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic in Index.razor's SelectedComponentType uses Type.GetType - doesn't that look at all the loaded assemblies?
It only works if the type is in the executing assembly which requires the additional work around fully qualifying it. I have this tweaked a bit where we rely on the runtime to fail loudly if the type is unable to be found. Perhaps that would suffice here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, makes sense.
The improvement you've added looks good to me. It's test code - we can always try to streamline it later if we want.
|
|
||
| <option value="Components.TestServer.ProtectedBrowserStorageUsageComponent, @serverAssembly.FullName">Protected browser storage usage</option> | ||
| <option value="Components.TestServer.ProtectedBrowserStorageInjectionComponent, @serverAssembly.FullName">Protected browser storage injection</option> | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic in Index.razor's SelectedComponentType uses Type.GetType - doesn't that look at all the loaded assemblies?
It only works if the type is in the executing assembly which requires the additional work around fully qualifying it. I have this tweaked a bit where we rely on the runtime to fail loudly if the type is unable to be found. Perhaps that would suffice here?
| services.AddServerSideBlazor(); | ||
| services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(); | ||
| services.AddSingleton<LazyAssemblyLoader>(); | ||
| services.AddScoped<LazyAssemblyLoader>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@captainsafia I had trouble running the TestServer app without changing this. AddServerSideBlazor adds a scoped IJSRuntime instance. Our DI system will complain if a singleton service (in this case LazyAssemblyLoader) references a scoped service (IJSRuntime). Do you think there's a regression as a result of my changes?
| services.AddDataProtection(); | ||
|
|
||
| services.TryAddScoped<ProtectedLocalStorage>(); | ||
| services.TryAddScoped<ProtectedSessionStorage>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but it does mean they are making more of a conscious choice to plug it into their application.
-
Users are making that choice by using these types. Having the service registration isn't a significant cost and we have precedence with MVC registering a whole bunch of optional features \ services in DI behind a single gesture.
-
Previously using these APIs required bringing in an optional dependency (DataProtection), which is no longer the case. I would have felt more strongly about a separate API if this required bringing in more optional services.
-
Generally our service registration chain in dependencies. In this case,
AddProtectedBrowserStoragewould only make sense if you had already calledAddServerSideBlazor. That would require us to either callAddServerSideBlazoron your behalf or use a builder pattern, both of which seem unnecessary.
SteveSandersonMS
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know there are still a couple of open questions but I'm fine with what's here and whatever decisions you take on them.
|
Hello human! Please make sure you've included the Shiproom Template in a comment or (preferably) the PR description. Also, make sure this PR is not marked as a draft and is ready-to-merge. |
|
Does this have a breaking change impact for any customers that have started using it already? |
|
@Pilchie the would have to remove the package reference and change namespaces when upgrading from rc1. It will be useful to cover some of these packaging changes (there's one more component that's affected) as an announcement. |
|
Approved for .NET 5 RC2 pending CI checks, but we will need a breaking change announcement for this. |
|
Announcement filed: aspnet/Announcements#436 |
Fixes #25534