Add BaseAddress property to WebAssemblyHostEnvironment (#20019)
- Adds `BaseAddress` to `IWebAssemblyHostEnvironment` - Uses unmarshalled APIs to extract application host - Move NavigationManager initialization to startup code - Fix subdir mapping in ClientSideHostingTest Addresses #19910
This commit is contained in:
parent
ba2bae80fa
commit
e6078c4bdd
|
|
@ -23,6 +23,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
return (TResult)(object)_environment;
|
return (TResult)(object)_environment;
|
||||||
case "Blazor._internal.getConfig":
|
case "Blazor._internal.getConfig":
|
||||||
return (TResult)(object)null;
|
return (TResult)(object)null;
|
||||||
|
case "Blazor._internal.navigationManager.getBaseURI":
|
||||||
|
var testUri = "https://www.example.com/awesome-part-that-will-be-truncated-in-tests";
|
||||||
|
return (TResult)(object)testUri;
|
||||||
|
case "Blazor._internal.navigationManager.getLocationHref":
|
||||||
|
var testHref = "https://www.example.com/awesome-part-that-will-be-truncated-in-tests/cool";
|
||||||
|
return (TResult)(object)testHref;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"{nameof(TestWebAssemblyJSRuntimeInvoker)} has no implementation for '{identifier}'.");
|
throw new NotImplementedException($"{nameof(TestWebAssemblyJSRuntimeInvoker)} has no implementation for '{identifier}'.");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -13,8 +13,8 @@ export const internalFunctions = {
|
||||||
listenForNavigationEvents,
|
listenForNavigationEvents,
|
||||||
enableNavigationInterception,
|
enableNavigationInterception,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
getBaseURI: () => document.baseURI,
|
getBaseURI: () => BINDING.js_string_to_mono_string(document.baseURI),
|
||||||
getLocationHref: () => location.href,
|
getLocationHref: () => BINDING.js_string_to_mono_string(location.href),
|
||||||
};
|
};
|
||||||
|
|
||||||
function listenForNavigationEvents(callback: (uri: string, intercepted: boolean) => Promise<void>) {
|
function listenForNavigationEvents(callback: (uri: string, intercepted: boolean) => Promise<void>) {
|
||||||
|
|
@ -141,4 +141,4 @@ function toBaseUriWithTrailingSlash(baseUri: string) {
|
||||||
|
|
||||||
function eventHasSpecialKey(event: MouseEvent) {
|
function eventHasSpecialKey(event: MouseEvent) {
|
||||||
return event.ctrlKey || event.shiftKey || event.altKey || event.metaKey;
|
return event.ctrlKey || event.shiftKey || event.altKey || event.metaKey;
|
||||||
}
|
}
|
||||||
|
|
@ -13,5 +13,10 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// Configured to "Production" when not specified by the host.
|
/// Configured to "Production" when not specified by the host.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Environment { get; }
|
string Environment { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the base address for the application. This is typically derived from the "<base href>" value in the host page.
|
||||||
|
/// </summary>
|
||||||
|
string BaseAddress { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
using Microsoft.AspNetCore.Components.Routing;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
||||||
|
using Microsoft.AspNetCore.Components.Web;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Configuration.Json;
|
using Microsoft.Extensions.Configuration.Json;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
@ -55,6 +56,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
RootComponents = new RootComponentMappingCollection();
|
RootComponents = new RootComponentMappingCollection();
|
||||||
Services = new ServiceCollection();
|
Services = new ServiceCollection();
|
||||||
|
|
||||||
|
// Retrieve required attributes from JSRuntimeInvoker
|
||||||
|
InitializeNavigationManager(jsRuntimeInvoker);
|
||||||
InitializeDefaultServices();
|
InitializeDefaultServices();
|
||||||
|
|
||||||
var hostEnvironment = InitializeEnvironment(jsRuntimeInvoker);
|
var hostEnvironment = InitializeEnvironment(jsRuntimeInvoker);
|
||||||
|
|
@ -66,11 +69,19 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeNavigationManager(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
||||||
|
{
|
||||||
|
var baseUri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetBaseUri, null, null, null);
|
||||||
|
var uri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetLocationHref, null, null, null);
|
||||||
|
|
||||||
|
WebAssemblyNavigationManager.Instance = new WebAssemblyNavigationManager(baseUri, uri);
|
||||||
|
}
|
||||||
|
|
||||||
private WebAssemblyHostEnvironment InitializeEnvironment(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
private WebAssemblyHostEnvironment InitializeEnvironment(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
||||||
{
|
{
|
||||||
var applicationEnvironment = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(
|
var applicationEnvironment = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(
|
||||||
"Blazor._internal.getApplicationEnvironment", null, null, null);
|
"Blazor._internal.getApplicationEnvironment", null, null, null);
|
||||||
var hostEnvironment = new WebAssemblyHostEnvironment(applicationEnvironment);
|
var hostEnvironment = new WebAssemblyHostEnvironment(applicationEnvironment, WebAssemblyNavigationManager.Instance.BaseUri);
|
||||||
|
|
||||||
Services.AddSingleton<IWebAssemblyHostEnvironment>(hostEnvironment);
|
Services.AddSingleton<IWebAssemblyHostEnvironment>(hostEnvironment);
|
||||||
|
|
||||||
|
|
@ -129,11 +140,11 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// <see cref="ConfigureContainer{TBuilder}(IServiceProviderFactory{TBuilder}, Action{TBuilder})"/> is called by <see cref="Build"/>
|
/// <see cref="ConfigureContainer{TBuilder}(IServiceProviderFactory{TBuilder}, Action{TBuilder})"/> is called by <see cref="Build"/>
|
||||||
/// and so the delegate provided by <paramref name="configure"/> will run after all other services have been registered.
|
/// and so the delegate provided by <paramref name="configure"/> will run after all other services have been registered.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// Multiple calls to <see cref="ConfigureContainer{TBuilder}(IServiceProviderFactory{TBuilder}, Action{TBuilder})"/> will replace
|
/// Multiple calls to <see cref="ConfigureContainer{TBuilder}(IServiceProviderFactory{TBuilder}, Action{TBuilder})"/> will replace
|
||||||
/// the previously stored <paramref name="factory"/> and <paramref name="configure"/> delegate.
|
/// the previously stored <paramref name="factory"/> and <paramref name="configure"/> delegate.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public void ConfigureContainer<TBuilder>(IServiceProviderFactory<TBuilder> factory, Action<TBuilder> configure = null)
|
public void ConfigureContainer<TBuilder>(IServiceProviderFactory<TBuilder> factory, Action<TBuilder> configure = null)
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,14 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
{
|
{
|
||||||
internal sealed class WebAssemblyHostEnvironment : IWebAssemblyHostEnvironment
|
internal sealed class WebAssemblyHostEnvironment : IWebAssemblyHostEnvironment
|
||||||
{
|
{
|
||||||
public WebAssemblyHostEnvironment(string environment) => Environment = environment;
|
public WebAssemblyHostEnvironment(string environment, string baseAddress)
|
||||||
|
{
|
||||||
|
Environment = environment;
|
||||||
|
BaseAddress = baseAddress;
|
||||||
|
}
|
||||||
|
|
||||||
public string Environment { get; }
|
public string Environment { get; }
|
||||||
|
|
||||||
|
public string BaseAddress { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Microsoft.AspNetCore.Components;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyInjection
|
|
||||||
{
|
|
||||||
public static class HttpClientServiceCollectionExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a <see cref="HttpClient" /> instance to the <paramref name="serviceCollection" /> that is
|
|
||||||
/// configured to use the application's base address (<seealso cref="NavigationManager.BaseUri" />).
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="serviceCollection">The <see cref="IServiceCollection" />.</param>
|
|
||||||
/// <returns>The configured <see cref="IServiceCollection" />.</returns>
|
|
||||||
public static IServiceCollection AddBaseAddressHttpClient(this IServiceCollection serviceCollection)
|
|
||||||
{
|
|
||||||
return serviceCollection.AddSingleton(s =>
|
|
||||||
{
|
|
||||||
// Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
|
|
||||||
var navigationManager = s.GetRequiredService<NavigationManager>();
|
|
||||||
return new HttpClient
|
|
||||||
{
|
|
||||||
BaseAddress = new Uri(navigationManager.BaseUri)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,21 +15,10 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the instance of <see cref="WebAssemblyNavigationManager"/>.
|
/// Gets the instance of <see cref="WebAssemblyNavigationManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly WebAssemblyNavigationManager Instance = new WebAssemblyNavigationManager();
|
public static WebAssemblyNavigationManager Instance { get; set; }
|
||||||
|
|
||||||
// For simplicity we force public consumption of the BrowserNavigationManager through
|
public WebAssemblyNavigationManager(string baseUri, string uri)
|
||||||
// a singleton. Only a single instance can be updated by the browser through
|
|
||||||
// interop. We can construct instances for testing.
|
|
||||||
internal WebAssemblyNavigationManager()
|
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
protected override void EnsureInitialized()
|
|
||||||
{
|
|
||||||
// As described in the comment block above, BrowserNavigationManager is only for
|
|
||||||
// client-side (Mono) use, so it's OK to rely on synchronicity here.
|
|
||||||
var baseUri = DefaultWebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetBaseUri);
|
|
||||||
var uri = DefaultWebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetLocationHref);
|
|
||||||
Initialize(baseUri, uri);
|
Initialize(baseUri, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.Text;
|
||||||
using Microsoft.AspNetCore.Components.Routing;
|
using Microsoft.AspNetCore.Components.Routing;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyModel;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using Microsoft.JSInterop.WebAssembly;
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
|
@ -132,14 +133,27 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker(environment: "Development"));
|
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker(environment: "Development"));
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
|
||||||
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(builder.HostEnvironment);
|
Assert.NotNull(builder.HostEnvironment);
|
||||||
Assert.True(WebAssemblyHostEnvironmentExtensions.IsDevelopment(builder.HostEnvironment));
|
Assert.True(WebAssemblyHostEnvironmentExtensions.IsDevelopment(builder.HostEnvironment));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Builder_CreatesNavigationManager()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker(environment: "Development"));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var host = builder.Build();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var navigationManager = host.Services.GetRequiredService<NavigationManager>();
|
||||||
|
Assert.NotNull(navigationManager);
|
||||||
|
Assert.Equal("https://www.example.com/", navigationManager.BaseUri);
|
||||||
|
Assert.Equal("https://www.example.com/awesome-part-that-will-be-truncated-in-tests/cool", navigationManager.Uri);
|
||||||
|
}
|
||||||
|
|
||||||
private class TestServiceThatTakesStringBuilder
|
private class TestServiceThatTakesStringBuilder
|
||||||
{
|
{
|
||||||
public TestServiceThatTakesStringBuilder(StringBuilder builder) { }
|
public TestServiceThatTakesStringBuilder(StringBuilder builder) { }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
@ -13,7 +15,7 @@ namespace StandaloneApp
|
||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
builder.RootComponents.Add<App>("app");
|
builder.RootComponents.Add<App>("app");
|
||||||
builder.Services.AddBaseAddressHttpClient();
|
builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MapFallbackToClientSideBlazor_FilePath()
|
public void MapFallbackToClientSideBlazor_FilePath()
|
||||||
{
|
{
|
||||||
Navigate("/filepath");
|
Navigate("/subdir/filepath");
|
||||||
WaitUntilLoaded();
|
WaitUntilLoaded();
|
||||||
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MapFallbackToClientSideBlazor_Pattern_FilePath()
|
public void MapFallbackToClientSideBlazor_Pattern_FilePath()
|
||||||
{
|
{
|
||||||
Navigate("/pattern_filepath/test");
|
Navigate("/subdir/pattern_filepath/test");
|
||||||
WaitUntilLoaded();
|
WaitUntilLoaded();
|
||||||
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MapFallbackToClientSideBlazor_AssemblyPath_FilePath()
|
public void MapFallbackToClientSideBlazor_AssemblyPath_FilePath()
|
||||||
{
|
{
|
||||||
Navigate("/assemblypath_filepath");
|
Navigate("/subdir/assemblypath_filepath");
|
||||||
WaitUntilLoaded();
|
WaitUntilLoaded();
|
||||||
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MapFallbackToClientSideBlazor_AssemblyPath_Pattern_FilePath()
|
public void MapFallbackToClientSideBlazor_AssemblyPath_Pattern_FilePath()
|
||||||
{
|
{
|
||||||
Navigate("/assemblypath_pattern_filepath/test");
|
Navigate("/subdir/assemblypath_pattern_filepath/test");
|
||||||
WaitUntilLoaded();
|
WaitUntilLoaded();
|
||||||
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BasicTestApp.AuthTest;
|
using BasicTestApp.AuthTest;
|
||||||
|
|
@ -36,7 +37,7 @@ namespace BasicTestApp
|
||||||
|
|
||||||
builder.RootComponents.Add<Index>("root");
|
builder.RootComponents.Add<Index>("root");
|
||||||
|
|
||||||
builder.Services.AddBaseAddressHttpClient();
|
builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||||
builder.Services.AddSingleton<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
builder.Services.AddSingleton<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
||||||
builder.Services.AddAuthorizationCore(options =>
|
builder.Services.AddAuthorizationCore(options =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ namespace TestServer
|
||||||
["Server authentication"] = (BuildWebHost<ServerAuthenticationStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
["Server authentication"] = (BuildWebHost<ServerAuthenticationStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
||||||
["CORS (WASM)"] = (BuildWebHost<CorsStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
["CORS (WASM)"] = (BuildWebHost<CorsStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
||||||
["Prerendering (Server-side)"] = (BuildWebHost<PrerenderedStartup>(CreateAdditionalArgs(args)), "/prerendered"),
|
["Prerendering (Server-side)"] = (BuildWebHost<PrerenderedStartup>(CreateAdditionalArgs(args)), "/prerendered"),
|
||||||
|
["Client-side with fallback"] = (BuildWebHost<StartupWithMapFallbackToClientSideBlazor>(CreateAdditionalArgs(args)), "/fallback"),
|
||||||
["Multiple components (Server-side)"] = (BuildWebHost<MultipleComponents>(CreateAdditionalArgs(args)), "/multiple-components"),
|
["Multiple components (Server-side)"] = (BuildWebHost<MultipleComponents>(CreateAdditionalArgs(args)), "/multiple-components"),
|
||||||
["Globalization + Localization (Server-side)"] = (BuildWebHost<InternationalizationStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
["Globalization + Localization (Server-side)"] = (BuildWebHost<InternationalizationStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
||||||
["Server-side blazor"] = (BuildWebHost<ServerStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
["Server-side blazor"] = (BuildWebHost<ServerStartup>(CreateAdditionalArgs(args)), "/subdir"),
|
||||||
|
|
|
||||||
|
|
@ -31,50 +31,43 @@ namespace TestServer
|
||||||
}
|
}
|
||||||
|
|
||||||
// The client-side files middleware needs to be here because the base href in hardcoded to /subdir/
|
// The client-side files middleware needs to be here because the base href in hardcoded to /subdir/
|
||||||
app.Map("/subdir", app =>
|
app.Map("/subdir", subApp =>
|
||||||
{
|
{
|
||||||
app.UseBlazorFrameworkFiles();
|
subApp.UseBlazorFrameworkFiles();
|
||||||
app.UseStaticFiles();
|
subApp.UseStaticFiles();
|
||||||
});
|
|
||||||
|
|
||||||
// The calls to `Map` allow us to test each of these overloads, while keeping them isolated.
|
// The calls to `Map` allow us to test each of these overloads, while keeping them isolated.
|
||||||
app.Map("/filepath", app =>
|
subApp.Map("/filepath", filepath =>
|
||||||
{
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
{
|
||||||
endpoints.MapFallbackToFile("index.html");
|
filepath.UseRouting();
|
||||||
|
filepath.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapFallbackToFile("index.html");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
subApp.Map("/pattern_filepath", patternFilePath =>
|
||||||
|
|
||||||
app.Map("/pattern_filepath", app =>
|
|
||||||
{
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
{
|
||||||
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
patternFilePath.UseRouting();
|
||||||
|
patternFilePath.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
subApp.Map("/assemblypath_filepath", assemblyPathFilePath =>
|
||||||
|
|
||||||
app.Map("/assemblypath_filepath", app =>
|
|
||||||
{
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
{
|
||||||
endpoints.MapFallbackToFile("index.html");
|
assemblyPathFilePath.UseRouting();
|
||||||
|
assemblyPathFilePath.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapFallbackToFile("index.html");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
subApp.Map("/assemblypath_pattern_filepath", assemblyPatternFilePath =>
|
||||||
|
|
||||||
app.Map("/assemblypath_pattern_filepath", app =>
|
|
||||||
{
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
|
||||||
{
|
{
|
||||||
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
assemblyPatternFilePath.UseRouting();
|
||||||
|
assemblyPatternFilePath.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -18,7 +19,7 @@ namespace ComponentsWebAssembly_CSharp
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
builder.RootComponents.Add<App>("app");
|
builder.RootComponents.Add<App>("app");
|
||||||
|
|
||||||
builder.Services.AddBaseAddressHttpClient();
|
builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
||||||
#if (IndividualLocalAuth)
|
#if (IndividualLocalAuth)
|
||||||
#if (Hosted)
|
#if (Hosted)
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue