Skip to content

Commit 61f85f5

Browse files
committed
Add type-safe query string utilities and samples
Introduces QueryStringBuilder, RouterStateExtensions, and RouterNavigationExtensions for fluent, type-safe query string manipulation and parsing. Updates documentation and sample components to demonstrate new query string features, including typed parameter parsing, advanced navigation, and comprehensive usage examples.
1 parent 250b9c3 commit 61f85f5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2939
-325
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ ClientBin/
167167
*.pfx
168168
*.publishsettings
169169
node_modules/
170+
bun.lock
170171

171172
# RIA/Silverlight projects
172173
Generated_Code/

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.0.11] - 2025-11-24
11+
12+
### Added
13+
- **Query String Helpers and Utilities**: Comprehensive type-safe query string manipulation
14+
- `QueryStringBuilder` class with fluent API for building query strings
15+
- 15 type-safe `Add()` method overloads supporting string, int, long, decimal, double, bool, DateTime, Guid, enum, and nullable variants
16+
- 15 type-safe `Set()` method overloads for replacing values (prevents duplicates)
17+
- `RouterStateExtensions` with typed query parameter parsing methods: `GetQueryInt()`, `GetQueryBool()`, `GetQueryDateTime()`, etc.
18+
- `GetAllQueryParams()` method to retrieve all query parameters as a dictionary
19+
- `RouterNavigationExtensions` for enhanced navigation with query strings
20+
- `NavigateToWithQuery()` for fluent query string building during navigation
21+
- `NavigateToWithUpdatedQuery()` for updating specific parameters while preserving others
22+
- `NavigateToWithRemovedQuery()` and `NavigateToWithClearedQuery()` for parameter removal
23+
- `NavigateToWithSingleQuery()` convenience methods for single parameter navigation
24+
- Automatic URL encoding via `Uri.EscapeDataString`
25+
- Safe parsing with `TryParse` and default value support
26+
- Comprehensive XML documentation with usage examples
27+
28+
### Changed
29+
- Updated README.md with Query String Utilities documentation and usage examples
30+
- Enhanced UserList sample component to display all query parameters using `GetAllQueryParams()`
31+
- Updated project structure documentation to reflect new Utilities directory
32+
1033
## [1.0.10] - 2025-11-19
1134

1235
### Added
@@ -151,6 +174,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
151174
- FEATURES.md detailing all capabilities
152175
- Sample application demonstrating key features
153176

177+
[1.0.11]: https://github.com/Taiizor/Blazouter/compare/v1.0.10...v1.0.11
154178
[1.0.10]: https://github.com/Taiizor/Blazouter/compare/v1.0.9...v1.0.10
155179
[1.0.9]: https://github.com/Taiizor/Blazouter/compare/v1.0.5...v1.0.9
156180
[1.0.6-1.0.8]: https://github.com/Taiizor/Blazouter/compare/v1.0.5...v1.0.9

FEATURES.md

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,31 @@ Blazouter is a comprehensive routing library for Blazor applications, available
108108
- Custom error handler registration via `AddBlazouterErrorHandler<T>()`
109109
- Error types: `ComponentLoadFailed`, `GuardRejected`, `NavigationFailed`, `InvalidRoute`
110110

