dotnet/aspnetcore

Tilde ~ in HTML tag path segments of Razor pages breaks hot reload

Closed this issue · 6 comments

Ducki commented

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Using the ~ tilde character in path segments of HTML tags in Razor pages leads to exceptions while recompiling and reloading in dotnet watch mode.

I have created a minimal repo, to reproduce the issue: https://github.com/Ducki/TildeTest

Start the app with dotnet watch and then add/change some text in the Tilde.cshtml file, which has an img tag using the ~ in its src attribute. The app should crash.

Contrary, in NoTilde.cshtml, you can make changes without the app crashing, because no ~ is used in any path.

Running on MacOS (arm64).

Expected Behavior

Compile the changed page and display.

Exceptions (if any)

fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMK4210DVC3O", Request id "0HMK4210DVC3O:00000003": An unhandled exception was thrown by the application.
System.AggregateException: An error occurred while writing to logger(s). (Could not load type 'REDACTED.Pages.Projects.Installations.Plans.Pages_Projects_Installations_Plans_Landing+d__17#1' from assembly 'REDACTED, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.)
---> System.TypeLoadException: Could not load type 'REDACTED.Pages.Projects.Installations.Plans.Pages_Projects_Installations_Plans_Landing+d__17#1' from assembly 'KNX-Manager, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder1 derivedAttributes)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType)
at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
at System.Reflection.RuntimeMethodInfo.GetCustomAttributes(Type attributeType, Boolean inherit)
at System.Attribute.GetCustomAttributes(MemberInfo element, Type attributeType, Boolean inherit)
at System.Reflection.CustomAttributeExtensions.GetCustomAttributes[T](MemberInfo element, Boolean inherit)
at System.Diagnostics.StackTrace.TryResolveStateMachineMethod(MethodBase& method, Type& declaringType)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat, StringBuilder sb)
at System.Diagnostics.StackTrace.ToString(TraceFormat traceFormat)
at System.Exception.get_StackTrace()
at System.Exception.ToString()
at Microsoft.Extensions.Logging.Console.SimpleConsoleFormatter.CreateDefaultLogMessage[TState](TextWriter textWriter, LogEntry1& logEntry, String message, IExternalScopeProvider scopeProvider) at Microsoft.Extensions.Logging.Console.SimpleConsoleFormatter.Write[TState](LogEntry1& logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter)
at Microsoft.Extensions.Logging.Console.ConsoleLogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func3 formatter) at Microsoft.Extensions.Logging.Logger.<Log>g__LoggerLog|12_0[TState](LogLevel logLevel, EventId eventId, ILogger logger, Exception exception, Func3 formatter, List1& exceptions, TState& state) --- End of inner exception stack trace --- at Microsoft.Extensions.Logging.Logger.ThrowLoggingError(List1 exceptions)
at Microsoft.Extensions.Logging.Logger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func3 formatter) at Microsoft.Extensions.Logging.Logger1.Microsoft.Extensions.Logging.ILogger.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func3 formatter) at Microsoft.Extensions.Logging.LoggerMessage.<>c__DisplayClass8_0.<Define>g__Log|0(ILogger logger, Exception exception) at Microsoft.AspNetCore.Diagnostics.DiagnosticsLoggerExtensions.UnhandledException(ILogger logger, Exception exception) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware.InvokeAsync(HttpContext context) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application)

.NET Version

6.0.400

Anything else?

No response

@Ducki thanks for contacting us.

This very likely has to do with the "~" changing the semantics from an attribute literal to a tag helper.

Ducki commented

I have investigated a litte further.
It seems that it is unrelated to the tilde/UrlResolutionTagHelper. Rather, the issue always appears when modifying the _Layout.cshtml file. Also, (in a bigger project of mine) I am facing the issue when editing normal razor pages (meaning no _Layout.cshtml).

There is another report of this issue on Stackoverflow.

@Ducki could you turn on EmitCompilerGeneratedFiles in your csproj and capture the generated code before and after the change?

Ducki commented

I tried.
When starting dotnet watch, the first batch of the generated razor files gets compiled.
But it when making a change in the file, the generated files don't get updated – neither in a successful reload nor a faulty. Not sure if that's by design, that hot reload only alters those generated results in memory?

@Ducki taking a second look, I think this is a regression that we fixed recently. @tmat this looks familiar to the issue we investigated recently, doesn't it?

Looks like the same or a very similar thing happens with any custom tag helper: #43593. From what I can tell, the issue is unrelated to tilde or any specific file.