MintPlayer.AspNetCore.SpaServices.Routing
10.5.0
See the version list below for details.
dotnet add package MintPlayer.AspNetCore.SpaServices.Routing --version 10.5.0
NuGet\Install-Package MintPlayer.AspNetCore.SpaServices.Routing -Version 10.5.0
<PackageReference Include="MintPlayer.AspNetCore.SpaServices.Routing" Version="10.5.0" />
<PackageVersion Include="MintPlayer.AspNetCore.SpaServices.Routing" Version="10.5.0" />
<PackageReference Include="MintPlayer.AspNetCore.SpaServices.Routing" />
paket add MintPlayer.AspNetCore.SpaServices.Routing --version 10.5.0
#r "nuget: MintPlayer.AspNetCore.SpaServices.Routing, 10.5.0"
#:package MintPlayer.AspNetCore.SpaServices.Routing@10.5.0
#addin nuget:?package=MintPlayer.AspNetCore.SpaServices.Routing&version=10.5.0
#tool nuget:?package=MintPlayer.AspNetCore.SpaServices.Routing&version=10.5.0
MintPlayer.AspNetCore.SpaServices.Routing
This package simplifies SPA prerendering by allowing you to define your SPA routes in ASP.NET Core and determine which route is activated in the SupplyData callback.
Installation
NuGet Package Manager
Install-Package MintPlayer.AspNetCore.SpaServices.Routing
.NET CLI
dotnet add package MintPlayer.AspNetCore.SpaServices.Routing
MSBuild Integration
This package includes MintPlayer.AspNetCore.NodeServices which automatically configures your project with build targets for SPA development.
Properties
| Property | Default | Description |
|---|---|---|
EnableSpaBuilder |
true |
Master switch to disable SPA build automation |
SpaRoot |
ClientApp\ |
Path to your SPA source folder |
BuildServerSideRenderer |
true |
Whether to build the SSR bundle |
Disabling SPA Builder
If your project doesn't have a SPA but references this package:
<PropertyGroup>
<EnableSpaBuilder>false</EnableSpaBuilder>
</PropertyGroup>
Usage
1. Register SPA Routes
Define your SPA routes in ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddSpaRoutes(routes => routes
.Route("", "home")
.Group("person", "person", person_routes => person_routes
.Route("", "list")
.Route("create", "create")
.Route("{id}", "show")
.Route("{id}/edit", "edit")
)
);
}
2. Supply Data Based on Route
Use ISpaRouteService to determine the current route and supply appropriate data:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISpaRouteService spaRouteService)
{
app.UseSpa(spa =>
{
spa.UseSpaPrerendering(options =>
{
options.SupplyData = (context, data) =>
{
var route = spaRouteService.GetCurrentRoute(context);
var personRepository = context.RequestServices.GetRequiredService<IPersonRepository>();
switch (route?.Name)
{
case "person-list":
data["people"] = personRepository.GetPeople();
break;
case "person-show":
case "person-edit":
var id = Convert.ToInt32(route.Parameters["id"]);
data["person"] = personRepository.GetPerson(id);
break;
}
};
});
});
}
3. Use Data in Angular (main.server.ts)
const providers: StaticProvider[] = [
{ provide: APP_BASE_HREF, useValue: params.baseUrl },
{ provide: 'BASE_URL', useValue: params.origin + params.baseUrl },
];
if ('people' in params.data) {
providers.push({ provide: 'PEOPLE', useValue: params.data.people });
}
if ('person' in params.data) {
providers.push({ provide: 'PERSON', useValue: params.data.person });
}
4. Generate URLs Server-Side
Generate SPA URLs from C# code (useful for redirects, sitemaps, etc.):
// Using a dictionary
var parms = new Dictionary<string, object> { ["id"] = 5 };
var url = spaRouteService.GenerateUrl("person-edit", parms);
// Using an anonymous type
var url = spaRouteService.GenerateUrl("person-edit", new { id = 5 });
Parameter values are percent-encoded, and any parameter the route template does not declare is appended as a query-string entry:
var parms = new Dictionary<string, object> { ["id"] = 5, ["tab"] = "a b" };
var url = spaRouteService.GenerateUrl("person-edit", parms);
// "/person/5/edit?tab=a%20b"
GetCurrentRoute decodes the values again, so a value containing /, &, ?, % or a space
survives a generate/parse round-trip unchanged. Do not encode values yourself before passing them
in, or they will be encoded twice.
Route paths are matched literally apart from {placeholders} - a route path is not a regular
expression, so a . matches only a dot.
Related Packages
- MintPlayer.AspNetCore.NodeServices - Node.js integration
- MintPlayer.AspNetCore.SpaServices - Core SPA services
- MintPlayer.AspNetCore.SpaServices.Prerendering - Prerendering support
License
This project is licensed under the Apache 2.0 License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- MintPlayer.AspNetCore.SpaServices.Prerendering (>= 10.6.0)
- MintPlayer.SourceGenerators.Attributes (>= 10.13.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.8.0-preview1 | 93 | 9/5/2026 |
| 10.7.1 | 94 | 9/5/2026 |
| 10.7.0 | 86 | 9/3/2026 |
| 10.5.0 | 126 | 8/27/2026 |
| 10.4.0 | 960 | 2/27/2026 |
| 10.3.0 | 150 | 2/1/2026 |
| 10.2.1 | 151 | 1/19/2026 |
| 10.2.0 | 142 | 1/18/2026 |
| 10.1.0 | 147 | 1/16/2026 |
| 10.0.2 | 143 | 1/12/2026 |
| 10.0.1 | 263 | 12/20/2025 |
| 10.0.0 | 848 | 11/13/2025 |
| 10.0.0-rc.6 | 359 | 11/11/2025 |
| 10.0.0-rc.5 | 268 | 11/11/2025 |
| 10.0.0-rc.4 | 194 | 11/5/2025 |
| 10.0.0-rc.3 | 198 | 11/5/2025 |
| 10.0.0-rc.2 | 190 | 11/5/2025 |
| 10.0.0-rc.1 | 194 | 10/2/2025 |
| 9.1.0 | 1,676 | 11/22/2024 |
| 9.0.0 | 1,374 | 11/13/2024 |
v 10.5.0
BREAKING CHANGES
- GenerateUrl now percent-encodes parameter values, and GetCurrentRoute now decodes them.
A generate/parse round-trip is lossless for values containing '/', '&', '?', '%' or a space.
If you were encoding values yourself before calling GenerateUrl, stop - you will now get
double-encoded output. Likewise stop decoding SpaRoute.Parameters yourself.
A '+' is NOT read as a space when decoding: a space is written as %20, so the round-trip is
symmetric without it, and doing so would corrupt a value that legitimately contains a '+'.
- Route paths are now regex-escaped. Only {placeholders} are patterns; literal text is matched
literally, so a route "a.b" no longer also matches "/axb". Route paths were never documented
as regular expressions, but a route relying on that will now return 404 instead of matching.
- Redirect now sends 301 (Moved Permanently) instead of 302. It set 301 and then let
Response.Redirect overwrite it with 302, so the permanent redirect the API always implied was
never actually sent. Browsers and CDNs cache permanent redirects.
FIXES
- The empty (root) route now parses its query string. Previously "/?a=b" lost its query while
every other route kept it.
- A repeated query key is now last-one-wins instead of throwing ArgumentException. Repeated keys
are legal in a URL.
- The query is now split at the first '?' (RFC 3986 3.4) rather than the last, so a later '?' stays
in the query instead of being captured into a route parameter.
- A null parameter value now encodes to an empty string instead of throwing NullReferenceException.
v 3.1.0
- Moved the route builder to the SpaPrerenderingService