111+
### ✅ 11. Query String Helpers and Utilities
112+
- Tested and verified working
113+
- Type-safe query string manipulation with fluent API
114+
- `QueryStringBuilder` class for building query strings
115+
- Automatic URL encoding via `Uri.EscapeDataString`
116+
- Safe parsing with `TryParse` and default value support
117+
- Comprehensive XML documentation with code examples
118+
- `RouterStateExtensions` for typed query parameter parsing
119+
- `HasQuery()` to check parameter existence
120+
- `GetAllQueryParams()` to retrieve all parameters as dictionary
121+
- Nullable variants: `GetQueryIntOrNull()`, `GetQueryBoolOrNull()`, etc.
122+
- `GetQueryBool()` supporting "true", "false", "1", "0", "yes", "no", "on", "off"
123+
- `GetQueryDateTime()`, `GetQueryGuid()`, `GetQueryEnum<T>()` for complex types
124+
- `GetQueryInt()`, `GetQueryLong()`, `GetQueryDecimal()`, `GetQueryDouble()` with default values
125+
- 15 `Set()` method overloads for replacing values without duplicates
126+
- `RouterNavigationExtensions` for enhanced navigation with query strings
127+
- `NavigateToWithQuery()` - Fluent query builder integration
128+
- `NavigateToWithClearedQuery()` - Clear all query parameters
129+
- `NavigateToWithRemovedQuery()` - Remove specific parameters
130+
- `NavigateToWithReplacedQuery()` - Replace all query parameters
131+
- `NavigateToWithSingleQuery()` - Convenience for single parameter
132+
- `NavigateToWithUpdatedQuery()` - Update specific parameters, preserve others
133+
- Sample application demonstrates all features in Navigation.razor and UserList.razor
134+
- 15 `Add()` method overloads for all common types (string, int, long, decimal, double, bool, DateTime, Guid, enum, and nullable variants)
135+
111136
## Components
112137

113138
### Router
@@ -175,6 +200,46 @@ Nested route renderer that:
175200
- Error handling interface for custom implementations
176201
- Registered as scoped service via AddBlazouterErrorHandler<T>()
177202

203+
## Utilities
204+
205+
### QueryStringBuilder
206+
- Fluent API for building query strings
207+
- Support for nullable variants of all types
208+
- `AddIf()` for conditional parameter addition
209+
- `AddRange()` for multiple values per parameter
210+
- `Build()` returns query string without `?` prefix
211+
- `Remove()` and `Clear()` for parameter removal
212+
- 15 type-safe `Set()` methods for replacing values
213+
- Automatic URL encoding with Uri.EscapeDataString
214+
- 15 type-safe `Add()` methods for appending values
215+
- `BuildWithPrefix()` returns query string with `?` prefix
216+
- `ToDictionary()` converts to Dictionary<string, string>
217+
- Support for string, int, long, decimal, double, bool, DateTime, Guid, enum types
218+
219+
## Extension Methods
220+
221+
### RouterStateExtensions
222+
- `HasQuery()` - Check if parameter exists
223+
- `GetQueryBoolOrNull()` - Parse nullable boolean
224+
- All methods use InvariantCulture for consistent parsing
225+
- `GetAllQueryParams()` - Get all parameters as dictionary
226+
- `GetQueryArray()` - Get multiple values for same parameter
227+
- `GetQueryGuid()`, `GetQueryGuidOrNull()` - Parse Guid parameters
228+
- `GetQueryEnum<T>()`, `GetQueryEnumOrNull<T>()` - Parse enum parameters
229+
- `GetQueryDateTime()`, `GetQueryDateTimeOrNull()` - Parse DateTime in ISO 8601 format
230+
- `GetQueryBool()` - Parse boolean with support for "true", "false", "1", "0", "yes", "no", "on", "off"
231+
- `GetQueryInt()`, `GetQueryLong()`, `GetQueryDecimal()`, `GetQueryDouble()` - Parse numeric parameters with defaults
232+
- `GetQueryIntOrNull()`, `GetQueryLongOrNull()`, `GetQueryDecimalOrNull()`, `GetQueryDoubleOrNull()` - Parse nullable numeric parameters
233+
234+
### RouterNavigationExtensions
235+
- `NavigateToWithQuery()` - Navigate with fluent query builder
236+
- `NavigateToWithClearedQuery()` - Clear all query parameters
237+
- `NavigateToWithReplacedQuery()` - Replace all query parameters
238+
- `NavigateToWithRemovedQuery()` - Remove specific parameters by key
239+
- `NavigateToWithSingleQuery()` - Convenience method for single string parameter
240+
- `NavigateToWithSingleQuery<T>()` - Convenience method for single typed parameter
241+
- `NavigateToWithUpdatedQuery()` - Update specific parameters while preserving others
242+
178243
## Configuration
179244

