diff --git a/templates/KnockoutSpa/ClientApp/components/app-root/app-root.ts b/templates/KnockoutSpa/ClientApp/components/app-root/app-root.ts
index af9062c..2ca1bfe 100644
--- a/templates/KnockoutSpa/ClientApp/components/app-root/app-root.ts
+++ b/templates/KnockoutSpa/ClientApp/components/app-root/app-root.ts
@@ -12,12 +12,12 @@ const routes: Route[] = [
class AppRootViewModel {
public route: KnockoutObservable
;
- private _router: Router;
+ public router: Router;
- constructor(params: { history: History.History }) {
+ constructor(params: { history: History.History, basename: string }) {
// Activate the client-side router
- this._router = new Router(params.history, routes)
- this.route = this._router.currentRoute;
+ this.router = new Router(params.history, routes, params.basename);
+ this.route = this.router.currentRoute;
// Load and register all the KO components needed to handle the routes
// The optional 'bundle-loader?lazy!' prefix is a Webpack feature that causes the referenced modules
@@ -32,7 +32,7 @@ class AppRootViewModel {
// To support hot module replacement, this method unregisters the router and KO components.
// In production scenarios where hot module replacement is disabled, this would not be invoked.
public dispose() {
- this._router.dispose();
+ this.router.dispose();
// TODO: Need a better API for this
Object.getOwnPropertyNames((ko).components._allRegisteredComponents).forEach(componentName => {
diff --git a/templates/KnockoutSpa/ClientApp/components/fetch-data/fetch-data.ts b/templates/KnockoutSpa/ClientApp/components/fetch-data/fetch-data.ts
index 9576d66..b053890 100644
--- a/templates/KnockoutSpa/ClientApp/components/fetch-data/fetch-data.ts
+++ b/templates/KnockoutSpa/ClientApp/components/fetch-data/fetch-data.ts
@@ -12,7 +12,7 @@ class FetchDataViewModel {
public forecasts = ko.observableArray();
constructor() {
- fetch('/api/SampleData/WeatherForecasts')
+ fetch('api/SampleData/WeatherForecasts')
.then(response => response.json() as Promise)
.then(data => {
this.forecasts(data);
diff --git a/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.html b/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.html
index 0bfd32c..f053cef 100644
--- a/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.html
+++ b/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.html
@@ -13,17 +13,17 @@
-
-
+
Home
-
-
+
Counter
-
-
+
Fetch data
diff --git a/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.ts b/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.ts
index 186c60e..4ea1fdb 100644
--- a/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.ts
+++ b/templates/KnockoutSpa/ClientApp/components/nav-menu/nav-menu.ts
@@ -1,18 +1,20 @@
import * as ko from 'knockout';
-import { Route } from '../../router';
+import { Route, Router } from '../../router';
interface NavMenuParams {
- route: KnockoutObservable;
+ router: Router;
}
class NavMenuViewModel {
+ public router: Router;
public route: KnockoutObservable;
constructor(params: NavMenuParams) {
// This viewmodel doesn't do anything except pass through the 'route' parameter to the view.
// You could remove this viewmodel entirely, and define 'nav-menu' as a template-only component.
// But in most apps, you'll want some viewmodel logic to determine what navigation options appear.
- this.route = params.route;
+ this.router = params.router;
+ this.route = this.router.currentRoute;
}
}
diff --git a/templates/KnockoutSpa/ClientApp/router.ts b/templates/KnockoutSpa/ClientApp/router.ts
index d3ac749..5045487 100644
--- a/templates/KnockoutSpa/ClientApp/router.ts
+++ b/templates/KnockoutSpa/ClientApp/router.ts
@@ -16,7 +16,7 @@ export class Router {
private disposeHistory: () => void;
private clickEventListener: EventListener;
- constructor(history: History.History, routes: Route[]) {
+ constructor(private history: History.History, routes: Route[], basename: string) {
// Reset and configure Crossroads so it matches routes and updates this.currentRoute
crossroads.removeAllRoutes();
crossroads.resetState();
@@ -33,8 +33,9 @@ export class Router {
let target: any = evt.currentTarget;
if (target && target.tagName === 'A') {
let href = target.getAttribute('href');
- if (href && href.charAt(0) == '/') {
- history.push(href);
+ if (href && href.indexOf(basename + '/') === 0) {
+ const hrefAfterBasename = href.substring(basename.length);
+ history.push(hrefAfterBasename);
evt.preventDefault();
}
}
@@ -46,6 +47,10 @@ export class Router {
crossroads.parse((history as any).location.pathname);
}
+ public link(url: string): string {
+ return this.history.createHref({ pathname: url });
+ }
+
public dispose() {
this.disposeHistory();
$(document).off('click', 'a', this.clickEventListener);
diff --git a/templates/KnockoutSpa/Views/Home/Index.cshtml b/templates/KnockoutSpa/Views/Home/Index.cshtml
index 866fb01..0253020 100644
--- a/templates/KnockoutSpa/Views/Home/Index.cshtml
+++ b/templates/KnockoutSpa/Views/Home/Index.cshtml
@@ -2,7 +2,7 @@
ViewData["Title"] = "Home Page";
}
-
+
@section scripts {
diff --git a/templates/KnockoutSpa/npm-shrinkwrap.json b/templates/KnockoutSpa/npm-shrinkwrap.json
index 665c0a7..75ccbab 100644
--- a/templates/KnockoutSpa/npm-shrinkwrap.json
+++ b/templates/KnockoutSpa/npm-shrinkwrap.json
@@ -167,9 +167,9 @@
"dev": true
},
"aspnet-webpack": {
- "version": "1.0.29",
- "from": "aspnet-webpack@>=1.0.27 <2.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
+ "version": "2.0.0",
+ "from": "aspnet-webpack@2.0.0",
+ "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.0.tgz",
"dev": true
},
"assert": {
diff --git a/templates/KnockoutSpa/package.json b/templates/KnockoutSpa/package.json
index c4c42fc..385775a 100644
--- a/templates/KnockoutSpa/package.json
+++ b/templates/KnockoutSpa/package.json
@@ -12,7 +12,7 @@
"@types/react-router": "^2.0.37",
"@types/requirejs": "^2.1.26",
"@types/signals": "0.0.16",
- "aspnet-webpack": "^1.0.27",
+ "aspnet-webpack": "^2.0.0",
"awesome-typescript-loader": "^3.0.0",
"bootstrap": "^3.3.6",
"bundle-loader": "^0.5.4",
diff --git a/templates/KnockoutSpa/webpack.config.js b/templates/KnockoutSpa/webpack.config.js
index 9be0b9e..98a37b6 100644
--- a/templates/KnockoutSpa/webpack.config.js
+++ b/templates/KnockoutSpa/webpack.config.js
@@ -13,7 +13,7 @@ module.exports = (env) => {
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
- publicPath: '/dist/'
+ publicPath: 'dist/'
},
module: {
rules: [
diff --git a/templates/KnockoutSpa/webpack.config.vendor.js b/templates/KnockoutSpa/webpack.config.vendor.js
index f53c6ba..12d4dba 100644
--- a/templates/KnockoutSpa/webpack.config.vendor.js
+++ b/templates/KnockoutSpa/webpack.config.vendor.js
@@ -21,7 +21,7 @@ module.exports = (env) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
- publicPath: '/dist/',
+ publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},
diff --git a/templates/ReactReduxSpa/ClientApp/boot-client.tsx b/templates/ReactReduxSpa/ClientApp/boot-client.tsx
index cd84cc9..188729e 100644
--- a/templates/ReactReduxSpa/ClientApp/boot-client.tsx
+++ b/templates/ReactReduxSpa/ClientApp/boot-client.tsx
@@ -12,7 +12,8 @@ import * as RoutesModule from './routes';
let routes = RoutesModule.routes;
// Create browser history to use in the Redux store
-const history = createBrowserHistory();
+const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
+const history = createBrowserHistory({ basename: baseUrl });
// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = (window as any).initialReduxState as ApplicationState;
diff --git a/templates/ReactReduxSpa/ClientApp/boot-server.tsx b/templates/ReactReduxSpa/ClientApp/boot-server.tsx
index 62be968..7b622c0 100644
--- a/templates/ReactReduxSpa/ClientApp/boot-server.tsx
+++ b/templates/ReactReduxSpa/ClientApp/boot-server.tsx
@@ -12,15 +12,17 @@ export default createServerRenderer(params => {
return new Promise((resolve, reject) => {
// Prepare Redux store with in-memory history, and dispatch a navigation event
// corresponding to the incoming URL
+ const basename = params.baseUrl.substring(0, params.baseUrl.length - 1); // Remove trailing slash
+ const urlAfterBasename = params.url.substring(basename.length);
const store = configureStore(createMemoryHistory());
- store.dispatch(replace(params.location));
+ store.dispatch(replace(urlAfterBasename));
// Prepare an instance of the application and perform an inital render that will
// cause any async tasks (e.g., data access) to begin
const routerContext: any = {};
const app = (
-
+
);
renderToString(app);
diff --git a/templates/ReactReduxSpa/ClientApp/store/WeatherForecasts.ts b/templates/ReactReduxSpa/ClientApp/store/WeatherForecasts.ts
index 87828de..e7960b1 100644
--- a/templates/ReactReduxSpa/ClientApp/store/WeatherForecasts.ts
+++ b/templates/ReactReduxSpa/ClientApp/store/WeatherForecasts.ts
@@ -45,7 +45,7 @@ export const actionCreators = {
requestWeatherForecasts: (startDateIndex: number): AppThunkAction => (dispatch, getState) => {
// Only load data if it's something we don't already have (and are not already loading)
if (startDateIndex !== getState().weatherForecasts.startDateIndex) {
- let fetchTask = fetch(`/api/SampleData/WeatherForecasts?startDateIndex=${ startDateIndex }`)
+ let fetchTask = fetch(`api/SampleData/WeatherForecasts?startDateIndex=${ startDateIndex }`)
.then(response => response.json() as Promise)
.then(data => {
dispatch({ type: 'RECEIVE_WEATHER_FORECASTS', startDateIndex: startDateIndex, forecasts: data });
diff --git a/templates/ReactReduxSpa/npm-shrinkwrap.json b/templates/ReactReduxSpa/npm-shrinkwrap.json
index 9dc18a0..5e4df91 100644
--- a/templates/ReactReduxSpa/npm-shrinkwrap.json
+++ b/templates/ReactReduxSpa/npm-shrinkwrap.json
@@ -170,26 +170,19 @@
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz"
},
"aspnet-prerendering": {
- "version": "2.0.6",
- "from": "aspnet-prerendering@>=2.0.5 <3.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-2.0.6.tgz",
- "dependencies": {
- "domain-task": {
- "version": "2.0.3",
- "from": "domain-task@>=2.0.2 <3.0.0",
- "resolved": "https://registry.npmjs.org/domain-task/-/domain-task-2.0.3.tgz"
- }
- }
+ "version": "3.0.1",
+ "from": "aspnet-prerendering@3.0.1",
+ "resolved": "https://registry.npmjs.org/aspnet-prerendering/-/aspnet-prerendering-3.0.1.tgz"
},
"aspnet-webpack": {
- "version": "1.0.29",
- "from": "aspnet-webpack@>=1.0.29 <2.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz"
+ "version": "2.0.0",
+ "from": "aspnet-webpack@2.0.0",
+ "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.0.tgz"
},
"aspnet-webpack-react": {
- "version": "3.0.0-beta.1",
- "from": "aspnet-webpack-react@>=3.0.0-beta <4.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0-beta.1.tgz"
+ "version": "3.0.0",
+ "from": "aspnet-webpack-react@3.0.0",
+ "resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0.tgz"
},
"assert": {
"version": "1.4.1",
diff --git a/templates/ReactReduxSpa/package.json b/templates/ReactReduxSpa/package.json
index 9d3ab76..b8c308a 100644
--- a/templates/ReactReduxSpa/package.json
+++ b/templates/ReactReduxSpa/package.json
@@ -12,9 +12,9 @@
"@types/react-router-redux": "5.0.3",
"@types/webpack": "2.2.15",
"@types/webpack-env": "1.13.0",
- "aspnet-prerendering": "^2.0.5",
- "aspnet-webpack": "^1.0.29",
- "aspnet-webpack-react": "^3.0.0-beta",
+ "aspnet-prerendering": "^3.0.1",
+ "aspnet-webpack": "^2.0.0",
+ "aspnet-webpack-react": "^3.0.0",
"awesome-typescript-loader": "3.2.1",
"bootstrap": "3.3.7",
"css-loader": "0.28.4",
diff --git a/templates/ReactReduxSpa/webpack.config.js b/templates/ReactReduxSpa/webpack.config.js
index 5a613b8..deebbeb 100644
--- a/templates/ReactReduxSpa/webpack.config.js
+++ b/templates/ReactReduxSpa/webpack.config.js
@@ -13,7 +13,7 @@ module.exports = (env) => {
resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
output: {
filename: '[name].js',
- publicPath: '/dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
+ publicPath: 'dist/' // Webpack dev middleware, if enabled, handles requests for this URL prefix
},
module: {
rules: [
diff --git a/templates/ReactReduxSpa/webpack.config.vendor.js b/templates/ReactReduxSpa/webpack.config.vendor.js
index dbc0303..eaaa647 100644
--- a/templates/ReactReduxSpa/webpack.config.vendor.js
+++ b/templates/ReactReduxSpa/webpack.config.vendor.js
@@ -33,7 +33,7 @@ module.exports = (env) => {
],
},
output: {
- publicPath: '/dist/',
+ publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},
diff --git a/templates/ReactSpa/ClientApp/boot.tsx b/templates/ReactSpa/ClientApp/boot.tsx
index 3b2debf..a97ee68 100644
--- a/templates/ReactSpa/ClientApp/boot.tsx
+++ b/templates/ReactSpa/ClientApp/boot.tsx
@@ -10,9 +10,10 @@ let routes = RoutesModule.routes;
function renderApp() {
// This code starts up the React app when it runs in a browser. It sets up the routing
// configuration and injects the app into a DOM element.
+ const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
ReactDOM.render(
-
+
,
document.getElementById('react-app')
);
diff --git a/templates/ReactSpa/ClientApp/components/FetchData.tsx b/templates/ReactSpa/ClientApp/components/FetchData.tsx
index 6474f01..c958ea6 100644
--- a/templates/ReactSpa/ClientApp/components/FetchData.tsx
+++ b/templates/ReactSpa/ClientApp/components/FetchData.tsx
@@ -11,7 +11,7 @@ export class FetchData extends React.Component<{}, FetchDataExampleState> {
super();
this.state = { forecasts: [], loading: true };
- fetch('/api/SampleData/WeatherForecasts')
+ fetch('api/SampleData/WeatherForecasts')
.then(response => response.json() as Promise)
.then(data => {
this.setState({ forecasts: data, loading: false });
diff --git a/templates/ReactSpa/npm-shrinkwrap.json b/templates/ReactSpa/npm-shrinkwrap.json
index 694cbc9..4069cea 100644
--- a/templates/ReactSpa/npm-shrinkwrap.json
+++ b/templates/ReactSpa/npm-shrinkwrap.json
@@ -155,15 +155,15 @@
"dev": true
},
"aspnet-webpack": {
- "version": "1.0.29",
- "from": "aspnet-webpack@>=1.0.29 <2.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
+ "version": "2.0.0",
+ "from": "aspnet-webpack@2.0.0",
+ "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.0.tgz",
"dev": true
},
"aspnet-webpack-react": {
- "version": "3.0.0-beta.1",
- "from": "aspnet-webpack-react@>=3.0.0-beta <4.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0-beta.1.tgz",
+ "version": "3.0.0",
+ "from": "aspnet-webpack-react@3.0.0",
+ "resolved": "https://registry.npmjs.org/aspnet-webpack-react/-/aspnet-webpack-react-3.0.0.tgz",
"dev": true
},
"assert": {
diff --git a/templates/ReactSpa/package.json b/templates/ReactSpa/package.json
index 980d979..913de25 100644
--- a/templates/ReactSpa/package.json
+++ b/templates/ReactSpa/package.json
@@ -8,8 +8,8 @@
"@types/react-dom": "15.5.1",
"@types/react-router": "4.0.12",
"@types/webpack-env": "1.13.0",
- "aspnet-webpack": "^1.0.29",
- "aspnet-webpack-react": "^3.0.0-beta",
+ "aspnet-webpack": "^2.0.0",
+ "aspnet-webpack-react": "^3.0.0",
"awesome-typescript-loader": "3.2.1",
"bootstrap": "3.3.7",
"css-loader": "0.28.4",
diff --git a/templates/ReactSpa/webpack.config.js b/templates/ReactSpa/webpack.config.js
index e2254d6..01e45ea 100644
--- a/templates/ReactSpa/webpack.config.js
+++ b/templates/ReactSpa/webpack.config.js
@@ -13,7 +13,7 @@ module.exports = (env) => {
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
- publicPath: '/dist/'
+ publicPath: 'dist/'
},
module: {
rules: [
diff --git a/templates/ReactSpa/webpack.config.vendor.js b/templates/ReactSpa/webpack.config.vendor.js
index 11fc2a6..d23ac4f 100644
--- a/templates/ReactSpa/webpack.config.vendor.js
+++ b/templates/ReactSpa/webpack.config.vendor.js
@@ -21,7 +21,7 @@ module.exports = (env) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
- publicPath: '/dist/',
+ publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]',
},
diff --git a/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts b/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts
index dcc37f0..c6108f9 100644
--- a/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts
+++ b/templates/VueSpa/ClientApp/components/fetchdata/fetchdata.ts
@@ -13,7 +13,7 @@ export default class FetchDataComponent extends Vue {
forecasts: WeatherForecast[] = [];
mounted() {
- fetch('/api/SampleData/WeatherForecasts')
+ fetch('api/SampleData/WeatherForecasts')
.then(response => response.json() as Promise)
.then(data => {
this.forecasts = data;
diff --git a/templates/VueSpa/npm-shrinkwrap.json b/templates/VueSpa/npm-shrinkwrap.json
index 55b7451..ab6bf01 100644
--- a/templates/VueSpa/npm-shrinkwrap.json
+++ b/templates/VueSpa/npm-shrinkwrap.json
@@ -119,9 +119,9 @@
"dev": true
},
"aspnet-webpack": {
- "version": "1.0.29",
- "from": "aspnet-webpack@>=1.0.27 <2.0.0",
- "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-1.0.29.tgz",
+ "version": "2.0.0",
+ "from": "aspnet-webpack@2.0.0",
+ "resolved": "https://registry.npmjs.org/aspnet-webpack/-/aspnet-webpack-2.0.0.tgz",
"dev": true
},
"assert": {
diff --git a/templates/VueSpa/package.json b/templates/VueSpa/package.json
index d7b4334..eac756d 100644
--- a/templates/VueSpa/package.json
+++ b/templates/VueSpa/package.json
@@ -4,7 +4,7 @@
"version": "0.0.0",
"devDependencies": {
"@types/requirejs": "^2.1.28",
- "aspnet-webpack": "^1.0.27",
+ "aspnet-webpack": "^2.0.0",
"awesome-typescript-loader": "^3.0.0",
"bootstrap": "^3.3.6",
"css-loader": "^0.25.0",
diff --git a/templates/VueSpa/webpack.config.js b/templates/VueSpa/webpack.config.js
index 7aca565..a44f366 100644
--- a/templates/VueSpa/webpack.config.js
+++ b/templates/VueSpa/webpack.config.js
@@ -23,7 +23,7 @@ module.exports = (env) => {
output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
- publicPath: '/dist/'
+ publicPath: 'dist/'
},
plugins: [
new CheckerPlugin(),
diff --git a/templates/VueSpa/webpack.config.vendor.js b/templates/VueSpa/webpack.config.vendor.js
index 2cd2af6..5c21d67 100644
--- a/templates/VueSpa/webpack.config.vendor.js
+++ b/templates/VueSpa/webpack.config.vendor.js
@@ -28,7 +28,7 @@ module.exports = (env) => {
},
output: {
path: path.join(__dirname, 'wwwroot', 'dist'),
- publicPath: '/dist/',
+ publicPath: 'dist/',
filename: '[name].js',
library: '[name]_[hash]'
},