Mobile .NET MAUI
Purpose
Guide for building cross-platform mobile apps with .NET MAUI using MVVM, Shell navigation, and platform-specific customization.
Agent Protocol
Trigger
Phrases: ".NET MAUI", "MAUI app", "Xamarin", "MAUI Shell", "MAUI page", "MAUI MVVM", "MAUI data binding", "MAUI collection view"
Input Context
- Target platforms (Android, iOS, Windows, macOS)
- Pages and navigation structure
- Data models and service interfaces
- Required platform-specific features
Output Artifact
MAUI solution with: AppShell, Pages with ViewModels, Services, Platform-specific code in Platforms/ folder, CommunityToolkit.Mvvm integration.
Response Format
No preamble. No postamble. No explanations. No filler/hedging/transitions. Compress output — why use many token when few do trick.
Completion Criteria
- AppShell navigation works on all targets
- MVVM bindings resolve without code-behind
- CollectionView renders with DataTemplate
- Platform-specific code compiles under correct target
- App deploys and runs on iOS simulator and Android emulator
Max Response Length
8000 tokens
Architecture Decision Trees
Shell vs NavigationPage
App navigation structure?
├── Tab bar + flyout menu → Shell (FlyoutItem, TabBar, Tab)
│ Pros: Built-in navigation bar, flyout, tabs, search, back behavior
├── Simple stack navigation → NavigationPage
│ Push/pop modal stack, simpler API
└── Tabbed app without flyout → TabbedPage
Simpler than Shell, but less flexible
MVVM Framework
Team preference?
├── CommunityToolkit.Mvvm → Source generators, [ObservableProperty], [RelayCommand]
│ Pros: Minimal boilerplate, compile-time binding validation
├── Prism.Maui → Full MVVM framework, navigation service, DI integration
│ Pros: Navigation service, regions, platform service abstraction
└── Manual INotifyPropertyChanged → Lightweight, no dependency
Cons: More code, no source generators
Platform-Specific Code Strategy
Volume of platform code?
├── Small (1-5 specialized views) → #if ANDROID / #if IOS preprocessor
├── Medium → Platform handlers in MauiProgram.cs ConfigureMauiHandlers
│ Preferred approach — maps cross-platform properties to native views
└── Large → Conditional compilation with partial class files per platform
Use Platforms/Android/, Platforms/iOS/ folders for large blocks
Workflow
MAUI project architecture — .NET MAUI uses a single-project structure targeting Android, iOS, Windows, and macOS from one codebase. Solution layout: App.xaml (global styles, resource dictionaries, theme definitions), AppShell.xaml (navigation container with flyout/tabs), Pages/ (XAML views with code-behind minimal), ViewModels/ (business logic with CommunityToolkit.Mvvm), Models/ (data entities, DTOs), Services/ (interfaces + implementations registered in DI), Resources/ (colors, fonts, images, styles), Platforms/ (Android with MainActivity/MainApplication/AndroidManifest, iOS with AppDelegate/Info.plist, Windows, Mac). MauiProgram.cs configures the app builder, registers services, and sets up handlers.
Shell navigation — Shell provides flyout (hamburger menu) and TabBar (bottom tabs) navigation containers. Define structure in AppShell.xaml: FlyoutItem for menu items, TabBar for bottom navigation, ShellContent for pages. Register detail routes with Routing.RegisterRoute("route/name", typeof(Page)) in AppShell constructor. Navigate via Shell.Current.GoToAsync("route/name?param=value"). Receive parameters with [QueryProperty(nameof(Param), "param")] attribute or IQueryAttributable interface. Handle navigation events via Shell.Current.Navigated event. Shell provides built-in back button behavior, search handlers, and flyout customization (header template, icon, content templates).
MVVM with CommunityToolkit.Mvvm — ViewModel base class ObservableObject from CommunityToolkit.Mvvm. Source generators [ObservableProperty] (auto-generates INotifyPropertyChanged), [RelayCommand] (auto-generates IRelayCommand from method), [NotifyPropertyChangedFor] (notify dependent property on change). Data binding in XAML via {Binding Property} expressions. x:DataType for compile-time binding validation. Converters for value transformations (IValueConverter). ViewModel registered as transient in DI — new instance per navigation. Constructor injection for services. Messenger pattern (WeakReferenceMessenger) for cross-ViewModel communication.
XAML and data binding — XAML markup extensions: {Binding}, {StaticResource}, {DynamicResource}, {TemplateBinding}, {RelativeSource}. Compiled bindings enabled with x:DataType on page/control level — compile-time errors for invalid paths. x:Array and x:Static for static resources. Data templates for item rendering. Control templates for custom control structure. Styles in ResourceDictionary with BasedOn, TargetType, Setter. Triggers: DataTrigger, MultiTrigger, EventTrigger for state-based styling. VisualStateManager for view states (Normal, Disabled, Focused, Selected).
MAUI controls — CollectionView (replaces ListView): vertical/horizontal grids, grouping via IsGrouped, EmptyView for no-data state, pull-to-refresh with RefreshView wrapper. CarouselView for swipeable cards with PeekAreaInsets and Loop properties. Border replaces Frame for rounded corners. FlexLayout for wrapping layouts. GraphicsView for custom 2D drawing. BlazorWebView for hybrid Blazor + MAUI apps. Handlers architecture replaces the old Custom Renderers system — each control has a mapper that maps cross-platform properties to native views.
Platform-specific code — Three approaches: (a) Platforms/ folder with conditional compilation — code files in Platforms/Android/, Platforms/iOS/, etc. are compiled only for the target platform. (b) #if ANDROID, #if IOS, #if WINDOWS, #if MACCATALYST preprocessor directives for inline platform branching. (c) Platform handlers in MauiProgram.cs via ConfigureMauiHandlers() — customize native controls (e.g., remove Entry underline on Android, set border style on iOS). Map native events to MAUI events. Handler customization is the preferred approach over conditional compilation.
Deployment and hot reload — dotnet build -t:Run -f net8.0-android builds and deploys to Android emulator. XAML Hot Reload applies XAML changes instantly during debugging on emulator/simulator (not real-time on physical device). Code signing: Android via .csproj properties (AndroidSigningKeyStore, AndroidSigningKeyAlias), iOS via provisioning profile in Info.plist. CI/CD: Azure DevOps or GitHub Actions with dotnet publish and platform-specific build steps. App Center retired — migrate to GitHub Actions or self-hosted. Test Cloud via Xamarin.UITest or Appium.
Platform Compatibility
| Feature |
Android |
iOS |
Windows |
macOS |
| Shell navigation |
Full |
Full |
Flyout only |
Flyout only |
| XAML Hot Reload |
Yes |
Yes |
Yes |
Yes |
| CollectionView |
Full |
Full |
Full |
Full |
| Platform handlers |
Yes |
Yes |
Partial |
Partial |
| .NET 8 support |
Yes |
Yes |
Yes |
Yes |
Best Practices
- Use compiled bindings (
x:DataType) on every page — catches binding errors at compile time
- Register all services and ViewModels in
MauiProgram.cs — no service locator pattern
- Keep code-behind to DI constructor + InitializeComponent calls only
- Prefer
Border over Frame — Frame is deprecated for rendering performance
- Use
CommunityToolkit.Maui for behaviors, converters, animations, and popups
- Version
Platforms/ code with #if blocks — never duplicate entire files per platform
Common Pitfalls
- Missing linker configuration: .NET MAUI linker strips unused assemblies. Add
Preserve attribute or linker config XML for dynamically accessed types.
- CollectionView inside ScrollView: Causes ambiguous scroll direction exception. Use
CollectionView alone or set NestedScrollEnabled=false.
- iOS simulator keyboard: Hardware keyboard on simulator doesn't trigger
Completed event. Test keyboard on real device.
- Android WebView mixed content:
usesCleartextTraffic="true" in AndroidManifest for HTTP resources in WebView.
- XAML Hot Reload limitations: Doesn't work for constructor changes, new page creation, or C# changes — only XAML property edits.
Anti-Patterns
- Code-behind with business logic: Keep to DI constructor + InitializeComponent
- Singleton ViewModels: ViewModels should be transient — new instance per navigation
- Messaging abuse: WeakReferenceMessenger for cross-ViewModel, not for general pub-sub
- Direct static navigation calls: Use Shell routing — never instantiate pages directly
- Platform API calls without #if guard: Platform-specific APIs crash on unsupported targets
- Ignoring linker configuration: Linker strips dynamically accessed types — preserve them explicitly
Performance Optimization
Startup Performance
MAUI app startup involves: native initialization, XAML parsing, Shell construction, and first-page rendering. Profile with: dotnet-trace (event tracing), Xamarin Profiler (legacy), or custom stopwatch logging. Key optimizations:
- AOT compilation: Enable
<PublishAot>true</PublishAot> in .csproj for iOS/Android (reduces JIT overhead at startup, but increases binary size ~30%). For .NET 8+ MAUI, AOT is available for iOS via --aot.
- Trim assemblies:
<TrimMode>full</TrimMode> with linker configuration. Reduces app size but requires [DynamicallyAccessedMembers] attributes on types accessed via reflection.
- Lazy initialization: Defer non-critical services:
Lazy<IService> or Task.Run(() => InitializeHeavyService()) after first frame render. Register heavy services as transient or use Lazy<T> wrapper.
- Shell caching: Shell caches pages by default — pages remain in memory after navigation. Use
Shell.Current.CachingStrategy = CachingStrategy.RetainElement judiciously. Prefer CachingStrategy.RecycleElement for memory-bound scenarios.
- Startup tracing: Measure with
Activity or DiagnosticListener between Application.OnStart() and first frame Appearing event. Target: <2s cold start on mid-range Android/iOS devices.
Memory Management
- CollectionView recycling: Virtualization recycles cell templates — ensure views are data-bound, not created in
ItemTemplate code-behind. Avoid DataTemplate with complex nested layouts.
- Image caching: Use
FFImageLoading (community) or MAUI CommunityToolkit's CachedImage. Set CacheType to Disk for large images. Avoid ImageSource.FromStream on UI thread.
- Weak event patterns: Event subscriptions (PropertyChanged, CollectionChanged) prevent GC of pages. Use
WeakEventManager or WeakReference for subscribers.
- Dispose pattern: Implement
IDisposable on ViewModels that hold subscriptions. Call Dispose() in page OnDisappearing or via Lifecycle events. Unsubscribe from MessagingCenter/WeakReferenceMessenger in ViewModel cleanup.
- Large collection handling: For 1000+ items, use
CollectionView with RemainingItemsThreshold + RemainingItemsThresholdReachedCommand for incremental loading (infinite scroll). Never load all items into memory at once.
UI Thread and Responsiveness
- Async all the way: All I/O-bound operations (HTTP, database, file system) must use
async/await. Never call .Result or .Wait() on Task — this deadlocks on MAUI's main thread.
MainThread.BeginInvokeOnMainThread: Only use for UI updates from background threads. Batch UI updates — don't invoke per-item in a loop.
- Layout passes: Minimize layout pass count. Use
HorizontalStackLayout/VerticalStackLayout over StackLayout (lighter). Avoid AbsoluteLayout for dynamic layouts (measuring pass is expensive). Prefer Grid with proportional rows/columns.
- XAML compilation: Enable
XAMLC (XAML compilation) in all Release configs: add [XamlCompilation(XamlCompilationOptions.Compile)] on all Pages. Reduces runtime XAML parsing time.
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
- Data binding performance: Prefer compiled bindings (
x:DataType) over reflection-based bindings. Compiled bindings reduce reflection overhead and catch errors at compile time. For list items, ensure x:DataType on DataTemplate is set to the item type.
<CollectionView ItemsSource="{Binding Orders}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:Order">
<Label Text="{Binding CustomerName}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Graphics and Animation
- GPU-accelerated properties: Animate
Opacity, Rotation, Scale, TranslationX/TranslationY (GPU-composited). Avoid animating Width, Height, Margin, Padding (trigger layout passes).
GraphicsView over custom drawing: MAUI's GraphicsView uses Microsoft.Maui.Graphics for 2D drawing — hardware-accelerated on most platforms. Use for custom charts, signatures, diagrams.
- Reduce shadow/blur: Shadows (
Shadow effect) and blurs trigger off-screen rendering. Use sparingly in lists. Prefer flat design for list items, reserve shadows for modals/popups.
Build & Deployment Patterns
Project Configuration (.csproj)
<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<OutputType>Exe</OutputType>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- Release optimizations -->
<PublishTrimmed>true</PublishTrimmed>
<PublishAot>false</PublishAot>
<TrimMode>partial</TrimMode>
<Optimize>true</Optimize>
</PropertyGroup>
<!-- Android-specific -->
<PropertyGroup Condition="$(TargetFramework.Contains('android'))">
<ApplicationId>com.company.app</ApplicationId>
<ApplicationVersion>1</ApplicationVersion>
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<AndroidSigningKeyStore>$(ProjectDir)release.keystore</AndroidSigningKeyStore>
<AndroidSigningKeyAlias>app-alias</AndroidSigningKeyAlias>
<AndroidSigningKeyPass>$(KS_PASS)</AndroidSigningKeyPass>
<AndroidSigningStorePass>$(KSP_PASS)</AndroidSigningStorePass>
<AndroidPackageFormat>aab</AndroidPackageFormat>
</PropertyGroup>
<!-- iOS-specific -->
<PropertyGroup Condition="$(TargetFramework.Contains('ios'))">
<ApplicationId>com.company.app</ApplicationId>
<BuildIpa>true</BuildIpa>
<RuntimeIdentifier>ios-arm64</RuntimeIdentifier>
<CodesignKey>Apple Distribution: Company Name</CodesignKey>
<CodesignProvision>$(APPLE_PROVISIONING_PROFILE)</CodesignProvision>
<ArchiveOnBuild>true</ArchiveOnBuild>
</PropertyGroup>
CI/CD Pipeline (GitHub Actions)
name: Build and Deploy MAUI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-android:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Restore
run: dotnet restore
- name: Build Android
run: |
dotnet build -f net8.0-android --configuration Release `
-p:AndroidSigningKeyStore=release.keystore `
-p:AndroidSigningKeyAlias=app-alias `
-p:AndroidSigningKeyPass=${{ secrets.KEY_PASS }} `
-p:AndroidSigningStorePass=${{ secrets.STORE_PASS }}
- name: Sign AAB
run: |
java -jar bundletool-all.jar build-bundle --modules=bin/Release/net8.0-android/*.aab
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: android-release
path: '**/*.aab'
build-ios:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Install iOS provisioning
run: |
echo ${{ secrets.IOS_CERT }} | base64 --decode > cert.p12
echo ${{ secrets.IOS_PROVISIONING }} | base64 --decode > provisioning.mobileprovision
security create-keychain -p temp temp.keychain
security import cert.p12 -k temp.keychain -P ${{ secrets.CERT_PASS }}
- name: Build iOS
run: |
dotnet build -f net8.0-ios --configuration Release `
-p:RuntimeIdentifier=ios-arm64 `
-p:CodesignKey="Apple Distribution: Company" `
-p:CodesignProvision="$(ls provisioning.mobileprovision)"
- name: Upload IPA
uses: actions/upload-artifact@v4
with:
name: ios-release
path: '**/*.ipa'
App Store & Play Store Submission
Google Play: Build AAB with dotnet publish -f net8.0-android -c Release. Sign with Android keystore (jarsigner or MSBuild properties). Upload to Google Play Console → Internal Testing → Closed Alpha → Open Beta → Production. Use bundletool for AAB testing: java -jar bundletool.jar install-apks --apks=app.aab.
Apple App Store: Build IPA with dotnet publish -f net8.0-ios -c Release. Requires Apple Developer Program membership ($99/year). Distribution via App Store Connect: Xcode Organizer → Distribute App → App Store Connect. Or use Transporter app for IPA upload. TestFlight for beta distribution before production release.
App Center (retired): Migrate to GitHub Actions + App Center Distribute (still available for distribution). Alternative: Firebase App Distribution for Android beta testing, TestFlight for iOS.
Versioning Strategy
ApplicationVersion (Android): integer, auto-increment per release.
CFBundleVersion (iOS): same integer, matches Android version code.
ApplicationDisplayVersion / CFBundleShortVersionString: semver string ("1.2.3").
- Sync via CI: read from
version.txt or Git tag, inject into .csproj properties via script or Directory.Build.props.
Platform-Specific Code Examples
Android — Custom Handler (Remove Entry Underline)
// MauiProgram.cs
builder.ConfigureMauiHandlers(handlers => {
handlers.AddHandler<Entry, EntryHandler>(nameof(Entry), (handler) => {
#if ANDROID
handler.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(
Android.Graphics.Color.Transparent);
#endif
});
});
iOS — Safe Area Handling
// iOS — respect safe area in custom views
#if IOS
using UIKit;
using CoreGraphics;
public class SafeAreaAwareView : UIView
{
public override void LayoutSubviews()
{
base.LayoutSubviews();
var insets = Window?.SafeAreaInsets ?? UIEdgeInsets.Zero;
// Adjust layout based on safe area
}
}
#endif
Windows — Title Bar Customization
#if WINDOWS
using Microsoft.UI.Xaml;
using Microsoft.UI;
public static class WindowTitleBar
{
public static void SetTheme(Window window, bool darkMode)
{
var nativeWindow = window.Handler?.PlatformView as Microsoft.UI.Xaml.Window;
if (nativeWindow != null)
{
nativeWindow.ExtendsContentIntoTitleBar = true;
// Custom title bar colors
}
}
}
#endif
Shared Service with Platform DI
// Interface in shared code
public interface IDeviceInfo
{
string GetDeviceName();
string GetOSVersion();
}
// Android implementation (Platforms/Android/)
public class AndroidDeviceInfo : IDeviceInfo
{
public string GetDeviceName() =>
Android.OS.Build.Model ?? "Unknown";
public string GetOSVersion() =>
Android.OS.Build.VERSION.Release ?? "Unknown";
}
// iOS implementation (Platforms/iOS/)
public class IosDeviceInfo : IDeviceInfo
{
public string GetDeviceName() =>
UIKit.UIDevice.CurrentDevice.Name;
public string GetOSVersion() =>
UIKit.UIDevice.CurrentDevice.SystemVersion;
}
// Registration in MauiProgram.cs
#if ANDROID
builder.Services.AddSingleton<IDeviceInfo, AndroidDeviceInfo>();
#elif IOS
builder.Services.AddSingleton<IDeviceInfo, IosDeviceInfo>();
#endif
Anti-Patterns (Expanded)
- Static service locator:
Application.Current.MainPage or DependencyService.Get<T>() creates hidden dependencies. Use constructor DI only.
- Massive MauiProgram.cs: Registering every service and handler inline in MauiProgram.cs creates an unmaintainable file. Use extension methods:
builder.Services.AddOrderModule(), builder.ConfigurePaymentHandlers().
- Direct ObservableCollection manipulation: Adding/removing items on background thread crashes. Use
MainThread.BeginInvokeOnMainThread(() => collection.Add(item)).
- Overusing Effects: Effects are procedural and harder to override. Use Handlers for MAUI-native customization, Effects only for pre-MAUI migration code.
- Ignoring linker configuration: Linker strips unused IL. Types accessed via reflection (Sqlite, serialization) must be preserved. Use
[Preserve] attribute or linker XML configuration.
- Missing
#if on platform APIs: Android.Graphics.Color in shared code compiles on all targets but throws on iOS. Always guard platform-specific types with #if ANDROID, #if IOS.
- Nested layouts in ListView: ListView/CollectionView with complex nested layouts (Grid in StackLayout in Frame) kills scroll performance. Flatten hierarchy for list items.
- No
x:DataType on DataTemplate: Reflection-based bindings in lists are 3-5x slower than compiled bindings. Always set x:DataType on ItemTemplate DataTemplate.
- Storing secrets in code: API keys, connection strings in source code. Use Azure Key Vault, GitHub Secrets, or
Secrets.json (user secrets in development). Never commit secrets.
- Over-engineering with Prism: Prism adds significant complexity for most apps. CommunityToolkit.Mvvm covers 90% of MVVM needs with less overhead.
Configuration Reference
<!-- .csproj — Android signing -->
<PropertyGroup Condition="$(TargetFramework.Contains('android'))">
<AndroidSigningKeyStore>release.keystore</AndroidSigningKeyStore>
<AndroidSigningKeyAlias>app-alias</AndroidSigningKeyAlias>
</PropertyGroup>
<!-- .csproj — iOS version -->
<PropertyGroup Condition="$(TargetFramework.Contains('ios'))">
<CFBundleVersion>1.0.0</CFBundleVersion>
<CFBundleShortVersionString>1.0</CFBundleShortVersionString>
</PropertyGroup>
References
- references/dotnet-maui-advanced.md — Dotnet Maui Advanced Topics
- references/dotnet-maui-fundamentals.md — Dotnet Maui Fundamentals
- references/maui-architecture.md — MAUI Architecture
- references/maui-controls.md — MAUI Controls
- references/maui-mvvm.md — MAUI MVVM with CommunityToolkit
- references/maui-structure.md — MAUI Project Structure
Handoff
Hand off to iOS/Android native skills when platform handler customization requires deep UIKit or Android Views API knowledge.
Implementation Patterns
Observer Pattern for Event Handling
`
interface EventObserver {
onEvent(event: T): Promise;
}
class EventBus {
private observers: Set<EventObserver> = new Set();
subscribe(observer: EventObserver): void {
this.observers.add(observer);
}
unsubscribe(observer: EventObserver): void {
this.observers.delete(observer);
}
async emit(event: T): Promise {
const results = Array.from(this.observers).map(o => o.onEvent(event));
await Promise.allSettled(results);
}
}
`
Configuration-Driven Approach
config: defaults: timeout: 30s retryCount: 3 overrides: production: timeout: 60s retryCount: 5 development: timeout: 300s retryCount: 1
Production Considerations
Deployment Checklist
Monitoring and Alerting
| Metric |
Threshold |
Severity |
Action |
| Error rate |
> 1% over 5min |
Critical |
Page on-call |
| p99 latency |
> 2s over 5min |
Warning |
Investigate |
| Throughput drop |
> 50% over 1min |
Critical |
Check upstream |
| Queue depth |
> 1000 over 1min |
Warning |
Scale consumers |
| Disk usage |
> 85% |
Warning |
Clean or expand |
| Memory usage |
> 90% heap |
Critical |
Restart or scale |
Anti-Patterns
| Anti-Pattern |
Symptom |
Root Cause |
Solution |
| Premature optimization |
Complex code for no measured benefit |
Guessing instead of profiling |
Measure first, optimize based on data |
| Copy-paste reuse |
Duplicate code across codebase |
Lack of abstraction |
Extract shared logic into libraries |
| Gold-plating |
Features with no current requirement |
Over-engineering |
YAGNI — build what's needed now |
| Magical thinking |
Assumptions without validation |
Skipping error handling |
Handle all failure modes explicitly |
Performance Optimization
Caching Strategy
Cache hierarchy: L1 (in-memory local) → L2 (distributed Redis/Memcached) → L3 (CDN/Edge).
Cache invalidation: TTL-based (simple, stale), event-based (complex, fresh), write-through (consistent, higher write latency), write-behind (fast writes, eventual consistency).
Resource Pooling
- Database connections: Pool of reusable connections (HikariCP, pgBouncer)
- HTTP connections: Keep-alive + connection pooling for external calls
- Thread pool: Bounded thread pools for async task execution
Profiling Methodology
- Establish baseline with production traffic profile
- Profile CPU with sampling profiler (pprof, perf, async-profiler)
- Profile memory with heap dumps and allocation tracking
- Profile I/O with strace/perf trace for syscall analysis
- Profile latency with distributed tracing (OpenTelemetry)
- Identify bottleneck, formulate hypothesis, implement fix
- Re-profile to verify improvement, repeat
Security Considerations
Threat Modeling (STRIDE)
- Spoofing: Identity validation, authentication
- Tampering: Integrity checks, digital signatures
- Repudiation: Audit logs, non-repudiation
- Information disclosure: Encryption, access control
- Denial of service: Rate limiting, resource quotas
- Elevation of privilege: Principle of least privilege
Supply Chain Security
- Dependency scanning: Snyk, Dependabot, Trivy
- SBOM generation: CycloneDX or SPDX format
- Signed commits: GPG or SSH commit signing
- Artifact verification: Checksum validation, signature verification
Secrets Management
- Secrets never in code — always in secrets manager (Vault, AWS Secrets Manager)
- Rotation policy: Rotate database credentials every 90 days
- Access audit: Log every secrets access, alert on anomalies
- Encryption at rest and in transit for all secrets
- Principle of least privilege: each service gets only its own secrets
Rules
- Default-deny security posture — allow only explicitly required access.
- All inputs validated, all outputs encoded, all errors handled.
- Defend in depth — multiple layers of security controls.
- Fail securely — errors default to safe behavior.
- Log security-relevant events for audit and investigation.
- Keep dependencies updated — automate vulnerability scanning.
- Design for observability from day one, not as an afterthought.
- Document all architectural decisions with rationale.
- Review code for security, performance, and correctness before merging.
1---2name: mobile-dotnet-maui3description: Use this skill when the user says '.NET MAUI', 'MAUI app', 'Xamarin', 'MAUI', 'MAUI page', 'MAUI Shell', 'MAUI MVVM', 'MAUI data binding', 'MAUI collection view'. Build cross-platform mobile apps with .NET MAUI including Shell navigation, MVVM, controls, and deployment. Do NOT use for: ASP.NET Core or Blazor development.4license: MIT5---67# Mobile .NET MAUI89## Purpose10Guide for building cross-platform mobile apps with .NET MAUI using MVVM, Shell navigation, and platform-specific customization.1112## Agent Protocol1314### Trigger15Phrases: ".NET MAUI", "MAUI app", "Xamarin", "MAUI Shell", "MAUI page", "MAUI MVVM", "MAUI data binding", "MAUI collection view"1617### Input Context18- Target platforms (Android, iOS, Windows, macOS)19- Pages and navigation structure20- Data models and service interfaces21- Required platform-specific features2223### Output Artifact24MAUI solution with: AppShell, Pages with ViewModels, Services, Platform-specific code in Platforms/ folder, CommunityToolkit.Mvvm integration.2526### Response Format27No preamble. No postamble. No explanations. No filler/hedging/transitions. Compress output — why use many token when few do trick.2829### Completion Criteria30- AppShell navigation works on all targets31- MVVM bindings resolve without code-behind32- CollectionView renders with DataTemplate33- Platform-specific code compiles under correct target34- App deploys and runs on iOS simulator and Android emulator3536### Max Response Length378000 tokens3839## Architecture Decision Trees4041### Shell vs NavigationPage42```43App navigation structure?44├── Tab bar + flyout menu → Shell (FlyoutItem, TabBar, Tab)45│ Pros: Built-in navigation bar, flyout, tabs, search, back behavior46├── Simple stack navigation → NavigationPage47│ Push/pop modal stack, simpler API48└── Tabbed app without flyout → TabbedPage49 Simpler than Shell, but less flexible50```5152### MVVM Framework53```54Team preference?55├── CommunityToolkit.Mvvm → Source generators, [ObservableProperty], [RelayCommand]56│ Pros: Minimal boilerplate, compile-time binding validation57├── Prism.Maui → Full MVVM framework, navigation service, DI integration58│ Pros: Navigation service, regions, platform service abstraction59└── Manual INotifyPropertyChanged → Lightweight, no dependency60 Cons: More code, no source generators61```6263### Platform-Specific Code Strategy64```65Volume of platform code?66├── Small (1-5 specialized views) → #if ANDROID / #if IOS preprocessor67├── Medium → Platform handlers in MauiProgram.cs ConfigureMauiHandlers68│ Preferred approach — maps cross-platform properties to native views69└── Large → Conditional compilation with partial class files per platform70 Use Platforms/Android/, Platforms/iOS/ folders for large blocks71```7273## Workflow74751. **MAUI project architecture** — .NET MAUI uses a single-project structure targeting Android, iOS, Windows, and macOS from one codebase. Solution layout: `App.xaml` (global styles, resource dictionaries, theme definitions), `AppShell.xaml` (navigation container with flyout/tabs), `Pages/` (XAML views with code-behind minimal), `ViewModels/` (business logic with CommunityToolkit.Mvvm), `Models/` (data entities, DTOs), `Services/` (interfaces + implementations registered in DI), `Resources/` (colors, fonts, images, styles), `Platforms/` (Android with MainActivity/MainApplication/AndroidManifest, iOS with AppDelegate/Info.plist, Windows, Mac). `MauiProgram.cs` configures the app builder, registers services, and sets up handlers.76772. **Shell navigation** — Shell provides flyout (hamburger menu) and TabBar (bottom tabs) navigation containers. Define structure in `AppShell.xaml`: `FlyoutItem` for menu items, `TabBar` for bottom navigation, `ShellContent` for pages. Register detail routes with `Routing.RegisterRoute("route/name", typeof(Page))` in AppShell constructor. Navigate via `Shell.Current.GoToAsync("route/name?param=value")`. Receive parameters with `[QueryProperty(nameof(Param), "param")]` attribute or `IQueryAttributable` interface. Handle navigation events via `Shell.Current.Navigated` event. Shell provides built-in back button behavior, search handlers, and flyout customization (header template, icon, content templates).78793. **MVVM with CommunityToolkit.Mvvm** — ViewModel base class `ObservableObject` from CommunityToolkit.Mvvm. Source generators `[ObservableProperty]` (auto-generates INotifyPropertyChanged), `[RelayCommand]` (auto-generates IRelayCommand from method), `[NotifyPropertyChangedFor]` (notify dependent property on change). Data binding in XAML via `{Binding Property}` expressions. `x:DataType` for compile-time binding validation. Converters for value transformations (`IValueConverter`). ViewModel registered as transient in DI — new instance per navigation. Constructor injection for services. Messenger pattern (`WeakReferenceMessenger`) for cross-ViewModel communication.80814. **XAML and data binding** — XAML markup extensions: `{Binding}`, `{StaticResource}`, `{DynamicResource}`, `{TemplateBinding}`, `{RelativeSource}`. Compiled bindings enabled with `x:DataType` on page/control level — compile-time errors for invalid paths. `x:Array` and `x:Static` for static resources. Data templates for item rendering. Control templates for custom control structure. Styles in ResourceDictionary with `BasedOn`, `TargetType`, `Setter`. Triggers: `DataTrigger`, `MultiTrigger`, `EventTrigger` for state-based styling. VisualStateManager for view states (Normal, Disabled, Focused, Selected).82835. **MAUI controls** — `CollectionView` (replaces ListView): vertical/horizontal grids, grouping via `IsGrouped`, `EmptyView` for no-data state, pull-to-refresh with `RefreshView` wrapper. `CarouselView` for swipeable cards with `PeekAreaInsets` and `Loop` properties. `Border` replaces Frame for rounded corners. `FlexLayout` for wrapping layouts. `GraphicsView` for custom 2D drawing. `BlazorWebView` for hybrid Blazor + MAUI apps. Handlers architecture replaces the old Custom Renderers system — each control has a mapper that maps cross-platform properties to native views.84856. **Platform-specific code** — Three approaches: (a) `Platforms/` folder with conditional compilation — code files in `Platforms/Android/`, `Platforms/iOS/`, etc. are compiled only for the target platform. (b) `#if ANDROID`, `#if IOS`, `#if WINDOWS`, `#if MACCATALYST` preprocessor directives for inline platform branching. (c) Platform handlers in `MauiProgram.cs` via `ConfigureMauiHandlers()` — customize native controls (e.g., remove Entry underline on Android, set border style on iOS). Map native events to MAUI events. Handler customization is the preferred approach over conditional compilation.86877. **Deployment and hot reload** — `dotnet build -t:Run -f net8.0-android` builds and deploys to Android emulator. XAML Hot Reload applies XAML changes instantly during debugging on emulator/simulator (not real-time on physical device). Code signing: Android via `.csproj` properties (`AndroidSigningKeyStore`, `AndroidSigningKeyAlias`), iOS via provisioning profile in Info.plist. CI/CD: Azure DevOps or GitHub Actions with `dotnet publish` and platform-specific build steps. App Center retired — migrate to GitHub Actions or self-hosted. Test Cloud via Xamarin.UITest or Appium.8889## Platform Compatibility9091| Feature | Android | iOS | Windows | macOS |92|---------|---------|-----|---------|-------|93| Shell navigation | Full | Full | Flyout only | Flyout only |94| XAML Hot Reload | Yes | Yes | Yes | Yes |95| CollectionView | Full | Full | Full | Full |96| Platform handlers | Yes | Yes | Partial | Partial |97| .NET 8 support | Yes | Yes | Yes | Yes |9899## Best Practices100101- Use compiled bindings (`x:DataType`) on every page — catches binding errors at compile time102- Register all services and ViewModels in `MauiProgram.cs` — no service locator pattern103- Keep code-behind to DI constructor + InitializeComponent calls only104- Prefer `Border` over `Frame` — Frame is deprecated for rendering performance105- Use `CommunityToolkit.Maui` for behaviors, converters, animations, and popups106- Version `Platforms/` code with `#if` blocks — never duplicate entire files per platform107108## Common Pitfalls109110- **Missing linker configuration**: .NET MAUI linker strips unused assemblies. Add `Preserve` attribute or linker config XML for dynamically accessed types.111- **CollectionView inside ScrollView**: Causes ambiguous scroll direction exception. Use `CollectionView` alone or set `NestedScrollEnabled=false`.112- **iOS simulator keyboard**: Hardware keyboard on simulator doesn't trigger `Completed` event. Test keyboard on real device.113- **Android WebView mixed content**: `usesCleartextTraffic="true"` in AndroidManifest for HTTP resources in WebView.114- **XAML Hot Reload limitations**: Doesn't work for constructor changes, new page creation, or C# changes — only XAML property edits.115116## Anti-Patterns117118- **Code-behind with business logic**: Keep to DI constructor + InitializeComponent119- **Singleton ViewModels**: ViewModels should be transient — new instance per navigation120- **Messaging abuse**: WeakReferenceMessenger for cross-ViewModel, not for general pub-sub121- **Direct static navigation calls**: Use Shell routing — never instantiate pages directly122- **Platform API calls without #if guard**: Platform-specific APIs crash on unsupported targets123- **Ignoring linker configuration**: Linker strips dynamically accessed types — preserve them explicitly124125## Performance Optimization126127### Startup Performance128MAUI app startup involves: native initialization, XAML parsing, Shell construction, and first-page rendering. Profile with: `dotnet-trace` (event tracing), Xamarin Profiler (legacy), or custom stopwatch logging. Key optimizations:129130- **AOT compilation**: Enable `<PublishAot>true</PublishAot>` in .csproj for iOS/Android (reduces JIT overhead at startup, but increases binary size ~30%). For .NET 8+ MAUI, AOT is available for iOS via `--aot`.131- **Trim assemblies**: `<TrimMode>full</TrimMode>` with linker configuration. Reduces app size but requires `[DynamicallyAccessedMembers]` attributes on types accessed via reflection.132- **Lazy initialization**: Defer non-critical services: `Lazy<IService>` or `Task.Run(() => InitializeHeavyService())` after first frame render. Register heavy services as transient or use `Lazy<T>` wrapper.133- **Shell caching**: Shell caches pages by default — pages remain in memory after navigation. Use `Shell.Current.CachingStrategy = CachingStrategy.RetainElement` judiciously. Prefer `CachingStrategy.RecycleElement` for memory-bound scenarios.134- **Startup tracing**: Measure with `Activity` or `DiagnosticListener` between `Application.OnStart()` and first frame `Appearing` event. Target: <2s cold start on mid-range Android/iOS devices.135136### Memory Management137- **CollectionView recycling**: Virtualization recycles cell templates — ensure views are data-bound, not created in `ItemTemplate` code-behind. Avoid `DataTemplate` with complex nested layouts.138- **Image caching**: Use `FFImageLoading` (community) or `MAUI CommunityToolkit`'s `CachedImage`. Set `CacheType` to `Disk` for large images. Avoid `ImageSource.FromStream` on UI thread.139- **Weak event patterns**: Event subscriptions (PropertyChanged, CollectionChanged) prevent GC of pages. Use `WeakEventManager` or `WeakReference` for subscribers.140- **Dispose pattern**: Implement `IDisposable` on ViewModels that hold subscriptions. Call `Dispose()` in page `OnDisappearing` or via `Lifecycle` events. Unsubscribe from `MessagingCenter`/`WeakReferenceMessenger` in ViewModel cleanup.141- **Large collection handling**: For 1000+ items, use `CollectionView` with `RemainingItemsThreshold` + `RemainingItemsThresholdReachedCommand` for incremental loading (infinite scroll). Never load all items into memory at once.142143### UI Thread and Responsiveness144- **Async all the way**: All I/O-bound operations (HTTP, database, file system) must use `async`/`await`. Never call `.Result` or `.Wait()` on Task — this deadlocks on MAUI's main thread.145- **`MainThread.BeginInvokeOnMainThread`**: Only use for UI updates from background threads. Batch UI updates — don't invoke per-item in a loop.146- **Layout passes**: Minimize layout pass count. Use `HorizontalStackLayout`/`VerticalStackLayout` over `StackLayout` (lighter). Avoid `AbsoluteLayout` for dynamic layouts (measuring pass is expensive). Prefer `Grid` with proportional rows/columns.147- **XAML compilation**: Enable `XAMLC` (XAML compilation) in all Release configs: add `[XamlCompilation(XamlCompilationOptions.Compile)]` on all Pages. Reduces runtime XAML parsing time.148149```csharp150[assembly: XamlCompilation(XamlCompilationOptions.Compile)]151```152153- **Data binding performance**: Prefer compiled bindings (`x:DataType`) over reflection-based bindings. Compiled bindings reduce reflection overhead and catch errors at compile time. For list items, ensure `x:DataType` on `DataTemplate` is set to the item type.154155```xml156<CollectionView ItemsSource="{Binding Orders}">157 <CollectionView.ItemTemplate>158 <DataTemplate x:DataType="models:Order">159 <Label Text="{Binding CustomerName}" />160 </DataTemplate>161 </CollectionView.ItemTemplate>162</CollectionView>163```164165### Graphics and Animation166- **GPU-accelerated properties**: Animate `Opacity`, `Rotation`, `Scale`, `TranslationX`/`TranslationY` (GPU-composited). Avoid animating `Width`, `Height`, `Margin`, `Padding` (trigger layout passes).167- **`GraphicsView` over custom drawing**: MAUI's `GraphicsView` uses `Microsoft.Maui.Graphics` for 2D drawing — hardware-accelerated on most platforms. Use for custom charts, signatures, diagrams.168- **Reduce shadow/blur**: Shadows (`Shadow` effect) and blurs trigger off-screen rendering. Use sparingly in lists. Prefer flat design for list items, reserve shadows for modals/popups.169170## Build & Deployment Patterns171172### Project Configuration (.csproj)173```xml174<PropertyGroup>175 <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>176 <OutputType>Exe</OutputType>177 <UseMaui>true</UseMaui>178 <SingleProject>true</SingleProject>179 <ImplicitUsings>enable</ImplicitUsings>180 <Nullable>enable</Nullable>181 <!-- Release optimizations -->182 <PublishTrimmed>true</PublishTrimmed>183 <PublishAot>false</PublishAot>184 <TrimMode>partial</TrimMode>185 <Optimize>true</Optimize>186</PropertyGroup>187188<!-- Android-specific -->189<PropertyGroup Condition="$(TargetFramework.Contains('android'))">190 <ApplicationId>com.company.app</ApplicationId>191 <ApplicationVersion>1</ApplicationVersion>192 <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>193 <AndroidSigningKeyStore>$(ProjectDir)release.keystore</AndroidSigningKeyStore>194 <AndroidSigningKeyAlias>app-alias</AndroidSigningKeyAlias>195 <AndroidSigningKeyPass>$(KS_PASS)</AndroidSigningKeyPass>196 <AndroidSigningStorePass>$(KSP_PASS)</AndroidSigningStorePass>197 <AndroidPackageFormat>aab</AndroidPackageFormat>198</PropertyGroup>199200<!-- iOS-specific -->201<PropertyGroup Condition="$(TargetFramework.Contains('ios'))">202 <ApplicationId>com.company.app</ApplicationId>203 <BuildIpa>true</BuildIpa>204 <RuntimeIdentifier>ios-arm64</RuntimeIdentifier>205 <CodesignKey>Apple Distribution: Company Name</CodesignKey>206 <CodesignProvision>$(APPLE_PROVISIONING_PROFILE)</CodesignProvision>207 <ArchiveOnBuild>true</ArchiveOnBuild>208</PropertyGroup>209```210211### CI/CD Pipeline (GitHub Actions)212```yaml213name: Build and Deploy MAUI214215on:216 push:217 branches: [main]218 pull_request:219 branches: [main]220221jobs:222 build-android:223 runs-on: windows-latest224 steps:225 - uses: actions/checkout@v4226 - name: Setup .NET227 uses: actions/setup-dotnet@v4228 with:229 dotnet-version: '8.0.x'230 - name: Restore231 run: dotnet restore232 - name: Build Android233 run: |234 dotnet build -f net8.0-android --configuration Release `235 -p:AndroidSigningKeyStore=release.keystore `236 -p:AndroidSigningKeyAlias=app-alias `237 -p:AndroidSigningKeyPass=${{ secrets.KEY_PASS }} `238 -p:AndroidSigningStorePass=${{ secrets.STORE_PASS }}239 - name: Sign AAB240 run: |241 java -jar bundletool-all.jar build-bundle --modules=bin/Release/net8.0-android/*.aab242 - name: Upload Artifact243 uses: actions/upload-artifact@v4244 with:245 name: android-release246 path: '**/*.aab'247248 build-ios:249 runs-on: macos-latest250 steps:251 - uses: actions/checkout@v4252 - name: Setup .NET253 uses: actions/setup-dotnet@v4254 with:255 dotnet-version: '8.0.x'256 - name: Install iOS provisioning257 run: |258 echo ${{ secrets.IOS_CERT }} | base64 --decode > cert.p12259 echo ${{ secrets.IOS_PROVISIONING }} | base64 --decode > provisioning.mobileprovision260 security create-keychain -p temp temp.keychain261 security import cert.p12 -k temp.keychain -P ${{ secrets.CERT_PASS }}262 - name: Build iOS263 run: |264 dotnet build -f net8.0-ios --configuration Release `265 -p:RuntimeIdentifier=ios-arm64 `266 -p:CodesignKey="Apple Distribution: Company" `267 -p:CodesignProvision="$(ls provisioning.mobileprovision)"268 - name: Upload IPA269 uses: actions/upload-artifact@v4270 with:271 name: ios-release272 path: '**/*.ipa'273```274275### App Store & Play Store Submission276277**Google Play**: Build AAB with `dotnet publish -f net8.0-android -c Release`. Sign with Android keystore (`jarsigner` or MSBuild properties). Upload to Google Play Console → Internal Testing → Closed Alpha → Open Beta → Production. Use `bundletool` for AAB testing: `java -jar bundletool.jar install-apks --apks=app.aab`.278279**Apple App Store**: Build IPA with `dotnet publish -f net8.0-ios -c Release`. Requires Apple Developer Program membership ($99/year). Distribution via App Store Connect: Xcode Organizer → Distribute App → App Store Connect. Or use `Transporter` app for IPA upload. TestFlight for beta distribution before production release.280281**App Center** (retired): Migrate to GitHub Actions + App Center Distribute (still available for distribution). Alternative: Firebase App Distribution for Android beta testing, TestFlight for iOS.282283### Versioning Strategy284- `ApplicationVersion` (Android): integer, auto-increment per release.285- `CFBundleVersion` (iOS): same integer, matches Android version code.286- `ApplicationDisplayVersion` / `CFBundleShortVersionString`: semver string ("1.2.3").287- Sync via CI: read from `version.txt` or Git tag, inject into .csproj properties via script or `Directory.Build.props`.288289## Platform-Specific Code Examples290291### Android — Custom Handler (Remove Entry Underline)292```csharp293// MauiProgram.cs294builder.ConfigureMauiHandlers(handlers => {295 handlers.AddHandler<Entry, EntryHandler>(nameof(Entry), (handler) => {296#if ANDROID297 handler.PlatformView.BackgroundTintList = Android.Content.Res.ColorStateList.ValueOf(298 Android.Graphics.Color.Transparent);299#endif300 });301});302```303304### iOS — Safe Area Handling305```csharp306// iOS — respect safe area in custom views307#if IOS308using UIKit;309using CoreGraphics;310311public class SafeAreaAwareView : UIView312{313 public override void LayoutSubviews()314 {315 base.LayoutSubviews();316 var insets = Window?.SafeAreaInsets ?? UIEdgeInsets.Zero;317 // Adjust layout based on safe area318 }319}320#endif321```322323### Windows — Title Bar Customization324```csharp325#if WINDOWS326using Microsoft.UI.Xaml;327using Microsoft.UI;328329public static class WindowTitleBar330{331 public static void SetTheme(Window window, bool darkMode)332 {333 var nativeWindow = window.Handler?.PlatformView as Microsoft.UI.Xaml.Window;334 if (nativeWindow != null)335 {336 nativeWindow.ExtendsContentIntoTitleBar = true;337 // Custom title bar colors338 }339 }340}341#endif342```343344### Shared Service with Platform DI345```csharp346// Interface in shared code347public interface IDeviceInfo348{349 string GetDeviceName();350 string GetOSVersion();351}352353// Android implementation (Platforms/Android/)354public class AndroidDeviceInfo : IDeviceInfo355{356 public string GetDeviceName() =>357 Android.OS.Build.Model ?? "Unknown";358 public string GetOSVersion() =>359 Android.OS.Build.VERSION.Release ?? "Unknown";360}361362// iOS implementation (Platforms/iOS/)363public class IosDeviceInfo : IDeviceInfo364{365 public string GetDeviceName() =>366 UIKit.UIDevice.CurrentDevice.Name;367 public string GetOSVersion() =>368 UIKit.UIDevice.CurrentDevice.SystemVersion;369}370371// Registration in MauiProgram.cs372#if ANDROID373builder.Services.AddSingleton<IDeviceInfo, AndroidDeviceInfo>();374#elif IOS375builder.Services.AddSingleton<IDeviceInfo, IosDeviceInfo>();376#endif377```378379## Anti-Patterns (Expanded)380381- **Static service locator**: `Application.Current.MainPage` or `DependencyService.Get<T>()` creates hidden dependencies. Use constructor DI only.382- **Massive MauiProgram.cs**: Registering every service and handler inline in MauiProgram.cs creates an unmaintainable file. Use extension methods: `builder.Services.AddOrderModule()`, `builder.ConfigurePaymentHandlers()`.383- **Direct ObservableCollection manipulation**: Adding/removing items on background thread crashes. Use `MainThread.BeginInvokeOnMainThread(() => collection.Add(item))`.384- **Overusing Effects**: Effects are procedural and harder to override. Use Handlers for MAUI-native customization, Effects only for pre-MAUI migration code.385- **Ignoring linker configuration**: Linker strips unused IL. Types accessed via reflection (Sqlite, serialization) must be preserved. Use `[Preserve]` attribute or linker XML configuration.386- **Missing `#if` on platform APIs**: `Android.Graphics.Color` in shared code compiles on all targets but throws on iOS. Always guard platform-specific types with `#if ANDROID`, `#if IOS`.387- **Nested layouts in ListView**: ListView/CollectionView with complex nested layouts (Grid in StackLayout in Frame) kills scroll performance. Flatten hierarchy for list items.388- **No `x:DataType` on DataTemplate**: Reflection-based bindings in lists are 3-5x slower than compiled bindings. Always set `x:DataType` on ItemTemplate DataTemplate.389- **Storing secrets in code**: API keys, connection strings in source code. Use Azure Key Vault, GitHub Secrets, or `Secrets.json` (user secrets in development). Never commit secrets.390- **Over-engineering with Prism**: Prism adds significant complexity for most apps. CommunityToolkit.Mvvm covers 90% of MVVM needs with less overhead.391392## Configuration Reference393394```xml395<!-- .csproj — Android signing -->396<PropertyGroup Condition="$(TargetFramework.Contains('android'))">397 <AndroidSigningKeyStore>release.keystore</AndroidSigningKeyStore>398 <AndroidSigningKeyAlias>app-alias</AndroidSigningKeyAlias>399</PropertyGroup>400401<!-- .csproj — iOS version -->402<PropertyGroup Condition="$(TargetFramework.Contains('ios'))">403 <CFBundleVersion>1.0.0</CFBundleVersion>404 <CFBundleShortVersionString>1.0</CFBundleShortVersionString>405</PropertyGroup>406```407408## References409 - references/dotnet-maui-advanced.md — Dotnet Maui Advanced Topics410 - references/dotnet-maui-fundamentals.md — Dotnet Maui Fundamentals411 - references/maui-architecture.md — MAUI Architecture412 - references/maui-controls.md — MAUI Controls413 - references/maui-mvvm.md — MAUI MVVM with CommunityToolkit414 - references/maui-structure.md — MAUI Project Structure415## Handoff416Hand off to iOS/Android native skills when platform handler customization requires deep UIKit or Android Views API knowledge.417## Implementation Patterns418419### Observer Pattern for Event Handling420`421interface EventObserver<T> {422 onEvent(event: T): Promise<void>;423}424425class EventBus<T> {426 private observers: Set<EventObserver<T>> = new Set();427 subscribe(observer: EventObserver<T>): void {428 this.observers.add(observer);429 }430 unsubscribe(observer: EventObserver<T>): void {431 this.observers.delete(observer);432 }433 async emit(event: T): Promise<void> {434 const results = Array.from(this.observers).map(o => o.onEvent(event));435 await Promise.allSettled(results);436 }437}438`439440### Configuration-Driven Approach441`442config:443 defaults:444 timeout: 30s445 retryCount: 3446 overrides:447 production:448 timeout: 60s449 retryCount: 5450 development:451 timeout: 300s452 retryCount: 1453`454455## Production Considerations456457### Deployment Checklist458- [ ] Configuration validated against schema before startup459- [ ] Health check endpoints registered and monitored460- [ ] Graceful shutdown with draining period (30s timeout)461- [ ] Resource limits configured (CPU, memory, file descriptors)462- [ ] Log level set appropriate for environment463- [ ] Metrics endpoint secured and exposed464- [ ] Rate limiting configured per-tier465- [ ] TLS certificates valid and auto-renewing466- [ ] Database migrations run as separate deployment step467- [ ] Feature flags ready for gradual rollout468469### Monitoring and Alerting470| Metric | Threshold | Severity | Action |471|--------|-----------|----------|--------|472| Error rate | > 1% over 5min | Critical | Page on-call |473| p99 latency | > 2s over 5min | Warning | Investigate |474| Throughput drop | > 50% over 1min | Critical | Check upstream |475| Queue depth | > 1000 over 1min | Warning | Scale consumers |476| Disk usage | > 85% | Warning | Clean or expand |477| Memory usage | > 90% heap | Critical | Restart or scale |478479## Anti-Patterns480481| Anti-Pattern | Symptom | Root Cause | Solution |482|-------------|---------|------------|----------|483| Premature optimization | Complex code for no measured benefit | Guessing instead of profiling | Measure first, optimize based on data |484| Copy-paste reuse | Duplicate code across codebase | Lack of abstraction | Extract shared logic into libraries |485| Gold-plating | Features with no current requirement | Over-engineering | YAGNI — build what's needed now |486| Magical thinking | Assumptions without validation | Skipping error handling | Handle all failure modes explicitly |487488## Performance Optimization489490### Caching Strategy491Cache hierarchy: L1 (in-memory local) → L2 (distributed Redis/Memcached) → L3 (CDN/Edge).492Cache invalidation: TTL-based (simple, stale), event-based (complex, fresh), write-through (consistent, higher write latency), write-behind (fast writes, eventual consistency).493494### Resource Pooling495- Database connections: Pool of reusable connections (HikariCP, pgBouncer)496- HTTP connections: Keep-alive + connection pooling for external calls497- Thread pool: Bounded thread pools for async task execution498499### Profiling Methodology5001. Establish baseline with production traffic profile5012. Profile CPU with sampling profiler (pprof, perf, async-profiler)5023. Profile memory with heap dumps and allocation tracking5034. Profile I/O with strace/perf trace for syscall analysis5045. Profile latency with distributed tracing (OpenTelemetry)5056. Identify bottleneck, formulate hypothesis, implement fix5067. Re-profile to verify improvement, repeat507508## Security Considerations509510### Threat Modeling (STRIDE)511- Spoofing: Identity validation, authentication512- Tampering: Integrity checks, digital signatures513- Repudiation: Audit logs, non-repudiation514- Information disclosure: Encryption, access control515- Denial of service: Rate limiting, resource quotas516- Elevation of privilege: Principle of least privilege517518### Supply Chain Security519- Dependency scanning: Snyk, Dependabot, Trivy520- SBOM generation: CycloneDX or SPDX format521- Signed commits: GPG or SSH commit signing522- Artifact verification: Checksum validation, signature verification523524### Secrets Management525- Secrets never in code — always in secrets manager (Vault, AWS Secrets Manager)526- Rotation policy: Rotate database credentials every 90 days527- Access audit: Log every secrets access, alert on anomalies528- Encryption at rest and in transit for all secrets529- Principle of least privilege: each service gets only its own secrets530531## Rules532- Default-deny security posture — allow only explicitly required access.533- All inputs validated, all outputs encoded, all errors handled.534- Defend in depth — multiple layers of security controls.535- Fail securely — errors default to safe behavior.536- Log security-relevant events for audit and investigation.537- Keep dependencies updated — automate vulnerability scanning.538- Design for observability from day one, not as an afterthought.539- Document all architectural decisions with rationale.540- Review code for security, performance, and correctness before merging.