180245
### RouteConfig Properties
@@ -200,12 +265,15 @@ Nested route renderer that:
200265
- Layout system support (DefaultLayout, per-route Layout)
201266
- CSS animations included (blazouter.css, blazouter.min.css)
202267
- All routing components (Router, RouterLink, RouterOutlet)
268+
- Fluent query string building with automatic URL encoding
203269
- Multi-framework support (net6.0, net7.0, net8.0, net9.0, net10.0)
270+
- Type-safe query parameter parsing with 15+ extension methods
204271
- Navigation services (RouterNavigationService, RouterStateService)
205272
- Route guards interface (IRouteGuard, AuthGuard base implementation)
206273
- Route configuration and matching (RouteConfig, RouteMatcherService)
207274
- Attribute-based routing (RouteAttributeDiscoveryService, 8 route attributes)
208275
- Error handling (IRouterErrorHandler, DefaultRouterErrorHandler, RouterErrorContext)
276+
- Query string utilities (QueryStringBuilder, RouterStateExtensions, RouterNavigationExtensions)
209277

210278
### Blazouter.Server
211279
- Server-side route optimization
@@ -234,6 +302,11 @@ The sample application demonstrates:
234302
3. About page with library information
235303
4. Lazy loaded page with component loader
236304
5. Users page with nested routing (list and detail views)
305+
6. Navigation page with comprehensive query string utilities showcase
306+
- Type-safe query parameter parsing examples
307+
- Traditional vs fluent query string building comparison
308+
- Query parameter manipulation (update, remove, clear)
309+
- Interactive buttons demonstrating all query string features
237310

238311
All features are interactive and can be tested by navigating through the application.
239312

@@ -250,4 +323,5 @@ All features are interactive and can be tested by navigating through the applica
250323
| Nested Routes | ❌ Limited | ✅ Unlimited nesting depth |
251324
| Attribute Routes |@page only | ✅ 8 attribute types with full config |
252325
| Parameter Access | ✅ Basic | ✅ Enhanced with RouterStateService |
253-
| Programmatic Nav | ✅ Basic | ✅ Enhanced with RouterNavigationService |
326+
| Programmatic Nav | ✅ Basic | ✅ Enhanced with RouterNavigationService |
327+
| Query String Helpers | ❌ Manual parsing | ✅ Type-safe fluent API with 15+ methods |

README.md

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Blazouter addresses the limitations of traditional Blazor routing:
4545
- **📐 Layout System**: Flexible layout management with default and per-route layouts
4646
- **🔗 Programmatic Navigation**: Navigate imperatively with enhanced navigation service
4747
- **⚠️ Error Handling**: Comprehensive error handling with custom error handlers and retry mechanisms
48+
- **🔧 Query String Utilities**: Type-safe query string builder and typed parameter parsing with fluent API
4849
- **🎨 Route Transitions**: Beautiful animations when navigating between routes with 14 built-in transition types
4950

