Try our conversational search powered by Generative AI!

Razor component in blocks fails with an InvalidOperationException when rendered using PropertyFor

Vote:
 

I know that this is an extreme edge case but figured that anyone that's as curious as we are on Blazor and Razor components might run into this issue.

If you happen to build a Block that will end up rendering a Razor component with server interactivity you may end up with the following exception and stacktrace:

System.InvalidOperationException: The current thread is not associated with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher when triggering rendering or component state.
         at Microsoft.AspNetCore.Components.Dispatcher.AssertAccess()
         at Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure.StaticHtmlRenderer.WriteComponentHtml(Int32 componentId, TextWriter output)
         at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.WriteComponentHtml(Int32 componentId, TextWriter output, Boolean allowBoundaryMarkers, SequenceAndKey sequenceAndKey)
         at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.WriteComponentHtml(Int32 componentId, TextWriter output)
         at Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.PrerenderedComponentHtmlContent.WriteTo(TextWriter writer, HtmlEncoder encoder)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers.ViewBuffer.WriteTo(TextWriter writer, HtmlEncoder encoder)
         at EPiServer.Web.Mvc.Html.Internal.WrappedHtmlContent.WriteTo(TextWriter writer, HtmlEncoder encoder)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers.ViewBuffer.WriteToAsync(TextWriter writer, HtmlEncoder encoder)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(ViewContext context, ViewBufferTextWriter bodyWriter)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderLayoutAsync(ViewContext context, ViewBufferTextWriter bodyWriter)
         at Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
         at Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, String contentType, Nullable`1 statusCode)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
      --- End of stack trace from previous location ---
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
         at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
         at EPiServer.Cms.Shell.UI.Internal.RegisterAdminUserMiddleware.InvokeAsync(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
         at EPiServer.Middleware.InitializeOnFirstRequestMiddleware.InvokeAsync(HttpContext httpContext)
         at EPiServer.Framework.DependencyInjection.Internal.VisitorGroupMiddleware.Invoke(HttpContext httpContext)
         at Microsoft.WebTools.BrowserLink.Net.BrowserLinkMiddleware.InvokeAsync(HttpContext context)
         at Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware.InvokeAsync(HttpContext context)
         at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

This issue seems to occur when you're rendering this block in a contentarea using @Html.PropertyFor(m => m.MyContentArea).
If you change @Html.PropertyFor to @Html.DisplayFor or use the new epi-property-taghelper - this problem does not take place.

Just to clarify, a block vith a view like this:
CounterBlock.cshtml

@model CounterBlock

<h3>Hello Counter Block</h3>
<component type="typeof(Counter)" render-mode="ServerPrerendered" />

cannot be rendered using @Html.PropertyFor.

ArticlePage.cshtml

@* This works *@
<div epi-property="CurrentContent.MainBody" />

@* This works *@
@Html.DisplayFor(x => x.CurrentContent.MainBody)

@* This also works *@
@{ Html.RenderContentArea(Model.CurrentContent.MainBody); }

@* But this does not work *@
@Html.PropertyFor(x => x.CurrentContent.MainBody)


I pushed my examples to a new empty CMS site if anyone wants run this themselves: https://github.com/KevinJCandlert/epi-razor-component-issue/tree/master


#319644
Edited, Mar 28, 2024 22:16
Karol Berezicki - Mar 29, 2024 8:53
Hi Kevin, just wanted to let you know that the repository seems to be private.
Yet I was able to reproduce it in my project.
Kevin Candlert - Mar 30, 2024 19:59
oh shoot! It's fixed now, thanks! 😄
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.