-
-
Notifications
You must be signed in to change notification settings - Fork 115
feat: Navigation will set parameters #1584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
c0bfe13 to
97cff02
Compare
c3daea1 to
b2137f1
Compare
|
Just some paper-trail for our future selfs:
Assumption here is that we don't need the
While properly all of that (at least three reflection invocations plus some more setup to create * The CC: @egil |
640d486 to
46f5dfb
Compare
46f5dfb to
6abd715
Compare
|
@egil I rebased all the work on |
6abd715 to
46e7ef6
Compare
|
Okay done :D - now the implementation is using our renderers That was a shortcoming that was easy to overcome with In any case many points are up to discussion. So we are not bored next Friday. |
46e7ef6 to
6ee39df
Compare
c0317cc to
f73a3bd
Compare
f73a3bd to
5f8cb25
Compare
|
@egil I updated the branch. I am still very convinced that this approach is better than reflection-based (across 3 to 4 different objects). A different perspective for |
Ok, could there be something we can ask the Blazor team to change in the code to enable us to do this better. They seem open to suggestions :) |
Good point - I think making the objects in question pub-ternal (how they already have many types and EF does a lot o things). EDIT: Alternatively, an easy wrapper that takes an url, a component and spits out a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements a feature that allows bUnit's NavigationManager to automatically set component parameters based on route templates during navigation, addressing issue #1580.
Key changes:
- Added router functionality that parses route templates and maps URL segments to component parameters
- Integrated the router with the existing NavigationManager to trigger parameter updates on navigation
- Added comprehensive test coverage for various routing scenarios
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| ComponentRouteParameterService.cs | Core service that handles route template parsing and parameter mapping |
| BunitNavigationManager.cs | Updated to integrate with the new route parameter service |
| BunitContext.cs | Added tracking of rendered components for parameter updates |
| RouterTests.cs | Comprehensive test suite covering various routing scenarios |
| RouterTests.Components.cs | Test components with different route configurations |
| passing-parameters-to-components.md | Documentation for the new routing parameter feature |
| CHANGELOG.md | Added feature description to changelog |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| public ComponentFactoryCollection ComponentFactories { get; } = new(); | ||
|
|
||
| /// <summary> | ||
| /// Gets the components that has been rendered by this <see cref="BunitContext"/>. |
Copilot
AI
Sep 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The TODO comment should be replaced with proper documentation describing the purpose and usage of the ReturnedRenderedComponents property.
| /// Gets the components that has been rendered by this <see cref="BunitContext"/>. | |
| /// Gets the set of rendered components that have been returned by this test context. | |
| /// This is used internally to track components created during testing, enabling proper disposal and management. |
| if (templateSegments.Length > uriSegments.Length) | ||
| { | ||
| return []; | ||
| } |
Copilot
AI
Sep 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic doesn't handle optional parameters correctly. A template with optional parameters could be longer than the URI but still be a valid match. Consider checking if the extra template segments are optional before returning an empty dictionary.
| private static object GetValue(string value, PropertyInfo property) | ||
| { | ||
| var underlyingType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; | ||
| return Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); | ||
| } |
Copilot
AI
Sep 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Convert.ChangeType call can throw exceptions for invalid conversions. This method should handle conversion failures gracefully, especially for user-provided URL segments that might not be valid for the target type.
| private static object GetValue(string value, PropertyInfo property) | |
| { | |
| var underlyingType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; | |
| return Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); | |
| } | |
| private static object? GetValue(string value, PropertyInfo property) | |
| { | |
| var underlyingType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; | |
| try | |
| { | |
| return Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); | |
| } | |
| catch (FormatException) | |
| { | |
| return GetDefaultValue(underlyingType); | |
| } | |
| catch (InvalidCastException) | |
| { | |
| return GetDefaultValue(underlyingType); | |
| } | |
| catch (OverflowException) | |
| { | |
| return GetDefaultValue(underlyingType); | |
| } | |
| } | |
| private static object? GetDefaultValue(Type type) | |
| { | |
| // Return null for reference types and Nullable<T>, otherwise default(T) | |
| if (!type.IsValueType || Nullable.GetUnderlyingType(type) != null) | |
| return null; | |
| return Activator.CreateInstance(type); | |
| } |
This closes #1580
The basic idea here is to have a router that takes care of everything. There are a few open points. I will mark them here. We can discuss this next Friday, I just had some time to do the feature today and wanted to finish it as much as possible.