5051
## 📦 Available Packages
@@ -544,6 +545,65 @@ new RouteConfig
544545
}
545546
```
546547

548+
### Query String Utilities
549+
550+
Blazouter provides comprehensive query string helpers for type-safe parameter handling:
551+
552+
**Type-safe query parameter parsing:**
553+
554+
```razor
555+
@using Blazouter.Extensions
556+
@inject RouterStateService RouterState
557+
558+
@code {
559+
protected override void OnInitialized()
560+
{
561+
// Typed parsing with defaults
562+
int page = RouterState.GetQueryInt("page", 1);
563+
bool active = RouterState.GetQueryBool("active", false);
564+
DateTime? date = RouterState.GetQueryDateTimeOrNull("date");
565+
566+
// Get all query parameters
567+
var allParams = RouterState.GetAllQueryParams();
568+
}
569+
}
570+
```
571+
572+
**Fluent query string building:**
573+
574+
```csharp
575+
@using Blazouter.Utilities
576+
@inject RouterNavigationService NavService
577+
578+
@code {
579+
private void NavigateWithQuery()
580+
{
581+
// Build query strings with type safety
582+
NavService.NavigateToWithQuery("/search", q => q
583+
.Add("term", "blazor")
584+
.Add("active", true)
585+
.Add("page", 2));
586+
}
587+
}
588+
```
589+
590+
**Update query parameters:**
591+
592+
```csharp
593+
// Replace specific parameters while keeping others
594+
NavService.NavigateToWithUpdatedQuery(RouterState, null, q => q
595+
.Set("page", currentPage + 1)
596+
.Set("sort", "name"));
597+
598+
// Remove parameters
599+
NavService.NavigateToWithRemovedQuery(RouterState, "filter", "sort");
600+
601+
// Clear all parameters
602+
NavService.NavigateToWithClearedQuery(RouterState);
603+
```
604+
605+
The `QueryStringBuilder` supports 15 type overloads including: string, int, long, decimal, double, bool, DateTime, Guid, enum, and their nullable variants.
606+
547607
## 🎨 Route Transitions
548608

549609
Blazouter includes 14 built-in transitions for beautiful page navigation:
@@ -621,10 +681,10 @@ builder.Services.AddBlazouterErrorHandler<CustomRouterErrorHandler>();
621681

622682
### Error Types
623683

624-
- `ComponentLoadFailed` - Component failed to load
684+
- `InvalidRoute` - Invalid route configuration
625685
- `GuardRejected` - Route guard denied access
626686
- `NavigationFailed` - Navigation operation failed
627-
- `InvalidRoute` - Invalid route configuration
687+
- `ComponentLoadFailed` - Component failed to load
628688

629689
## 🏗️ Project Structure
630690

@@ -635,11 +695,12 @@ Blazouter/
635695
│ │ ├── Attributes/ # Route attribute definitions
636696
│ │ ├── Components/ # Router components (Router, RouterLink, RouterOutlet)
637697
│ │ │ └── Layouts/ # Built-in layout components
638-
│ │ ├── Extensions/ # Service collection extensions
698+
│ │ ├── Extensions/ # Service collection and router extensions (typed query parameters, navigation)
639699
│ │ ├── Guards/ # Route guard interfaces
640700
│ │ ├── Models/ # Route models (RouteConfig, RouteMatch, RouteTransition)
641701
│ │ ├── Resources/ # Embedded resources
642702
│ │ ├── Services/ # Routing services (RouterStateService, RouteMatcherService, etc.)
703+
│ │ ├── Utilities/ # Query string builder and helper utilities
643704
│ │ └── wwwroot/ # CSS and assets (blazouter.css, blazouter.min.css)
644705
│ ├── Blazouter.Server/ # Server-specific extensions
645706
│ │ ├── Extensions/ # Server integration (AddBlazouterSupport)
@@ -733,7 +794,7 @@ Inspired by React Router and built to bring similar capabilities to the Blazor e
733794
- [ ] Route middleware support
734795
- [ ] Performance optimizations
735796
- [ ] Advanced caching strategies
736-
- [ ] Query string helpers and utilities
797+
- [x] Query string helpers and utilities
737798
- [ ] Better TypeScript integration for JS interop
738799

739800
## ⭐ Show Your Support

samples/Blazouter.Hybrid.Sample/Blazouter.Hybrid.Sample.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
</ItemGroup>
7171

7272
<ItemGroup>
73+
<None Include="bun.lock" Visible="false" />
7374
<None Include="package.json" Visible="false" />
7475
<None Include="Tailwind.txt" Visible="false" />
7576
<None Include="postcss.config.mjs" Visible="false" />

0 commit comments

Comments
 (0)