BLAZMVVM0005: Navigation Type Safety
Summary
Navigation calls must reference registered ViewModels with proper routes.
Description
This analyzer validates that NavigateTo calls reference ViewModels that are properly registered with [ViewModelDefinition] and have associated routable components. This prevents runtime navigation failures.
Severity
Error - Invalid navigation targets cause runtime errors.
Why This Rule Exists
- Prevents runtime navigation failures
- Ensures ViewModels are properly registered
- Validates route existence at compile time
- Improves type safety in navigation
- Catches broken navigation links early
✅ DO: Correct Usage
// ViewModel with proper registration
[ViewModelDefinition(Lifetime = ServiceLifetime.Transient)]
public class ProductDetailsViewModel : ViewModelBase
{
[ViewParameter]
public int ProductId { get; set; }
}
// Component with route
@page "/products/{ProductId:int}"
@inherits MvvmComponentBase<ProductDetailsViewModel>
// Navigation - Type-safe
public class ProductListViewModel : ViewModelBase
{
private readonly MvvmNavigationManager _navigation;
public ProductListViewModel(MvvmNavigationManager navigation)
{
_navigation = navigation;
}
[RelayCommand]
private void ViewProduct(int productId)
{
// ✅ Correct: Type-safe navigation to registered ViewModel
_navigation.NavigateTo<ProductDetailsViewModel>(
parameters: new { ProductId = productId });
}
}
❌ DON'T: Incorrect Usage
// ❌ Wrong: Navigating to unregistered ViewModel
public class ProductListViewModel : ViewModelBase
{
[RelayCommand]
private void ViewProduct()
{
// Error: UnregisteredViewModel not decorated with [ViewModelDefinition]
_navigation.NavigateTo<UnregisteredViewModel>();
}
}
public class UnregisteredViewModel : ViewModelBase { }
// ❌ Wrong: ViewModel without associated route
[ViewModelDefinition]
public class NoRouteViewModel : ViewModelBase { }
// Missing: No component with @page directive for this ViewModel
// ❌ Wrong: Using string-based navigation (type-unsafe)
[RelayCommand]
private void Navigate()
{
// Avoid: No compile-time validation
_navigationManager.NavigateTo("/some/path");
}
How to Fix
Register the ViewModel
// Before
public class MyViewModel : ViewModelBase { }
_navigation.NavigateTo<MyViewModel>(); // Error
// After
[ViewModelDefinition(Lifetime = ServiceLifetime.Transient)]
public class MyViewModel : ViewModelBase { }
_navigation.NavigateTo<MyViewModel>(); // ✅ Valid
Create Associated Component
// ViewModel
[ViewModelDefinition]
public class MyViewModel : ViewModelBase { }
// Component with route
@page "/mypage"
@inherits MvvmComponentBase<MyViewModel>
<h3>My Page</h3>
Use Type-Safe Navigation
// Before
_navigationManager.NavigateTo("/products/123");
// After
_navigation.NavigateTo<ProductDetailsViewModel>(
parameters: new { ProductId = 123 });
Benefits
Compile-Time Validation
// Catches errors at compile time
_navigation.NavigateTo<InvalidViewModel>(); // Won't compile if not registered
Refactoring Safety
// Renaming ViewModel updates all navigation calls
_navigation.NavigateTo<ProductDetailsViewModel>(); // IDE refactoring works
IntelliSense Support
// Auto-completion shows only valid ViewModels
_navigation.NavigateTo<|> // Lists registered ViewModels
Navigation Patterns
Simple Navigation
[RelayCommand]
private void GoToHome()
{
_navigation.NavigateTo<HomeViewModel>();
}
With Parameters
[RelayCommand]
private void ViewProduct(int id)
{
_navigation.NavigateTo<ProductDetailsViewModel>(
parameters: new { ProductId = id });
}
With Query String
[RelayCommand]
private void Search(string query)
{
_navigation.NavigateTo<SearchViewModel>(
parameters: new { Query = query });
}
Code Fix
This analyzer provides an automatic code fix that adds the [ViewModelDefinition] attribute to the target ViewModel.
Related Analyzers
- BLAZMVVM0002: ViewModelDefinition Attribute
- BLAZMVVM0011: MvvmNavLink Type Safety
- BLAZMVVM0010: Route-ViewModel Mapping