diff --git a/src/Framework/Framework/Compilation/Directives/PropertyDeclarationDirectiveCompiler.cs b/src/Framework/Framework/Compilation/Directives/PropertyDeclarationDirectiveCompiler.cs index e9405be5dc..4131d51b1e 100644 --- a/src/Framework/Framework/Compilation/Directives/PropertyDeclarationDirectiveCompiler.cs +++ b/src/Framework/Framework/Compilation/Directives/PropertyDeclarationDirectiveCompiler.cs @@ -159,8 +159,10 @@ ImmutableList propertyDirectives baseType.FullName + "||" + string.Join("|", imports) + "||" + string.Join("|", properties) ) ); - var hash = Convert.ToBase64String(hashBytes, 0, 16); - + var hash = Convert.ToBase64String(hashBytes, 0, 16) + .Replace('+', '_') + .Replace('/', '_') + .TrimEnd('='); var typeName = "DotvvmMarkupControl-" + hash; return GetOrCreateDynamicType(baseType, typeName, propertyDirectives); diff --git a/src/Framework/Framework/Compilation/Directives/ResolvedPropertyDeclarationDirectiveCompiler.cs b/src/Framework/Framework/Compilation/Directives/ResolvedPropertyDeclarationDirectiveCompiler.cs index 97e66aeb88..c94b125f87 100644 --- a/src/Framework/Framework/Compilation/Directives/ResolvedPropertyDeclarationDirectiveCompiler.cs +++ b/src/Framework/Framework/Compilation/Directives/ResolvedPropertyDeclarationDirectiveCompiler.cs @@ -12,6 +12,7 @@ namespace DotVVM.Framework.Compilation.Directives public class ResolvedPropertyDeclarationDirectiveCompiler : PropertyDeclarationDirectiveCompiler { private static readonly Lazy DynamicMarkupControlAssembly = new(CreateDynamicMarkupControlAssembly); + private static readonly object locker = new(); public ResolvedPropertyDeclarationDirectiveCompiler( ImmutableDictionary> directiveNodesByName, @@ -45,18 +46,29 @@ protected override IPropertyDescriptor TryCreateDotvvmPropertyFromDirective(IAbs string typeName, ImmutableList propertyDirectives) { - if (DynamicMarkupControlAssembly.Value.GetType(typeName) is { } type) + // this must be done in the lock, otherwise the DynamicMarkupControlAssembly can return TypeBuilder instead of fully-built System.Type + lock (locker) { - return new ResolvedTypeDescriptor(type); - } + if (DynamicMarkupControlAssembly.Value.GetType(typeName) is { } type) + { + return new ResolvedTypeDescriptor(type); + } - var declaringTypeBuilder = - DynamicMarkupControlAssembly.Value.DefineType(typeName, TypeAttributes.Public, ResolvedTypeDescriptor.ToSystemType(baseType)); - var createdTypeInfo = declaringTypeBuilder.CreateTypeInfo()?.AsType(); + try + { + var declaringTypeBuilder = + DynamicMarkupControlAssembly.Value.DefineType(typeName, TypeAttributes.Public, ResolvedTypeDescriptor.ToSystemType(baseType)); + var createdTypeInfo = declaringTypeBuilder.CreateTypeInfo()?.AsType(); - return createdTypeInfo is not null - ? new ResolvedTypeDescriptor(createdTypeInfo) - : null; + return createdTypeInfo is not null + ? new ResolvedTypeDescriptor(createdTypeInfo) + : null; + } + catch (Exception ex) + { + throw new InvalidOperationException($"Failed to create dynamic type '{typeName}'", ex); + } + } } private static ModuleBuilder CreateDynamicMarkupControlAssembly() diff --git a/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-client.html b/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-client.html index 045eb23e48..06c8ef08cb 100644 --- a/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-client.html +++ b/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-client.html @@ -7,7 +7,7 @@ diff --git a/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-server.html b/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-server.html index c37b3bba11..35facebde8 100644 --- a/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-server.html +++ b/src/Tests/ControlTests/testoutputs/HierarchyRepeaterTests.CommandInMarkupControl-server.html @@ -4,19 +4,19 @@
-
+
-
+
-
+
-
+
-
+