Skip to content

Commit

Permalink
Improve error handling of CommandResolver: missing markup control
Browse files Browse the repository at this point in the history
  • Loading branch information
exyi committed Feb 25, 2024
1 parent e70ab8e commit dd7cf40
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 3 deletions.
73 changes: 71 additions & 2 deletions src/Framework/Framework/Controls/DotvvmControlProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,11 @@ public DotvvmPropertyDictionary(DotvvmBindableObject control)

public object? this[DotvvmProperty key] { get => control.properties.GetOrThrow(key); set => control.properties.Set(key, value); }

public ICollection<DotvvmProperty> Keys => throw new NotImplementedException();
public KeysCollection Keys => new KeysCollection(control);
ICollection<DotvvmProperty> IDictionary<DotvvmProperty, object?>.Keys => Keys;

public ICollection<object?> Values => throw new NotImplementedException();
public ValuesCollection Values => new ValuesCollection(control);
ICollection<object?> IDictionary<DotvvmProperty, object?>.Values => Values;

public int Count => control.properties.Count();
public bool IsReadOnly => false;
Expand Down Expand Up @@ -442,5 +444,72 @@ public bool TryGetValue(DotvvmProperty key, out object? value) =>
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();

IEnumerator<KeyValuePair<DotvvmProperty, object?>> IEnumerable<KeyValuePair<DotvvmProperty, object?>>.GetEnumerator() => this.GetEnumerator();


public readonly struct KeysCollection : ICollection<DotvvmProperty>, IReadOnlyCollection<DotvvmProperty>
{
private readonly DotvvmBindableObject control;

public KeysCollection(DotvvmBindableObject control) { this.control = control; }
public int Count => control.properties.Count();

public bool IsReadOnly => true;
public void Add(DotvvmProperty item) => throw new NotSupportedException("Adding a property without value doesn't make sense");
public void Clear() => throw new NotSupportedException("Explicitly use control.Properties.Clear() instead.");
public bool Contains(DotvvmProperty item) => control.properties.Contains(item);
public void CopyTo(DotvvmProperty[] array, int arrayIndex)
{
foreach (var x in control.properties)
{
array[arrayIndex++] = x.Key;
}
}
public IEnumerator<DotvvmProperty> GetEnumerator()
{
foreach (var x in control.properties)
{
yield return x.Key;
}
}
public bool Remove(DotvvmProperty item) => throw new NotSupportedException("Explicitly use control.Properties.Remove() instead.");
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

public struct ValuesCollection : ICollection<object?>
{
private readonly DotvvmBindableObject control;

public ValuesCollection(DotvvmBindableObject control) { this.control = control; }
public int Count => control.properties.Count();

public bool IsReadOnly => true;
public void Add(object? item) => throw new NotSupportedException("Adding a value without property doesn't make sense");
public void Clear() => throw new NotSupportedException("Explicitly use control.Properties.Clear() instead.");
public bool Contains(object? item)
{
foreach (var x in control.properties)
{
if (Object.Equals(x.Value, item))
return true;
}
return false;
}
public void CopyTo(object?[] array, int arrayIndex)
{
foreach (var x in control.properties)
{
array[arrayIndex++] = x.Value;
}
}
public IEnumerator<object?> GetEnumerator()
{
foreach (var x in control.properties)
{
yield return x.Value;
}
}
public bool Remove(object? item) => throw new NotSupportedException("Explicitly use control.Properties.Remove() instead.");
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,13 @@ public void PopulateViewModel(IDotvvmRequestContext context, string serializedPo
var target = view.FindControlByUniqueId(controlUniqueId);
if (target == null)
{
throw new Exception(string.Format("The control with ID '{0}' was not found!", controlUniqueId));
var markupControls =
view.GetAllDescendants()
.OfType<DotvvmMarkupControl>()
.Where(c => c.GetAllDescendants(cc => cc is not DotvvmMarkupControl)
.Any(cc => cc.Properties.Values
.Any(value => value is Binding.Expressions.CommandBindingExpression cb && cb.BindingId == command)));
throw new Exception($"The control with ID '{controlUniqueId}' was not found! Existing markup controls with this command are: {string.Join(", ", markupControls.Select(c => c.GetDotvvmUniqueId().ToString()).OrderBy(s => s, StringComparer.Ordinal))}");
}
return commandResolver.GetFunction(target, view, context, path!, command, args);
}
Expand Down

0 comments on commit dd7cf40

Please sign in to comment.