Skip to content
6 changes: 2 additions & 4 deletions src/Controls/src/Xaml/ApplyPropertiesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,8 @@ void ProvideValue(ref object value, ElementNode node, object source, XmlName pro
}
catch (Exception e)
{
if (Context.ExceptionHandler != null)
Context.ExceptionHandler(e);
else
throw e;
Context.ExceptionHandler?.Invoke(e);
throw;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,15 @@ public object ProvideValue(IServiceProvider serviceProvider)
&& !TryGetApplicationLevelResource(Key, out resource, out resourceDictionary))
{
var xmlLineInfo = serviceProvider.GetService(typeof(IXmlLineInfoProvider)) is IXmlLineInfoProvider xmlLineInfoProvider ? xmlLineInfoProvider.XmlLineInfo : null;
var ex = new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
if (Controls.Internals.ResourceLoader.ExceptionHandler2 is var ehandler && ehandler != null)
{
var ex = new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider));
var root = rootObjectProvider.RootObject;
ehandler.Invoke((ex, XamlFilePathAttribute.GetFilePathForObject(root)));
return null;
}
else
throw new XamlParseException($"StaticResource not found for key {Key}", xmlLineInfo);
// Throw an exception when the key is not found
throw ex;
}

Diagnostics.ResourceDictionaryDiagnostics.OnStaticResourceResolved(resourceDictionary, Key, valueProvider.TargetObject, valueProvider.TargetProperty);
Expand Down
45 changes: 45 additions & 0 deletions src/Controls/tests/DeviceTests/Xaml/StaticResourceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Xaml;
using Xunit;

namespace Microsoft.Maui.DeviceTests;

[Category(TestCategory.Xaml)]
public class StaticResourceTests
{
[Fact("Issue #23903: Missing ControlTemplate with exception handler should throw")]
[RequiresUnreferencedCode("XAML parsing may require unreferenced code")]
public void MissingControlTemplate_WithExceptionHandler_ShouldThrow()
{
// Issue #23903: StaticResourceExtension should always throw when resource is not found,
// even when an exception handler is present (for debug/hot reload scenarios).
// This prevents the app from crashing when relaunching.

Controls.Internals.ResourceLoader.ExceptionHandler2 = (ex) => { };

var xaml = """
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
ControlTemplate="{StaticResource InvalidTemplate}">
</ContentPage>
""";

var page = new ContentPage();

// Should throw an exception even with handler present
bool exceptionThrown = false;
try
{
page.LoadFromXaml(xaml);
}
catch (Exception)
{
exceptionThrown = true;
}

Assert.True(exceptionThrown, "Expected an exception to be thrown for missing ControlTemplate");
}
}
Loading