parent
47536a3c14
commit
383a4ebc52
|
|
@ -1,37 +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 Microsoft.AspNetCore.Components.WebAssembly.Services;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|
||||||
{
|
|
||||||
internal class TestWebAssemblyJSRuntimeInvoker : WebAssemblyJSRuntimeInvoker
|
|
||||||
{
|
|
||||||
private readonly string _environment;
|
|
||||||
|
|
||||||
public TestWebAssemblyJSRuntimeInvoker(string environment = "Production")
|
|
||||||
{
|
|
||||||
_environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
|
||||||
{
|
|
||||||
switch (identifier)
|
|
||||||
{
|
|
||||||
case "Blazor._internal.getApplicationEnvironment":
|
|
||||||
return (TResult)(object)_environment;
|
|
||||||
case "Blazor._internal.getConfig":
|
|
||||||
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:
|
|
||||||
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
|
|
@ -170,21 +170,16 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
|
||||||
module.postRun = [];
|
module.postRun = [];
|
||||||
(module as any).preloadPlugins = [];
|
(module as any).preloadPlugins = [];
|
||||||
|
|
||||||
// Begin loading the .dll/.pdb/.wasm files, but don't block here. Let other loading processes run in parallel.
|
|
||||||
const dotnetWasmResourceName = 'dotnet.wasm';
|
|
||||||
const assembliesBeingLoaded = resourceLoader.loadResources(resources.assembly, filename => `_framework/_bin/${filename}`);
|
|
||||||
const pdbsBeingLoaded = resourceLoader.loadResources(resources.pdb || {}, filename => `_framework/_bin/${filename}`);
|
|
||||||
const wasmBeingLoaded = resourceLoader.loadResource(
|
|
||||||
/* name */ dotnetWasmResourceName,
|
|
||||||
/* url */ `_framework/wasm/${dotnetWasmResourceName}`,
|
|
||||||
/* hash */ resourceLoader.bootConfig.resources.runtime[dotnetWasmResourceName]);
|
|
||||||
|
|
||||||
// Override the mechanism for fetching the main wasm file so we can connect it to our cache
|
// Override the mechanism for fetching the main wasm file so we can connect it to our cache
|
||||||
module.instantiateWasm = (imports, successCallback): WebAssembly.Exports => {
|
module.instantiateWasm = (imports, successCallback): WebAssembly.Exports => {
|
||||||
(async () => {
|
(async () => {
|
||||||
let compiledInstance: WebAssembly.Instance;
|
let compiledInstance: WebAssembly.Instance;
|
||||||
try {
|
try {
|
||||||
const dotnetWasmResource = await wasmBeingLoaded;
|
const dotnetWasmResourceName = 'dotnet.wasm';
|
||||||
|
const dotnetWasmResource = await resourceLoader.loadResource(
|
||||||
|
/* name */ dotnetWasmResourceName,
|
||||||
|
/* url */ `_framework/wasm/${dotnetWasmResourceName}`,
|
||||||
|
/* hash */ resourceLoader.bootConfig.resources.runtime[dotnetWasmResourceName]);
|
||||||
compiledInstance = await compileWasmModule(dotnetWasmResource, imports);
|
compiledInstance = await compileWasmModule(dotnetWasmResource, imports);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
module.printErr(ex);
|
module.printErr(ex);
|
||||||
|
|
@ -205,8 +200,12 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
|
||||||
// Fetch the assemblies and PDBs in the background, telling Mono to wait until they are loaded
|
// Fetch the assemblies and PDBs in the background, telling Mono to wait until they are loaded
|
||||||
// Mono requires the assembly filenames to have a '.dll' extension, so supply such names regardless
|
// Mono requires the assembly filenames to have a '.dll' extension, so supply such names regardless
|
||||||
// of the extensions in the URLs. This allows loading assemblies with arbitrary filenames.
|
// of the extensions in the URLs. This allows loading assemblies with arbitrary filenames.
|
||||||
assembliesBeingLoaded.forEach(r => addResourceAsAssembly(r, changeExtension(r.name, '.dll')));
|
resourceLoader.loadResources(resources.assembly, filename => `_framework/_bin/${filename}`)
|
||||||
pdbsBeingLoaded.forEach(r => addResourceAsAssembly(r, r.name));
|
.forEach(r => addResourceAsAssembly(r, changeExtension(r.name, '.dll')));
|
||||||
|
if (resources.pdb) {
|
||||||
|
resourceLoader.loadResources(resources.pdb, filename => `_framework/_bin/${filename}`)
|
||||||
|
.forEach(r => addResourceAsAssembly(r, r.name));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.postRun.push(() => {
|
module.postRun.push(() => {
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ export const internalFunctions = {
|
||||||
listenForNavigationEvents,
|
listenForNavigationEvents,
|
||||||
enableNavigationInterception,
|
enableNavigationInterception,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
getBaseURI: () => BINDING.js_string_to_mono_string(document.baseURI),
|
getBaseURI: () => document.baseURI,
|
||||||
getLocationHref: () => BINDING.js_string_to_mono_string(location.href),
|
getLocationHref: () => 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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,63 +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.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.Hosting
|
|
||||||
{
|
|
||||||
public static class DebugProxyHost
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a custom HostBuilder for the DebugProxyLauncher so that we can inject
|
|
||||||
/// only the needed configurations.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="args">Command line arguments passed in</param>
|
|
||||||
/// <param name="browserHost">Host where browser is listening for debug connections</param>
|
|
||||||
/// <returns><see cref="IHostBuilder"></returns>
|
|
||||||
public static IHostBuilder CreateDefaultBuilder(string[] args, string browserHost)
|
|
||||||
{
|
|
||||||
var builder = new HostBuilder();
|
|
||||||
|
|
||||||
builder.ConfigureAppConfiguration((hostingContext, config) =>
|
|
||||||
{
|
|
||||||
if (args != null)
|
|
||||||
{
|
|
||||||
config.AddCommandLine(args);
|
|
||||||
}
|
|
||||||
config.AddJsonFile("blazor-debugproxysettings.json", optional: true, reloadOnChange: true);
|
|
||||||
})
|
|
||||||
.ConfigureLogging((hostingContext, logging) =>
|
|
||||||
{
|
|
||||||
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
|
|
||||||
logging.AddConsole();
|
|
||||||
logging.AddDebug();
|
|
||||||
logging.AddEventSourceLogger();
|
|
||||||
})
|
|
||||||
.ConfigureWebHostDefaults(webBuilder =>
|
|
||||||
{
|
|
||||||
webBuilder.UseStartup<Startup>();
|
|
||||||
|
|
||||||
// By default we bind to a dyamic port
|
|
||||||
// This can be overridden using an option like "--urls http://localhost:9500"
|
|
||||||
webBuilder.UseUrls("http://127.0.0.1:0");
|
|
||||||
})
|
|
||||||
.ConfigureServices(serviceCollection =>
|
|
||||||
{
|
|
||||||
serviceCollection.AddSingleton(new DebugProxyOptions
|
|
||||||
{
|
|
||||||
BrowserHost = browserHost
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.DebugProxy.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.CommandLineUtils;
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
@ -37,8 +36,29 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.DebugProxy
|
||||||
|
|
||||||
app.OnExecute(() =>
|
app.OnExecute(() =>
|
||||||
{
|
{
|
||||||
var browserHost = browserHostOption.HasValue() ? browserHostOption.Value(): "http://127.0.0.1:9222";
|
var host = Host.CreateDefaultBuilder(args)
|
||||||
var host = DebugProxyHost.CreateDefaultBuilder(args, browserHost).Build();
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.AddCommandLine(args);
|
||||||
|
})
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
|
||||||
|
// By default we bind to a dyamic port
|
||||||
|
// This can be overridden using an option like "--urls http://localhost:9500"
|
||||||
|
webBuilder.UseUrls("http://127.0.0.1:0");
|
||||||
|
})
|
||||||
|
.ConfigureServices(serviceCollection =>
|
||||||
|
{
|
||||||
|
serviceCollection.AddSingleton(new DebugProxyOptions
|
||||||
|
{
|
||||||
|
BrowserHost = browserHostOption.HasValue()
|
||||||
|
? browserHostOption.Value()
|
||||||
|
: "http://127.0.0.1:9222",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
if (ownerPidOption.HasValue())
|
if (ownerPidOption.HasValue())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,39 +42,6 @@ namespace Microsoft.JSInterop.WebAssembly
|
||||||
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
|
BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<TResult>(string identifier)
|
|
||||||
=> InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, TResult>(string identifier, T0 arg0)
|
|
||||||
=> InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
|
||||||
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
|
||||||
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
|
||||||
/// <param name="identifier">The identifier used when registering the target function.</param>
|
|
||||||
/// <param name="arg0">The first argument.</param>
|
|
||||||
/// <param name="arg1">The second argument.</param>
|
|
||||||
/// <returns>The result of the function invocation.</returns>
|
|
||||||
public TResult InvokeUnmarshalled<T0, T1, TResult>(string identifier, T0 arg0, T1 arg1)
|
|
||||||
=> InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invokes the JavaScript function registered with the specified identifier.
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -87,7 +54,7 @@ namespace Microsoft.JSInterop.WebAssembly
|
||||||
/// <param name="arg1">The second argument.</param>
|
/// <param name="arg1">The second argument.</param>
|
||||||
/// <param name="arg2">The third argument.</param>
|
/// <param name="arg2">The third argument.</param>
|
||||||
/// <returns>The result of the function invocation.</returns>
|
/// <returns>The result of the function invocation.</returns>
|
||||||
public TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
public virtual TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
||||||
{
|
{
|
||||||
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TResult>(out var exception, identifier, arg0, arg1, arg2);
|
var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TResult>(out var exception, identifier, arg0, arg1, arg2);
|
||||||
return exception != null
|
return exception != null
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.JSInterop.WebAssembly
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for <see cref="WebAssemblyJSRuntime"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class WebAssemblyJSRuntimeExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||||
|
/// <param name="jsRuntime">The <see cref="WebAssemblyJSRuntime"/>.</param>
|
||||||
|
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||||
|
/// <returns>The result of the function invocation.</returns>
|
||||||
|
public static TResult InvokeUnmarshalled<TResult>(this WebAssemblyJSRuntime jsRuntime, string identifier)
|
||||||
|
{
|
||||||
|
if (jsRuntime is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(jsRuntime));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsRuntime.InvokeUnmarshalled<object, object, object, TResult>(identifier, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||||
|
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||||
|
/// <param name="jsRuntime">The <see cref="WebAssemblyJSRuntime"/>.</param>
|
||||||
|
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||||
|
/// <param name="arg0">The first argument.</param>
|
||||||
|
/// <returns>The result of the function invocation.</returns>
|
||||||
|
public static TResult InvokeUnmarshalled<T0, TResult>(this WebAssemblyJSRuntime jsRuntime, string identifier, T0 arg0)
|
||||||
|
{
|
||||||
|
if (jsRuntime is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(jsRuntime));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsRuntime.InvokeUnmarshalled<T0, object, object, TResult>(identifier, arg0, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the JavaScript function registered with the specified identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T0">The type of the first argument.</typeparam>
|
||||||
|
/// <typeparam name="T1">The type of the second argument.</typeparam>
|
||||||
|
/// <typeparam name="TResult">The .NET type corresponding to the function's return value type.</typeparam>
|
||||||
|
/// <param name="jsRuntime">The <see cref="WebAssemblyJSRuntime"/>.</param>
|
||||||
|
/// <param name="identifier">The identifier used when registering the target function.</param>
|
||||||
|
/// <param name="arg0">The first argument.</param>
|
||||||
|
/// <param name="arg1">The second argument.</param>
|
||||||
|
/// <returns>The result of the function invocation.</returns>
|
||||||
|
public static TResult InvokeUnmarshalled<T0, T1, TResult>(this WebAssemblyJSRuntime jsRuntime, string identifier, T0 arg0, T1 arg1)
|
||||||
|
{
|
||||||
|
if (jsRuntime is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(jsRuntime));
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsRuntime.InvokeUnmarshalled<T0, T1, object, TResult>(identifier, arg0, arg1, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -52,6 +52,7 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
};
|
};
|
||||||
|
RemoveUnwantedEnvironmentVariables(processStartInfo.Environment);
|
||||||
|
|
||||||
var debugProxyProcess = Process.Start(processStartInfo);
|
var debugProxyProcess = Process.Start(processStartInfo);
|
||||||
CompleteTaskWhenServerIsReady(debugProxyProcess, tcs);
|
CompleteTaskWhenServerIsReady(debugProxyProcess, tcs);
|
||||||
|
|
@ -64,6 +65,20 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
return await tcs.Task;
|
return await tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void RemoveUnwantedEnvironmentVariables(IDictionary<string, string> environment)
|
||||||
|
{
|
||||||
|
// Generally we expect to pass through most environment variables, since dotnet might
|
||||||
|
// need them for arbitrary reasons to function correctly. However, we specifically don't
|
||||||
|
// want to pass through any ASP.NET Core hosting related ones, since the child process
|
||||||
|
// shouldn't be trying to use the same port numbers, etc. In particular we need to break
|
||||||
|
// the association with IISExpress and the MS-ASPNETCORE-TOKEN check.
|
||||||
|
var keysToRemove = environment.Keys.Where(key => key.StartsWith("ASPNETCORE_")).ToList();
|
||||||
|
foreach (var key in keysToRemove)
|
||||||
|
{
|
||||||
|
environment.Remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static string LocateDebugProxyExecutable(IWebHostEnvironment environment)
|
private static string LocateDebugProxyExecutable(IWebHostEnvironment environment)
|
||||||
{
|
{
|
||||||
var assembly = Assembly.Load(environment.ApplicationName);
|
var assembly = Assembly.Load(environment.ApplicationName);
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,4 @@
|
||||||
<Reference Include="Microsoft.CodeAnalysis.CSharp" />
|
<Reference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)\test\TestWebAssemblyJSRuntimeInvoker.cs" Link="Shared\TestWebAssemblyJSRuntimeInvoker.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Services;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
|
@ -18,7 +17,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanResolve_AccessTokenProvider()
|
public void CanResolve_AccessTokenProvider()
|
||||||
{
|
{
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -28,7 +27,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanResolve_IRemoteAuthenticationService()
|
public void CanResolve_IRemoteAuthenticationService()
|
||||||
{
|
{
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -38,7 +37,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ApiAuthorizationOptions_ConfigurationDefaultsGetApplied()
|
public void ApiAuthorizationOptions_ConfigurationDefaultsGetApplied()
|
||||||
{
|
{
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -72,7 +71,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ApiAuthorizationOptions_DefaultsCanBeOverriden()
|
public void ApiAuthorizationOptions_DefaultsCanBeOverriden()
|
||||||
{
|
{
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddApiAuthorization(options =>
|
builder.Services.AddApiAuthorization(options =>
|
||||||
{
|
{
|
||||||
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
||||||
|
|
@ -132,7 +131,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void OidcOptions_ConfigurationDefaultsGetApplied()
|
public void OidcOptions_ConfigurationDefaultsGetApplied()
|
||||||
{
|
{
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.Replace(ServiceDescriptor.Singleton<NavigationManager, TestNavigationManager>());
|
builder.Services.Replace(ServiceDescriptor.Singleton<NavigationManager, TestNavigationManager>());
|
||||||
builder.Services.AddOidcAuthentication(options => { });
|
builder.Services.AddOidcAuthentication(options => { });
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
@ -170,7 +169,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
[Fact]
|
[Fact]
|
||||||
public void OidcOptions_DefaultsCanBeOverriden()
|
public void OidcOptions_DefaultsCanBeOverriden()
|
||||||
{
|
{
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(GetJSRuntime());
|
||||||
builder.Services.AddOidcAuthentication(options =>
|
builder.Services.AddOidcAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
options.AuthenticationPaths = new RemoteAuthenticationApplicationPathsOptions
|
||||||
|
|
@ -245,5 +244,19 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Authentication
|
||||||
|
|
||||||
protected override void NavigateToCore(string uri, bool forceLoad) => throw new System.NotImplementedException();
|
protected override void NavigateToCore(string uri, bool forceLoad) => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WebAssemblyJSRuntime GetJSRuntime(string environment = "Production")
|
||||||
|
{
|
||||||
|
var jsRuntime = new Mock<WebAssemblyJSRuntime>();
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<object, object, object, string>("Blazor._internal.getApplicationEnvironment", null, null, null))
|
||||||
|
.Returns(environment)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<string, object, object, byte[]>("Blazor._internal.getConfig", It.IsAny<string>(), null, null))
|
||||||
|
.Returns((byte[])null)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
return jsRuntime.Object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,5 @@ 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,13 +7,13 @@ 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;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Microsoft.JSInterop.WebAssembly;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
{
|
{
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
// We don't use the args for anything right now, but we want to accept them
|
// We don't use the args for anything right now, but we want to accept them
|
||||||
// here so that it shows up this way in the project templates.
|
// here so that it shows up this way in the project templates.
|
||||||
args ??= Array.Empty<string>();
|
args ??= Array.Empty<string>();
|
||||||
var builder = new WebAssemblyHostBuilder(WebAssemblyJSRuntimeInvoker.Instance);
|
var builder = new WebAssemblyHostBuilder(DefaultWebAssemblyJSRuntime.Instance);
|
||||||
|
|
||||||
// Right now we don't have conventions or behaviors that are specific to this method
|
// Right now we don't have conventions or behaviors that are specific to this method
|
||||||
// however, making this the default for the template allows us to add things like that
|
// however, making this the default for the template allows us to add things like that
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> with the minimal configuration.
|
/// Creates an instance of <see cref="WebAssemblyHostBuilder"/> with the minimal configuration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal WebAssemblyHostBuilder(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
internal WebAssemblyHostBuilder(WebAssemblyJSRuntime jsRuntime)
|
||||||
{
|
{
|
||||||
// Private right now because we don't have much reason to expose it. This can be exposed
|
// Private right now because we don't have much reason to expose it. This can be exposed
|
||||||
// in the future if we want to give people a choice between CreateDefault and something
|
// in the future if we want to give people a choice between CreateDefault and something
|
||||||
|
|
@ -56,32 +56,20 @@ 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(jsRuntime);
|
||||||
HostEnvironment = hostEnvironment;
|
|
||||||
|
|
||||||
_createServiceProvider = () =>
|
_createServiceProvider = () =>
|
||||||
{
|
{
|
||||||
return Services.BuildServiceProvider(validateScopes: WebAssemblyHostEnvironmentExtensions.IsDevelopment(hostEnvironment));
|
return Services.BuildServiceProvider(validateScopes: hostEnvironment.Environment == "Development");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeNavigationManager(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
private WebAssemblyHostEnvironment InitializeEnvironment(WebAssemblyJSRuntime jsRuntime)
|
||||||
{
|
{
|
||||||
var baseUri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetBaseUri, null, null, null);
|
var applicationEnvironment = jsRuntime.InvokeUnmarshalled<string>("Blazor._internal.getApplicationEnvironment");
|
||||||
var uri = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(BrowserNavigationManagerInterop.GetLocationHref, null, null, null);
|
var hostEnvironment = new WebAssemblyHostEnvironment(applicationEnvironment);
|
||||||
|
|
||||||
WebAssemblyNavigationManager.Instance = new WebAssemblyNavigationManager(baseUri, uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebAssemblyHostEnvironment InitializeEnvironment(WebAssemblyJSRuntimeInvoker jsRuntimeInvoker)
|
|
||||||
{
|
|
||||||
var applicationEnvironment = jsRuntimeInvoker.InvokeUnmarshalled<object, object, object, string>(
|
|
||||||
"Blazor._internal.getApplicationEnvironment", null, null, null);
|
|
||||||
var hostEnvironment = new WebAssemblyHostEnvironment(applicationEnvironment, WebAssemblyNavigationManager.Instance.BaseUri);
|
|
||||||
|
|
||||||
Services.AddSingleton<IWebAssemblyHostEnvironment>(hostEnvironment);
|
Services.AddSingleton<IWebAssemblyHostEnvironment>(hostEnvironment);
|
||||||
|
|
||||||
|
|
@ -93,8 +81,9 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
|
||||||
foreach (var configFile in configFiles)
|
foreach (var configFile in configFiles)
|
||||||
{
|
{
|
||||||
var appSettingsJson = jsRuntimeInvoker.InvokeUnmarshalled<string, object, object, byte[]>(
|
var appSettingsJson = jsRuntime.InvokeUnmarshalled<string, byte[]>(
|
||||||
"Blazor._internal.getConfig", configFile, null, null);
|
"Blazor._internal.getConfig",
|
||||||
|
configFile);
|
||||||
|
|
||||||
if (appSettingsJson != null)
|
if (appSettingsJson != null)
|
||||||
{
|
{
|
||||||
|
|
@ -123,11 +112,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IServiceCollection Services { get; }
|
public IServiceCollection Services { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets information about the app's host environment.
|
|
||||||
/// </summary>
|
|
||||||
public IWebAssemblyHostEnvironment HostEnvironment { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers a <see cref="IServiceProviderFactory{TBuilder}" /> instance to be used to create the <see cref="IServiceProvider" />.
|
/// Registers a <see cref="IServiceProviderFactory{TBuilder}" /> instance to be used to create the <see cref="IServiceProvider" />.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -140,11 +124,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,14 +5,8 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
{
|
{
|
||||||
internal sealed class WebAssemblyHostEnvironment : IWebAssemblyHostEnvironment
|
internal sealed class WebAssemblyHostEnvironment : IWebAssemblyHostEnvironment
|
||||||
{
|
{
|
||||||
public WebAssemblyHostEnvironment(string environment, string baseAddress)
|
public WebAssemblyHostEnvironment(string environment) => Environment = environment;
|
||||||
{
|
|
||||||
Environment = environment;
|
|
||||||
BaseAddress = baseAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Environment { get; }
|
public string Environment { get; }
|
||||||
|
|
||||||
public string BaseAddress { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,75 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
|
||||||
{
|
|
||||||
public static class WebAssemblyHostEnvironmentExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the current hosting environment name is <see cref="EnvironmentName.Development"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hostingEnvironment">An instance of <see cref="IWebAssemblyHostEnvironment"/>.</param>
|
|
||||||
/// <returns>True if the environment name is <see cref="EnvironmentName.Development"/>, otherwise false.</returns>
|
|
||||||
public static bool IsDevelopment(this IWebAssemblyHostEnvironment hostingEnvironment)
|
|
||||||
{
|
|
||||||
if (hostingEnvironment == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(hostingEnvironment));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostingEnvironment.IsEnvironment("Development");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the current hosting environment name is <see cref="EnvironmentName.Staging"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hostingEnvironment">An instance of <see cref="IWebAssemblyHostEnvironment"/>.</param>
|
|
||||||
/// <returns>True if the environment name is <see cref="EnvironmentName.Staging"/>, otherwise false.</returns>
|
|
||||||
public static bool IsStaging(this IWebAssemblyHostEnvironment hostingEnvironment)
|
|
||||||
{
|
|
||||||
if (hostingEnvironment == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(hostingEnvironment));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostingEnvironment.IsEnvironment("Staging");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if the current hosting environment name is <see cref="EnvironmentName.Production"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hostingEnvironment">An instance of <see cref="IWebAssemblyHostEnvironment"/>.</param>
|
|
||||||
/// <returns>True if the environment name is <see cref="EnvironmentName.Production"/>, otherwise false.</returns>
|
|
||||||
public static bool IsProduction(this IWebAssemblyHostEnvironment hostingEnvironment)
|
|
||||||
{
|
|
||||||
if (hostingEnvironment == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(hostingEnvironment));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hostingEnvironment.IsEnvironment("Production");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Compares the current hosting environment name against the specified value.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="hostingEnvironment">An instance of <see cref="IWebAssemblyHostEnvironment"/>.</param>
|
|
||||||
/// <param name="environmentName">Environment name to validate against.</param>
|
|
||||||
/// <returns>True if the specified name is the same as the current environment, otherwise false.</returns>
|
|
||||||
public static bool IsEnvironment(
|
|
||||||
this IWebAssemblyHostEnvironment hostingEnvironment,
|
|
||||||
string environmentName)
|
|
||||||
{
|
|
||||||
if (hostingEnvironment == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(hostingEnvironment));
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Equals(
|
|
||||||
hostingEnvironment.Environment,
|
|
||||||
environmentName,
|
|
||||||
StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
// 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)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,27 +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 Microsoft.JSInterop.WebAssembly;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// This class exists to enable unit testing for code that needs to call
|
|
||||||
/// <see cref="WebAssemblyJSRuntime.InvokeUnmarshalled{T0, T1, T2, TResult}(string, T0, T1, T2)"/>.
|
|
||||||
///
|
|
||||||
/// We should only use this in non-perf-critical code paths (for example, during hosting startup,
|
|
||||||
/// where we only call this a fixed number of times, and not during rendering where it might be
|
|
||||||
/// called arbitrarily frequently due to application logic). In perf-critical code paths, use
|
|
||||||
/// <see cref="DefaultWebAssemblyJSRuntime.Instance"/> and call it directly.
|
|
||||||
///
|
|
||||||
/// It might not ultimately make any difference but we won't know until we integrate AoT support.
|
|
||||||
/// When AoT is used, it's possible that virtual dispatch will force fallback on the interpreter.
|
|
||||||
/// </summary>
|
|
||||||
internal class WebAssemblyJSRuntimeInvoker
|
|
||||||
{
|
|
||||||
public static WebAssemblyJSRuntimeInvoker Instance = new WebAssemblyJSRuntimeInvoker();
|
|
||||||
|
|
||||||
public virtual TResult InvokeUnmarshalled<T0, T1, T2, TResult>(string identifier, T0 arg0, T1 arg1, T2 arg2)
|
|
||||||
=> DefaultWebAssemblyJSRuntime.Instance.InvokeUnmarshalled<T0, T1, T2, TResult>(identifier, arg0, arg1, arg2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,10 +15,21 @@ 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 WebAssemblyNavigationManager Instance { get; set; }
|
public static readonly WebAssemblyNavigationManager Instance = new WebAssemblyNavigationManager();
|
||||||
|
|
||||||
public WebAssemblyNavigationManager(string baseUri, string uri)
|
// For simplicity we force public consumption of the BrowserNavigationManager through
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// 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 Microsoft.JSInterop.WebAssembly;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
|
{
|
||||||
|
public class TestWebAssemblyJSRuntime
|
||||||
|
{
|
||||||
|
public static WebAssemblyJSRuntime Create(string environment = "Production")
|
||||||
|
{
|
||||||
|
var jsRuntime = new Mock<WebAssemblyJSRuntime>();
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<object, object, object, string>("Blazor._internal.getApplicationEnvironment", null, null, null))
|
||||||
|
.Returns(environment)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
jsRuntime.Setup(j => j.InvokeUnmarshalled<string, object, object, byte[]>("Blazor._internal.getConfig", It.IsAny<string>(), null, null))
|
||||||
|
.Returns((byte[])null)
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
return jsRuntime.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,6 @@ 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;
|
||||||
|
|
@ -22,7 +21,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringConfiguration()
|
public void Build_AllowsConfiguringConfiguration()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Configuration.AddInMemoryCollection(new[]
|
builder.Configuration.AddInMemoryCollection(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -40,7 +39,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringServices()
|
public void Build_AllowsConfiguringServices()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
// This test also verifies that we create a scope.
|
// This test also verifies that we create a scope.
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
|
|
@ -56,7 +55,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringContainer()
|
public void Build_AllowsConfiguringContainer()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
var factory = new MyFakeServiceProviderFactory();
|
var factory = new MyFakeServiceProviderFactory();
|
||||||
|
|
@ -74,7 +73,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AllowsConfiguringContainer_WithDelegate()
|
public void Build_AllowsConfiguringContainer_WithDelegate()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
|
|
||||||
|
|
@ -97,7 +96,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_InDevelopment_ConfiguresWithServiceProviderWithScopeValidation()
|
public void Build_InDevelopment_ConfiguresWithServiceProviderWithScopeValidation()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker(environment: "Development"));
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create(environment: "Development"));
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
||||||
|
|
@ -114,7 +113,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_InProduction_ConfiguresWithServiceProviderWithScopeValidation()
|
public void Build_InProduction_ConfiguresWithServiceProviderWithScopeValidation()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Services.AddScoped<StringBuilder>();
|
builder.Services.AddScoped<StringBuilder>();
|
||||||
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
builder.Services.AddSingleton<TestServiceThatTakesStringBuilder>();
|
||||||
|
|
@ -127,33 +126,6 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
Assert.NotNull(host.Services.GetRequiredService<TestServiceThatTakesStringBuilder>());
|
Assert.NotNull(host.Services.GetRequiredService<TestServiceThatTakesStringBuilder>());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Builder_InDevelopment_SetsHostEnvironmentProperty()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker(environment: "Development"));
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.NotNull(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) { }
|
||||||
|
|
@ -193,7 +165,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Build_AddsConfigurationToServices()
|
public void Build_AddsConfigurationToServices()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
builder.Configuration.AddInMemoryCollection(new[]
|
builder.Configuration.AddInMemoryCollection(new[]
|
||||||
{
|
{
|
||||||
|
|
@ -228,7 +200,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public void Constructor_AddsDefaultServices()
|
public void Constructor_AddsDefaultServices()
|
||||||
{
|
{
|
||||||
// Arrange & Act
|
// Arrange & Act
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(DefaultServiceTypes.Count, builder.Services.Count);
|
Assert.Equal(DefaultServiceTypes.Count, builder.Services.Count);
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public async Task RunAsync_CanExitBasedOnCancellationToken()
|
public async Task RunAsync_CanExitBasedOnCancellationToken()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public async Task RunAsync_CallingTwiceCausesException()
|
public async Task RunAsync_CallingTwiceCausesException()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
var cts = new CancellationTokenSource();
|
var cts = new CancellationTokenSource();
|
||||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Hosting
|
||||||
public async Task DisposeAsync_CanDisposeAfterCallingRunAsync()
|
public async Task DisposeAsync_CanDisposeAfterCallingRunAsync()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new WebAssemblyHostBuilder(new TestWebAssemblyJSRuntimeInvoker());
|
var builder = new WebAssemblyHostBuilder(TestWebAssemblyJSRuntime.Create());
|
||||||
builder.Services.AddSingleton<DisposableService>();
|
builder.Services.AddSingleton<DisposableService>();
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,4 @@
|
||||||
<Reference Include="Microsoft.CodeAnalysis.CSharp" />
|
<Reference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="$(ComponentsSharedSourceRoot)\test\TestWebAssemblyJSRuntimeInvoker.cs" Link="Shared\TestWebAssemblyJSRuntimeInvoker.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
// 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;
|
||||||
|
|
@ -15,7 +13,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.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
builder.Services.AddBaseAddressHttpClient();
|
||||||
|
|
||||||
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("/subdir/filepath");
|
Navigate("/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("/subdir/pattern_filepath/test");
|
Navigate("/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("/subdir/assemblypath_filepath");
|
Navigate("/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("/subdir/assemblypath_pattern_filepath/test");
|
Navigate("/assemblypath_pattern_filepath/test");
|
||||||
WaitUntilLoaded();
|
WaitUntilLoaded();
|
||||||
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
Assert.NotNull(Browser.FindElement(By.Id("test-selector")));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
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;
|
||||||
|
|
@ -37,7 +36,7 @@ namespace BasicTestApp
|
||||||
|
|
||||||
builder.RootComponents.Add<Index>("root");
|
builder.RootComponents.Add<Index>("root");
|
||||||
|
|
||||||
builder.Services.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
builder.Services.AddBaseAddressHttpClient();
|
||||||
builder.Services.AddSingleton<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
builder.Services.AddSingleton<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
|
||||||
builder.Services.AddAuthorizationCore(options =>
|
builder.Services.AddAuthorizationCore(options =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ 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,43 +31,50 @@ 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", subApp =>
|
app.Map("/subdir", app =>
|
||||||
{
|
{
|
||||||
subApp.UseBlazorFrameworkFiles();
|
app.UseBlazorFrameworkFiles();
|
||||||
subApp.UseStaticFiles();
|
app.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.
|
||||||
subApp.Map("/filepath", filepath =>
|
app.Map("/filepath", app =>
|
||||||
|
{
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
filepath.UseRouting();
|
endpoints.MapFallbackToFile("index.html");
|
||||||
filepath.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapFallbackToFile("index.html");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
subApp.Map("/pattern_filepath", patternFilePath =>
|
});
|
||||||
|
|
||||||
|
app.Map("/pattern_filepath", app =>
|
||||||
|
{
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
patternFilePath.UseRouting();
|
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
||||||
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 =>
|
||||||
{
|
{
|
||||||
assemblyPathFilePath.UseRouting();
|
endpoints.MapFallbackToFile("index.html");
|
||||||
assemblyPathFilePath.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapFallbackToFile("index.html");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
subApp.Map("/assemblypath_pattern_filepath", assemblyPatternFilePath =>
|
});
|
||||||
|
|
||||||
|
app.Map("/assemblypath_pattern_filepath", app =>
|
||||||
|
{
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
assemblyPatternFilePath.UseRouting();
|
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
||||||
assemblyPatternFilePath.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapFallbackToFile("test/{*path:nonfile}", "index.html");
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
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;
|
||||||
|
|
@ -19,7 +18,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.AddSingleton(new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
|
builder.Services.AddBaseAddressHttpClient();
|
||||||
#if (IndividualLocalAuth)
|
#if (IndividualLocalAuth)
|
||||||
#if (Hosted)
|
#if (Hosted)
|
||||||
builder.Services.AddApiAuthorization();
|
builder.Services.AddApiAuthorization();
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 27 KiB |
Loading…
Reference in New Issue