Skip to content

Commit f5bf604

Browse files
committed
Fix in PrefixResolver
1 parent a054e1d commit f5bf604

File tree

4 files changed

+103
-21
lines changed

4 files changed

+103
-21
lines changed

src/Components/Endpoints/src/FormMapping/PrefixResolver.cs

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,47 +50,43 @@ private class FormKeyComparer(bool checkPrefix) : IComparer<FormKey>
5050
// When comparing values, y is the element we are trying to find.
5151
public int Compare(FormKey x, FormKey y)
5252
{
53-
var separatorX = 0;
54-
var separatorY = 0;
55-
var currentXPos = 0;
56-
var currentYPos = 0;
53+
int separatorX = 0, separatorY = 0, currentXPos = 0, currentYPos = 0;
5754
while (separatorX != -1 && separatorY != -1)
5855
{
5956
separatorX = x.Value.Span[currentXPos..].IndexOfAny('.', '[');
6057
separatorY = y.Value.Span[currentYPos..].IndexOfAny('.', '[');
58+
int compare;
6159

6260
if (separatorX == -1 && separatorY == -1)
6361
{
64-
// no more segments, compare the remaining substrings
62+
// Both x and y have no more segments, compare the remaining segments
6563
return MemoryExtensions.CompareTo(x.Value.Span[currentXPos..], y.Value.Span[currentYPos..], StringComparison.Ordinal);
6664
}
6765
else if (separatorX == -1)
6866
{
69-
// x has no more segments, but y does, so x is less than y
70-
return -1;
67+
// x has no more segments, y has remaining segments
68+
compare = MemoryExtensions.CompareTo(x.Value.Span[currentXPos..], y.Value.Span[currentYPos..][..separatorY], StringComparison.Ordinal);
69+
if (compare == 0 && !checkPrefix)
70+
{
71+
return -1;
72+
}
73+
return compare;
7174
}
7275
else if (separatorY == -1)
7376
{
74-
if (!checkPrefix)
77+
// y has no more segments, x has remaining segments
78+
compare = MemoryExtensions.CompareTo(x.Value.Span[currentXPos..][..separatorX], y.Value.Span[currentYPos..], StringComparison.Ordinal);
79+
if (compare == 0 && !checkPrefix)
7580
{
76-
// We are just sorting, so x is greater than y because it has more segments.
7781
return 1;
7882
}
79-
80-
var match = MemoryExtensions.CompareTo(
81-
x.Value.Span[currentXPos..][..separatorX],
82-
y.Value.Span[currentYPos..], StringComparison.Ordinal);
83-
84-
return match;
83+
return compare;
8584
}
8685

87-
// both have segments, compare the segments
88-
var segmentX = x.Value.Span[currentXPos..][..separatorX];
89-
var segmentY = y.Value.Span[currentYPos..][..separatorY];
90-
var compareResult = MemoryExtensions.CompareTo(segmentX, segmentY, StringComparison.Ordinal);
91-
if (compareResult != 0)
86+
compare = MemoryExtensions.CompareTo(x.Value.Span[currentXPos..][..separatorX], y.Value.Span[currentYPos..][..separatorY], StringComparison.Ordinal);
87+
if (compare != 0)
9288
{
93-
return compareResult;
89+
return compare;
9490
}
9591

9692
currentXPos += separatorX + 1;

src/Components/Endpoints/test/Binding/PrefixResolverTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,40 @@ public void ContainsPrefix_HasEntries_NoMatch(string prefix)
7979
Assert.False(result);
8080
}
8181

82+
[Theory]
83+
[InlineData("Model")]
84+
[InlineData("Model.Model")]
85+
[InlineData("Model[0].Model")]
86+
public void ContainsPrefix_HasEntries(string prefix)
87+
{
88+
// Arrange - Simulating the exact scenario from debugging
89+
var keys = new string[] { "__RequestVerificationToken", "_handler", "Model.Name", "Model.Model.Name", "Model[0].Model.Name", "Model[0].Name" };
90+
var container = new PrefixResolver(GetKeys(keys), keys.Length);
91+
92+
// Act
93+
var result = container.HasPrefix(prefix.AsMemory());
94+
95+
// Assert
96+
Assert.True(result);
97+
}
98+
99+
[Theory]
100+
[InlineData("Model")]
101+
[InlineData("Model.Model")]
102+
[InlineData("Model[0].Model")]
103+
public void ContainsPrefix_DoesNotHaveEntries(string prefix)
104+
{
105+
// Arrange - Simulating the exact scenario from debugging
106+
var keys = new string[] { "__RequestVerificationToken", "_handler" };
107+
var container = new PrefixResolver(GetKeys(keys), keys.Length);
108+
109+
// Act
110+
var result = container.HasPrefix(prefix.AsMemory());
111+
112+
// Assert
113+
Assert.False(result);
114+
}
115+
82116
[Theory]
83117
[InlineData("a")]
84118
[InlineData("b")]

src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,16 @@ void AssertUiState(string expectedStringValue, bool expectedBoolValue)
14221422
}
14231423
}
14241424

1425+
[Fact]
1426+
public void EditFormRecursiveBinding()
1427+
{
1428+
GoTo("forms/recursive-edit-form");
1429+
Browser.Equal("", () => Browser.Exists(By.Id("result-form")).Text);
1430+
Browser.Exists(By.Id("text-input")).SendKeys("John");
1431+
Browser.Exists(By.Id("submit-button")).Click();
1432+
Browser.Equal("John", () => Browser.Exists(By.Id("result-form")).Text);
1433+
}
1434+
14251435
[Fact]
14261436
public void RadioButtonGetsResetAfterSubmittingEnhancedForm()
14271437
{
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
@page "/forms/recursive-edit-form"
2+
@using Microsoft.AspNetCore.Components.Forms
3+
4+
<PageTitle>Home</PageTitle>
5+
6+
<EditForm EditContext="FormContext" OnSubmit="Submit" FormName="RequestForm">
7+
<InputText id="text-input" @bind-Value="Model!.Name" />
8+
<button type="submit" id="submit-button">Submit</button>
9+
</EditForm>
10+
11+
<p id="result-form">@ModelName</p>
12+
13+
@code {
14+
string ModelName;
15+
16+
[SupplyParameterFromForm(FormName = "RequestForm")]
17+
private MyModel? Model { get; set; }
18+
19+
private EditContext FormContext = null!;
20+
21+
public class MyModel
22+
{
23+
public string? Name { get; set; }
24+
25+
public MyModel? Parent { get; set; }
26+
}
27+
28+
protected override void OnInitialized()
29+
{
30+
if (Model == null)
31+
{
32+
Model = new();
33+
}
34+
35+
FormContext = new EditContext(Model);
36+
}
37+
38+
private void Submit()
39+
{
40+
ModelName = Model?.Name ?? string.Empty;
41+
}
42+
}

0 commit comments

Comments
 (0)