Skip to content

Commit c48a0eb

Browse files
authored
Fixed rendering of self closing elements (dotnet#46347)
* fixed rendering of self closing elements
1 parent c160b85 commit c48a0eb

File tree

2 files changed

+69
-1
lines changed

2 files changed

+69
-1
lines changed

src/Mvc/Mvc.ViewFeatures/src/RazorComponents/HtmlRenderer.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,14 @@ private static int RenderAttributes(
228228
{
229229
var candidateIndex = position + i;
230230
ref var frame = ref frames.Array[candidateIndex];
231+
231232
if (frame.FrameType != RenderTreeFrameType.Attribute)
232233
{
234+
if (frame.FrameType == RenderTreeFrameType.ElementReferenceCapture)
235+
{
236+
continue;
237+
}
238+
233239
return candidateIndex;
234240
}
235241

@@ -311,4 +317,3 @@ public void WriteTo(TextWriter writer, HtmlEncoder encoder)
311317
}
312318
}
313319
}
314-

src/Mvc/Mvc.ViewFeatures/test/RazorComponents/HtmlRendererTest.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,69 @@ public void RenderComponentAsync_ValueAttributeOfTextareaElementOverridesTextCon
402402
AssertHtmlContentEquals(expectedHtml, result);
403403
}
404404

405+
[Fact]
406+
public void RenderComponentAsync_RendersSelfClosingElement()
407+
{
408+
// Arrange
409+
var expectedHtml = "<input value=\"Hello &lt;html&gt;-encoded content!\" id=\"Test\" />";
410+
var serviceProvider = new ServiceCollection().AddSingleton(new RenderFragment(rtb =>
411+
{
412+
rtb.OpenElement(0, "input");
413+
rtb.AddAttribute(1, "value", "Hello <html>-encoded content!");
414+
rtb.AddAttribute(2, "id", "Test");
415+
rtb.CloseElement();
416+
})).BuildServiceProvider();
417+
var htmlRenderer = GetHtmlRenderer(serviceProvider);
418+
419+
// Act
420+
var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync<TestComponent>(ParameterView.Empty)));
421+
422+
// Assert
423+
AssertHtmlContentEquals(expectedHtml, result);
424+
}
425+
426+
[Fact]
427+
public void RenderComponentAsync_RendersSelfClosingElementWithTextComponentAsNormalElement()
428+
{
429+
// Arrange
430+
var expectedHtml = "<meta>Something</meta>";
431+
var serviceProvider = new ServiceCollection().AddSingleton(new RenderFragment(rtb =>
432+
{
433+
rtb.OpenElement(0, "meta");
434+
rtb.AddContent(1, "Something");
435+
rtb.CloseElement();
436+
})).BuildServiceProvider();
437+
var htmlRenderer = GetHtmlRenderer(serviceProvider);
438+
439+
// Act
440+
var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync<TestComponent>(ParameterView.Empty)));
441+
442+
// Assert
443+
AssertHtmlContentEquals(expectedHtml, result);
444+
}
445+
446+
[Fact]
447+
public void RenderComponentAsync_RendersSelfClosingElementBySkippingElementReferenceCapture()
448+
{
449+
// Arrange
450+
var expectedHtml = "<input value=\"Hello &lt;html&gt;-encoded content!\" id=\"Test\" />";
451+
var serviceProvider = new ServiceCollection().AddSingleton(new RenderFragment(rtb =>
452+
{
453+
rtb.OpenElement(0, "input");
454+
rtb.AddAttribute(1, "value", "Hello <html>-encoded content!");
455+
rtb.AddAttribute(2, "id", "Test");
456+
rtb.AddElementReferenceCapture(3, inputReference => _ = inputReference);
457+
rtb.CloseElement();
458+
})).BuildServiceProvider();
459+
var htmlRenderer = GetHtmlRenderer(serviceProvider);
460+
461+
// Act
462+
var result = GetResult(htmlRenderer.Dispatcher.InvokeAsync(() => htmlRenderer.RenderComponentAsync<TestComponent>(ParameterView.Empty)));
463+
464+
// Assert
465+
AssertHtmlContentEquals(expectedHtml, result);
466+
}
467+
405468
[Fact]
406469
public void RenderComponentAsync_MarksSelectedOptionsAsSelected_WithOptGroups()
407470
{

0 commit comments

Comments
 (0)