Telerik Forums
UI for Blazor Forum
1 answer
691 views

Blazor DEEP LINKING Support:  -  seeking suggestions or interest.

I have discovered that Blazor "Deep Linking" is something with not much .NET API support and community code blogs.

ShortComing: 
This solution does not use the LocationChanged Event. Blazors NavigationManager LocationChanged Event is not friendly enough to support deep linking URL's that are not managed under a Blazor "Circuit".  eg an initial request by clicking a browser history/favorite link. 
KeyNote
So far, the findings indicate that the LocationChanged Event will not fire for this type of initial web request with subsequent requests managed in a Blazor "Circuit". It's too late because the first request was not caught by the LocationChanged  Event. 


Obtained GOAL:

Supports detailed "deep linking" to Restore Navigation UI Components and also restore workflow state for a page defined in the URL route. 

This is a Blazor Server implementation to support Blazor "Deep Linking". 
The code base has been refined, good comments and well ordered.; looking production ready. 
Blazor Server was chosen to reduce the security attack surface. The application using this type solution is not ultra high bandwidth so adding a few extra micro-seconds (or even a milli-second) of code runtime is not an issue. 

>>> Before scaling out adding application page-specific content, now seeking alternatives, insight and suggestions (yeah, should have asked sooner) 
               >>> Ideally, I should have created a few block diagrams and code fragments to help visualize. (perhaps support files can be added if further interest.)


Primary Application Components: 
The MainLayout Component supports four primary Blazor Components:
 1) "Module List":    in the upper title area, a TelerikBreadcrumb Component showing a list of "Module Items" to click on.
 2) "Module Item":   a TelerikTreeView Component containing a navigational hierarchical list of TreeItems located along the left side of the page. Each TreeItem contains url route segments to a Blazor Page Component. Each item contains properties for customization.
 3) "NavBreadcrumb":   a TelerikBreadcrumb Component showing the clicked selectedTreeView item, and its parent items.  Located just above the Module Item on the left side MainLayout Component. 
 4) "Page": the Page Component in the selected TreeItem from the selected ModuleItem.   KeyNote: in this solution, a page may be under multiple module list and module items.  Thus the format of the URL route as defined below. 

URL Route Schema: 
The following is the overall Route Template scheme for the website solution: 
     / ModuleListName / ModuleItemName PageName / optionalRouteParam1 / optionalRouteParam2 ? value1=xxx & value2=yyy

In each Page Component, the @Page Directive Is Not used. Instead, @attribute [Route("route template")] is used in all page type components. This allows the use of string constants.  @Page only allows string literals.

Here are two example route templates in one of the Page Components:   (each page may contain multiple routes)
   @attribute [Route($"/{ModuleListName.Tenant}/{ModuleItemName.ClientAdmin}/{PageItem.UserGrid}/{PageAction.Manage}")]
   @attribute [Route($"/{ModuleListName.Tenant}/{ModuleItemName.UserAdmin}/{PageItem.UserGrid}/{PageAction.Search}")]

Naming Constants and Dictionary:
In the above example, four static classes with multiple static string constants are used to define all navigation type lists and items, and the routing/query string values:
  The four static classes are: 
    ModuleList    -   A list of possible Module lists to display in the MainLayout Title Area. (each contains a list of "ModuleItems")
    ModuleItem   -  An item in each of the above Module Lists
    PageItem       -  The actual Page Component Name  (pageitems use "nameof(pagecomponent)" to assign a page item value.
    PageAction   -  Optional route fragments

Key Point: using string constants in a centrally located file subdirectory allows global renaming. And, allows using friendlier names in the source code while using more-so cryptic names in the built public url routes. 
* it does come with a bit of overhead managing names and assigned values but IMO worth the organizational effort; especially after the solution grows with many pages and complex list/item navigation. Maintaining this type information can be handled by even non-coders with app/solution familiarity.

 

App Specific Component Base Class:
A base class that inherits "ComponentBase" is used by all page components instead of ComponentBase. This is where incoming URL requests are handled. This class contains a number of methods and state management that are in common to all pages. 

Route Manager Class:  

There are "ModuleList" and ModuleItem" definition files that are essentially dictionary's to look up a name to .NET Type then activate the type to an instance. 
The "RouteManager" class contains URL Encoding and URL Decoding methods.

Route Manager - URL Encoding:
When a user clicks on a ModuleItem TreeItem selection, the tree item information is passed to a URL Encoding method to build a "deep link". Also, application specific query string parameters are appended. 

Route Manager - URL Decoding:
The incoming request route segments are parsed and mapped to the above blazor components:  ModuleList, ModuleItem, PageItem.
If a route change is detected, then events are fired to notify the MainLayout Component to update the affected component contents.

SessionStateManger Service Class:
Implemented is a comprehensive more-so generic type session manager class. It handles app-specific requirements. 
Retaining login and navigation to all "module's". ie the feature set and supporting pages. 
The solution also contains other supporting code.

>>> Overall, there is a lot going on to manage everything thus creating a working API for all page component content developers to code around as an de-facto standard. 


DEEP LINKING:

Using the above, the blazor solution supports detailed deep linking to fully restore state; restoring the four primary components listed above. Plus, optional route fragments and query string values to further define state for a given page component. 


*** I hope I have described the architecture clearly enough to grasp and visualize the implementation.***

I'd appreciate relevant input to affect the outcome of the implementation. 

Daniel
Top achievements
Rank 1
Iron
 answered on 06 Jun 2022
Top users last month
Mark
Top achievements
Rank 1
Yurii
Top achievements
Rank 1
Leland
Top achievements
Rank 2
Iron
Iron
Iron
Hon
Top achievements
Rank 1
Iron
Deltaohm
Top achievements
Rank 3
Bronze
Iron
Iron
Want to show your ninja superpower to fellow developers?
Want to show your ninja superpower to fellow developers?