Skip to content

Commit d4f04d2

Browse files
Create a new shared package, Microsoft.AspNet.SpaServices, to hold MapSpaFallbackRoute (and other common infrastructure yet to be added)
1 parent 4a5b9e6 commit d4f04d2

6 files changed

Lines changed: 110 additions & 60 deletions

File tree

Microsoft.AspNet.AngularServices/project.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
},
2727
"dependencies": {
2828
"Microsoft.AspNet.NodeServices": "1.0.0-alpha7",
29-
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-*"
29+
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-*",
30+
"Microsoft.AspNet.SpaServices": "1.0.0-alpha7"
3031
},
3132
"resource": [
3233
"Content/**/*"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/bin/
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.AspNet.Http;
4+
using Microsoft.AspNet.Routing;
5+
6+
namespace Microsoft.AspNet.SpaServices
7+
{
8+
internal class SpaRouteConstraint : IRouteConstraint
9+
{
10+
private readonly string clientRouteTokenName;
11+
12+
public SpaRouteConstraint(string clientRouteTokenName) {
13+
if (string.IsNullOrEmpty(clientRouteTokenName)) {
14+
throw new ArgumentException("Value cannot be null or empty", "clientRouteTokenName");
15+
}
16+
17+
this.clientRouteTokenName = clientRouteTokenName;
18+
}
19+
20+
public bool Match(HttpContext httpContext, IRouter route, string routeKey, IDictionary<string, object> values, RouteDirection routeDirection)
21+
{
22+
var clientRouteValue = (values[this.clientRouteTokenName] as string) ?? string.Empty;
23+
return !HasDotInLastSegment(clientRouteValue);
24+
}
25+
26+
private bool HasDotInLastSegment(string uri)
27+
{
28+
var lastSegmentStartPos = uri.LastIndexOf('/');
29+
return uri.IndexOf('.', lastSegmentStartPos + 1) >= 0;
30+
}
31+
}
32+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Microsoft.AspNet.Routing;
4+
using Microsoft.AspNet.SpaServices;
5+
6+
// Putting in this namespace so it's always available whenever MapRoute is
7+
namespace Microsoft.AspNet.Builder
8+
{
9+
public static class SpaRouteExtensions
10+
{
11+
private const string ClientRouteTokenName = "clientRoute";
12+
13+
public static void MapSpaFallbackRoute(this IRouteBuilder routeBuilder, string name, object defaults, object constraints = null, object dataTokens = null)
14+
{
15+
MapSpaFallbackRoute(routeBuilder, name, /* templatePrefix */ (string)null, defaults, constraints, dataTokens);
16+
}
17+
18+
public static void MapSpaFallbackRoute(this IRouteBuilder routeBuilder, string name, string templatePrefix, object defaults, object constraints = null, object dataTokens = null)
19+
{
20+
var template = CreateRouteTemplate(templatePrefix);
21+
22+
var constraintsDict = ObjectToDictionary(constraints);
23+
constraintsDict.Add(ClientRouteTokenName, new SpaRouteConstraint(ClientRouteTokenName));
24+
25+
routeBuilder.MapRoute(name, template, defaults, constraintsDict, dataTokens);
26+
}
27+
28+
private static string CreateRouteTemplate(string templatePrefix)
29+
{
30+
templatePrefix = templatePrefix ?? string.Empty;
31+
32+
if (templatePrefix.Contains("?")) {
33+
// TODO: Consider supporting this. The {*clientRoute} part should be added immediately before the '?'
34+
throw new ArgumentException("SPA fallback route templates don't support querystrings");
35+
}
36+
37+
if (templatePrefix.Contains("#")) {
38+
throw new ArgumentException("SPA fallback route templates should not include # characters. The hash part of a URI does not get sent to the server.");
39+
}
40+
41+
if (templatePrefix != string.Empty && !templatePrefix.EndsWith("/")) {
42+
templatePrefix += "/";
43+
}
44+
45+
return templatePrefix + $"{{*{ ClientRouteTokenName }}}";
46+
}
47+
48+
private static IDictionary<string, object> ObjectToDictionary(object value)
49+
{
50+
return value as IDictionary<string, object> ?? new RouteValueDictionary(value);
51+
}
52+
}
53+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"version": "1.0.0-alpha7",
3+
"description": "Microsoft.AspNet.SpaServices",
4+
"authors": [
5+
"Microsoft"
6+
],
7+
"tags": [
8+
""
9+
],
10+
"projectUrl": "",
11+
"licenseUrl": "",
12+
"dependencies": {
13+
"Microsoft.AspNet.Routing": "1.0.0-rc1-*"
14+
},
15+
"frameworks": {
16+
"dnx451": {},
17+
"dnxcore50": {
18+
"dependencies": {
19+
}
20+
}
21+
}
22+
}

samples/angular/MusicStore/Startup.cs

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
using Microsoft.AspNet.Authorization;
44
using Microsoft.AspNet.Builder;
55
using Microsoft.AspNet.Hosting;
6-
using Microsoft.AspNet.Http;
76
using Microsoft.AspNet.Identity.EntityFramework;
8-
using Microsoft.AspNet.Routing;
97
using Microsoft.Data.Entity;
108
using Microsoft.Extensions.Configuration;
119
using Microsoft.Extensions.DependencyInjection;
@@ -125,61 +123,4 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
125123
});
126124
}
127125
}
128-
internal static class SpaRouteExtensions {
129-
private const string ClientRouteTokenName = "clientRoute";
130-
131-
public static void MapSpaFallbackRoute(this IRouteBuilder routeBuilder, string name, object defaults, object constraints = null, object dataTokens = null) {
132-
MapSpaFallbackRoute(routeBuilder, name, /* templatePrefix */ (string)null, defaults, constraints, dataTokens);
133-
}
134-
135-
public static void MapSpaFallbackRoute(this IRouteBuilder routeBuilder, string name, string templatePrefix, object defaults, object constraints = null, object dataTokens = null)
136-
{
137-
var template = CreateRouteTemplate(templatePrefix);
138-
139-
var constraintsDict = ObjectToDictionary(constraints);
140-
constraintsDict.Add(ClientRouteTokenName, new SpaRouteConstraint());
141-
142-
routeBuilder.MapRoute(name, template, defaults, constraintsDict, dataTokens);
143-
}
144-
145-
private static string CreateRouteTemplate(string templatePrefix)
146-
{
147-
templatePrefix = templatePrefix ?? string.Empty;
148-
149-
if (templatePrefix.Contains("?")) {
150-
// TODO: Consider supporting this. The {*clientRoute} part should be added immediately before the '?'
151-
throw new ArgumentException("SPA fallback route templates don't support querystrings");
152-
}
153-
154-
if (templatePrefix.Contains("#")) {
155-
throw new ArgumentException("SPA fallback route templates should not include # characters. The hash part of a URI does not get sent to the server.");
156-
}
157-
158-
if (templatePrefix != string.Empty && !templatePrefix.EndsWith("/")) {
159-
templatePrefix += "/";
160-
}
161-
162-
return templatePrefix + $"{{*{ ClientRouteTokenName }}}";
163-
}
164-
165-
private static IDictionary<string, object> ObjectToDictionary(object value)
166-
{
167-
return value as IDictionary<string, object> ?? new RouteValueDictionary(value);
168-
}
169-
170-
private class SpaRouteConstraint : IRouteConstraint
171-
{
172-
public bool Match(HttpContext httpContext, IRouter route, string routeKey, IDictionary<string, object> values, RouteDirection routeDirection)
173-
{
174-
var clientRouteValue = (values[ClientRouteTokenName] as string) ?? string.Empty;
175-
return !HasDotInLastSegment(clientRouteValue);
176-
}
177-
178-
private bool HasDotInLastSegment(string uri)
179-
{
180-
var lastSegmentStartPos = uri.LastIndexOf('/');
181-
return uri.IndexOf('.', lastSegmentStartPos + 1) >= 0;
182-
}
183-
}
184-
}
185126
}

0 commit comments

Comments
 (0)