-
Notifications
You must be signed in to change notification settings - Fork 10.3k
[release/8.0] [Blazor] Improvements to SSR component activation #50848
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
Changes from all commits
b565785
4fe97de
a04974b
5f9bc49
c4349b2
80cb7f4
7f775ce
a8f7bfc
27435b4
8d0108c
6276e2d
acb5321
7de7461
ab97bea
2dbcc38
44713bd
8d135d2
89d0506
f59b538
366feba
6f2efed
aed4552
20bc964
1b99064
5cd6913
208190f
3b90980
8e13336
cd690f2
1814a87
a147371
4d605a9
419d753
556537e
ecb9eac
2adac55
5e5402e
4b1c210
1faa9ec
8586a31
a0f8a3b
ca1388f
dddde99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Text.Json; | ||
|
||
namespace Microsoft.AspNetCore.Components.Endpoints; | ||
|
||
public class WebRootComponentParametersTest | ||
{ | ||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_ForMismatchedParameterCount() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParameters(new() { ["First"] = 123, ["Second"] = "abc" }); | ||
|
||
// Act | ||
var result = parameters1.DefinitelyEquals(parameters2); | ||
|
||
// Assert | ||
Assert.False(result); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_ForMismatchedParameterNames() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParameters(new() { ["Second"] = 123 }); | ||
|
||
// Act | ||
var result = parameters1.DefinitelyEquals(parameters2); | ||
|
||
// Assert | ||
Assert.False(result); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_ForMismatchedParameterValues() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParameters(new() { ["First"] = 456 }); | ||
|
||
// Act | ||
var result = parameters1.DefinitelyEquals(parameters2); | ||
|
||
// Assert | ||
Assert.False(result); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_ReturnsFalse_ForMismatchedParameterTypes() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParameters(new() { ["First"] = 123L }); | ||
|
||
// Act | ||
var result = parameters1.DefinitelyEquals(parameters2); | ||
|
||
// Assert | ||
Assert.False(result); | ||
} | ||
|
||
public static readonly object[][] DefinitelyEqualParameterValues = | ||
[ | ||
[123], | ||
["abc"], | ||
[new { First = 123, Second = "abc" }], | ||
]; | ||
|
||
[Theory] | ||
[MemberData(nameof(DefinitelyEqualParameterValues))] | ||
public void WebRootComponentParameters_DefinitelyEquals_ReturnsTrue_ForSameParameterValues(object value) | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new() { ["First"] = value }); | ||
var parameters2 = CreateParameters(new() { ["First"] = value }); | ||
|
||
// Act | ||
var result = parameters1.DefinitelyEquals(parameters2); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_ReturnsTrue_ForEmptySetOfParameters() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new()); | ||
var parameters2 = CreateParameters(new()); | ||
|
||
// Act | ||
var result = parameters1.DefinitelyEquals(parameters2); | ||
|
||
// Assert | ||
Assert.True(result); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_Throws_WhenComparingNonJsonElementParameterToJsonElement() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParametersWithNonJsonElements(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParameters(new() { ["First"] = 456 }); | ||
|
||
// Act/assert | ||
Assert.Throws<InvalidCastException>(() => parameters1.DefinitelyEquals(parameters2)); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_Throws_WhenComparingJsonElementParameterToNonJsonElement() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParameters(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParametersWithNonJsonElements(new() { ["First"] = 456 }); | ||
|
||
// Act/assert | ||
Assert.Throws<InvalidCastException>(() => parameters1.DefinitelyEquals(parameters2)); | ||
} | ||
|
||
[Fact] | ||
public void WebRootComponentParameters_DefinitelyEquals_Throws_WhenComparingNonJsonElementParameters() | ||
{ | ||
// Arrange | ||
var parameters1 = CreateParametersWithNonJsonElements(new() { ["First"] = 123 }); | ||
var parameters2 = CreateParametersWithNonJsonElements(new() { ["First"] = 456 }); | ||
|
||
// Act/assert | ||
Assert.Throws<InvalidCastException>(() => parameters1.DefinitelyEquals(parameters2)); | ||
} | ||
|
||
private static WebRootComponentParameters CreateParameters(Dictionary<string, object> parameters) | ||
{ | ||
var parameterView = ParameterView.FromDictionary(parameters); | ||
var (parameterDefinitions, parameterValues) = ComponentParameter.FromParameterView(parameterView); | ||
for (var i = 0; i < parameterValues.Count; i++) | ||
{ | ||
// WebRootComponentParameters expects parameter values to be JsonElements. | ||
var jsonElement = JsonSerializer.SerializeToElement(parameterValues[i]); | ||
parameterValues[i] = jsonElement; | ||
MackinnonBuck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
return new(parameterView, parameterDefinitions.AsReadOnly(), parameterValues.AsReadOnly()); | ||
} | ||
|
||
private static WebRootComponentParameters CreateParametersWithNonJsonElements(Dictionary<string, object> parameters) | ||
{ | ||
var parameterView = ParameterView.FromDictionary(parameters); | ||
var (parameterDefinitions, parameterValues) = ComponentParameter.FromParameterView(parameterView); | ||
return new(parameterView, parameterDefinitions.AsReadOnly(), parameterValues.AsReadOnly()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace Microsoft.AspNetCore.Components.Server; | ||
|
||
internal sealed class CircuitRootComponentOperation(RootComponentOperation operation, WebRootComponentDescriptor? descriptor = null) | ||
{ | ||
public RootComponentOperationType Type => operation.Type; | ||
|
||
public int SsrComponentId => operation.SsrComponentId; | ||
|
||
public WebRootComponentDescriptor? Descriptor => descriptor; | ||
} | ||
Comment on lines
+6
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For some background behind the reason I added this type: The way we deserialize component descriptors in Blazor Server is:
With the changes in this PR, Blazor Web root components need information that wasn't in
...and they don't rely on the I created this type (and |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,5 @@ internal interface IServerComponentDeserializer | |
bool TryDeserializeComponentDescriptorCollection( | ||
string serializedComponentRecords, | ||
out List<ComponentDescriptor> descriptors); | ||
bool TryDeserializeSingleComponentDescriptor(ComponentMarker record, [NotNullWhen(true)] out ComponentDescriptor? result); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method didn't need to be on this interface |
||
bool TryDeserializeRootComponentOperations(string serializedComponentOperations, out (RootComponentOperation, ComponentDescriptor?)[] operationsWithDescriptors); | ||
bool TryDeserializeRootComponentOperations(string serializedComponentOperations, [NotNullWhen(true)] out CircuitRootComponentOperation[]? operationsWithDescriptors); | ||
} |
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
key
was added toServerComponent
because it needs to be part of the data protected payload now.