[Bug]: Router State is No Longer Saved To Disk
worldbeater opened this issue ยท 4 comments
Describe the bug ๐
Earlier, we were able to save RoutingState.NavigationStack
to disk, as the collection was annotated as a [DataMember]
: https://github.com/reactiveui/ReactiveUI/blame/a43e99ae2fbcd644460f245f471f573b7d3b66ec/src/ReactiveUI/Routing/RoutingState.cs#L26-L27
But now, the observable collection is [IgnoreDataMember]
d: https://github.com/reactiveui/ReactiveUI/blob/main/src/ReactiveUI/Routing/RoutingState.cs#L50-L51
Step to reproduce
- Clone https://github.com/reactiveui/ReactiveUI.Samples/
- Navigate to https://github.com/reactiveui/ReactiveUI.Samples/tree/main/avalonia/suspension/
- Launch
ReactiveUI.Samples.Suspension.sln
, - Try updating ReactiveUI to the latest version,
RoutingState.NavigationStack
is no longer saved to disk when the app is closed.
Reproduction repository
https://github.com/reactiveui/ReactiveUI.Samples/
Expected behavior
ReactiveUI suspension feature used to be working according to this guide: https://habr.com/en/post/462307/
And according to the documentation page: https://www.reactiveui.net/docs/handbook/data-persistence/
Probably worth marking NavigationStack
as DataMember
again and adding back a default ctor, if this won't cause issues, and if these were removed unintentionally.
ReactiveUI Version
17.0.1+
I encountered this issue and wrote this hack to get around it:
private sealed class NavigationStackResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var props = base.CreateProperties(type, memberSerialization);
foreach (var prop in props)
{
if (prop.DeclaringType == typeof(RoutingState)
&& prop.PropertyName == nameof(RoutingState.NavigationStack))
{
prop.Ignored = false;
prop.Writable = true;
prop.ValueProvider = new NavigationStackValueProvider(prop.ValueProvider!);
}
}
return props;
}
}
private sealed class NavigationStackValueProvider : IValueProvider
{
private readonly IValueProvider _Original;
public NavigationStackValueProvider(IValueProvider original)
{
_Original = original;
}
public object? GetValue(object target)
=> _Original.GetValue(target);
public void SetValue(object target, object? value)
{
var castedTarget = (RoutingState)target!;
var castedValue = (IEnumerable<IRoutableViewModel>)value!;
castedTarget.NavigationStack.Clear();
foreach (var vm in castedValue)
{
castedTarget.NavigationStack.Add(vm);
}
}
}
If anyone is willing, be happy to take a PR for the affected systems. I been under the pump lately and should be a easy PR for anyone to pick up.
Also thanks for the workaround @advorange