dotnet / dotnet/wpf

XAML Compiler generates incorrect lowercase resource URI when using custom Application-derived class in App.xaml

Open
#11,260 1 comment 0 reactions 0 assignees View on GitHub
Investigate
Dominant language
C#
Stars
7.7k
Forks
1.3k
Avg merge
1d 11h
Merged PRs (30d)
61

Description

## Summary
When using a custom class that derives from `Application` as the root element in `App.xaml`, the XAML compiler generates a lowercase resource URI (`app.xaml`) instead of preserving the actual file name case (`App.xaml`). This causes a runtime error because the resource cannot be located.

## Environment
- .NET Version: 10.0
- WPF Version: 10.0
- OS: Windows 11
- SDK Style Project: Yes

## Steps to Reproduce

1. Create a custom class that inherits from `Application`:

```csharp
// CustomStartup.cs
using System.Windows;

namespace ReproApp
{
public class CustomStartup : Application
{
}
}
```

2. Create `App.xaml` using the custom class as root element:

```xaml


```

3. Create code-behind:

```csharp
// App.xaml.cs
namespace ReproApp
{
public partial class App : CustomStartup
{
}
}
```

4. Build the project - **Builds successfully without errors**
5. Run the application - **Runtime error occurs**

## Expected Behavior
The application should start successfully, with the XAML compiler generating the correct resource URI matching the actual file name: `/ReproApp;component/App.xaml`

## Actual Behavior
Runtime error occurs:

```
System.IO.IOException: Cannot locate resource 'app.xaml'.
at MS.Internal.AppModel.ResourcePart.GetStreamCore(FileMode mode, FileAccess access)
at System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at ReproApp.App.InitializeComponent() in App.xaml:line 1
```

The generated code in `obj/.../App.g.cs` contains a **lowercase URI**:

```csharp
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/ReproApp;component/app.xaml", System.UriKind.Relative);
// ^^^^^^^^
// lowercase - should be App.xaml!

System.Windows.Application.LoadComponent(this, resourceLocater);
}
```

## Key Observations

1. **No `App.baml` file is generated** in the obj folder during build
- Other XAML files (like `MainWindow.xaml`) are correctly compiled to `.baml`
- This suggests the ApplicationDefinition is not being processed correctly

2. When using `` as the root element (standard approach), everything works correctly

3. The issue only occurs when using a custom `Application`-derived class as the root element

4. The XAML compiler appears to not recognize the custom Application class as a valid ApplicationDefinition

5. The lowercase URI in the generated code doesn't match the actual file name, which could cause issues on case-sensitive file systems

## Workaround
Remove `App.xaml` entirely and manually create the entry point:

```csharp
public partial class App : CustomStartup
{
[STAThread]
public static void Main()
{
var app = new App();
app.Run();
}
}
```

## Root Cause Analysis
The XAML compiler (`MarkupCompilePass1` task) seems to have issues when:
- The root element of `App.xaml` is not ``
- A custom class derived from `Application` is used instead

This results in:
1. The `App.baml` resource not being generated
2. An incorrect lowercase resource URI being generated
3. A mismatch between the expected and actual resource location at runtime

## Proposed Fix
The XAML compiler should either:
1. **Properly support custom Application-derived classes as root elements** in ApplicationDefinition files, OR
2. **Provide a clear compile-time error** indicating that only `` is supported as the root element in App.xaml

## Additional Context
This issue was discovered while working with a framework that uses a custom `Startup` class derived from `Application` to provide additional initialization logic. The workaround of removing `App.xaml` works but is not intuitive and requires manual Main() method creation.

Related WPF build targets: `Microsoft.WinFX.targets` (MarkupCompilePass1 task)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.