Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ public class ConstantDataContextChangeAttribute : DataContextChangeAttribute
public override int Order { get; }
public bool? ServerSideOnly { get; }

public ConstantDataContextChangeAttribute(Type type, int order = 0, bool? serverSideOnly = null)
public ConstantDataContextChangeAttribute(Type type, int order = 0)
{
Type = type;
Order = order;
ServerSideOnly = null;
}

public ConstantDataContextChangeAttribute(Type type, int order, bool serverSideOnly)
{
Type = type;
Order = order;
ServerSideOnly = serverSideOnly;
}

public override ITypeDescriptor? GetChildDataContextType(ITypeDescriptor dataContext, IDataContextStack controlContextStack, IAbstractControl control, IPropertyDescriptor? property = null)
{
return new ResolvedTypeDescriptor(Type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ namespace DotVVM.Framework.Configuration
public sealed class DefaultSerializerSettingsProvider
{
private const int defaultMaxSerializationDepth = 64;
internal readonly JsonSerializerOptions SettingsHtmlUnsafe;
internal readonly JsonSerializerOptions Settings;
public readonly JsonSerializerOptions SettingsHtmlUnsafe;
public readonly JsonSerializerOptions Settings;

// We need to encode for script tags (i.e. either < or / has to go) and for HTML comments (< and > have to go - https://html.spec.whatwg.org/#comments)
// The default JavaScriptEncoder is just annoyingly paranoid, I'm not interested in having all non-ASCII characters escaped to unicode codepoints
Expand All @@ -25,7 +25,7 @@ public sealed class DefaultSerializerSettingsProvider
// https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-DoubleStringCharacter
// - it says « SourceCharacter [=any Unicode code point] but not one of " or \ or LineTerminator »
// ...which isn't allowed in JSON in any context anyway
internal readonly JavaScriptEncoder HtmlSafeLessParanoidEncoder;
public readonly JavaScriptEncoder HtmlSafeLessParanoidEncoder;

private JsonSerializerOptions CreateSettings()
{
Expand Down
1 change: 0 additions & 1 deletion src/Framework/Framework/Controls/DotvvmBindableObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ namespace DotVVM.Framework.Controls

[ContainsDotvvmProperties]
[ControlMarkupOptions(AllowContent = true)]
[System.Text.Json.Serialization.JsonConverter(typeof(DotvvmControlDebugJsonConverter))]
public abstract class DotvvmBindableObject: IDotvvmObjectLike
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@ internal class DotvvmControlDebugJsonConverter() : GenericWriterJsonConverter<ID
else
{
w.WritePropertyName(name);
JsonSerializer.Serialize(w, rawValue, options);
try
{
JsonSerializer.Serialize(w, rawValue, options);
}
catch (Exception ex)
{
// don't crash error page when there is some error in serialization
w.WriteStringValue($"Error serializing property {name}: {ex.Message}");
}
}
}
w.WriteEndObject();
Expand Down
2 changes: 2 additions & 0 deletions src/Framework/Framework/Controls/IDotvvmControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
using DotVVM.Framework.Runtime;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace DotVVM.Framework.Controls
{
/// <summary> Object which is basically DotvvmBindableObject. This interface is useful for defining interfaces for controls, otherwise please prefer using DotvvmBindableObject directly. </summary>
public interface IDotvvmObjectLike
{
/// <summary> Returns itself. This is a kinda hack which allows interfaces to inherit from almost DotvvmBindableObject </summary>
[JsonIgnore]
DotvvmBindableObject Self { get; }
}
/// <summary> Marker interface for DotvvmBindableObject which have the specified capability. If no capability of type TCapability is defined, it will be registered automatically. </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ internal static JsonNode SerializeObjectForBrowser(object? obj)
Converters = {
new DebugReflectionTypeJsonConverter(),
new ReflectionAssemblyJsonConverter(),
new ReflectionTypeJsonConverter(),
new DotvvmTypeDescriptorJsonConverter<ITypeDescriptor>(),
new Controls.DotvvmControlDebugJsonConverter(),
new BindingDebugJsonConverter(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using DotVVM.Framework.Utils;

namespace DotVVM.Framework.ResourceManagement
{
public class ReflectionAssemblyJsonConverter : JsonConverter<Assembly>
{
public override Assembly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
return Assembly.Load(new AssemblyName(reader.GetString()!));
}
else throw new NotSupportedException();
throw new NotSupportedException();
}

public override void Write(Utf8JsonWriter writer, Assembly value, JsonSerializerOptions options)
Expand All @@ -32,12 +29,7 @@ public class ReflectionTypeJsonConverter : JsonConverter<Type>
{
public override Type Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var name = reader.GetString()!;
return Type.GetType(name) ?? throw new Exception($"Cannot find type {name}.");
}
else throw new NotSupportedException();
throw new NotSupportedException();
}

public override void Write(Utf8JsonWriter writer, Type t, JsonSerializerOptions options)
Expand All @@ -62,15 +54,7 @@ public class DotvvmTypeDescriptorJsonConverter<T> : JsonConverter<T>
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var name = reader.GetString()!;
ITypeDescriptor result = new ResolvedTypeDescriptor(Type.GetType(name) ?? throw new Exception($"Cannot find type {name}."));
if (result is T t)
return t;
else throw new NotSupportedException($"Cannot deserialize {typeToConvert}");
}
else throw new NotSupportedException();
throw new NotSupportedException();
}

public override void Write(Utf8JsonWriter writer, T t, JsonSerializerOptions options)
Expand Down Expand Up @@ -105,7 +89,15 @@ internal static void WriteObjectReflection(Utf8JsonWriter writer, object attribu

writer.WritePropertyName(prop.Name);

JsonSerializer.Serialize(writer, prop.GetValue(attribute), options);
var value = prop.GetValue(attribute);

// NB: RuntimeType is internal, so we need to use first public base type
var valueType = value?.GetType() ?? typeof(object);
while (!valueType.IsPublicType() || valueType == typeof(TypeInfo))
{
valueType = valueType.BaseType!;
}
JsonSerializer.Serialize(writer, value, valueType, options);
}
writer.WriteEndObject();
}
Expand Down
Loading