在 Blazor WebAssembly 解决方案中,如何在与服务器不同的端口上托管 Blazor WASM 客户端应用 API

In Blazor WebAssembly solution, how to host the Blazor WASM client app on a different port to the server API

我有一个 Blazor WebAssembly 解决方案,其中包含客户端项目、服务器项目和共享项目,基于 Microsoft 的默认解决方案模板。我正在使用 Google Chrome.

在 Visual Studio 2019 预览中进行编辑和调试

开箱即用,解决方案只有一个启动项目,即服务器应用程序。该服务器应用程序具有对客户端应用程序的项目引用。您可以通过检查服务器项目属性中的 "Enable SSL" 将其设置为使用 HTTPS,我已经做到了。

当你点击 debug 时,它工作得很好。

现在我想更改它,以便从 https://localhost:44331 and the API Controller endpoints of the server application are served from https://localhost:44331/api

提供我所有的 Blazor WASM 页面

我想使用 URL 的这个额外的“/api”部分来将对 API 的请求与仅在 Blazor 客户端应用程序中导航分开。因此,如果我请求“https://localhost:44331/api/something" I know I'm going to hit a point in my web API but if I request "https://localhost:44331/something”,我知道我将访问 Blazor 客户端应用程序中的特定页面。我认为它也将更接近正常设置在生产中的方式。

我希望你清楚我想做什么。

显而易见的起点似乎是将服务器应用程序属性 "Debug" 部分中的 "App URL" 设置更改为“http://localhost:52708/api". The project assigns a secure URL of "https://localhost:44331/api". I left the setting the same in the client app, so in the client app, the "App URL" setting in the "Debug" portion of the Properties of the client app is still "http://localhost:52708", with the project assigning a secure URL of "https://localhost:44331”。

这打破了一切。

现在“https://localhost:44331/" takes me to a 404 Not Found error and "https://localhost:44331/api”将我带到一个页面,上面写着:

Loading...
An unhandled error has occurred. Reload

那太容易了!有人知道如何获得我想要的环境的正确方法吗?

Wasm/Hosted 模板对新应用的最小改动:

WeatherForecastController.cs

//[Route("[controller]")]
  [Route("api/[controller]")]

FetchData.razor

//forecasts = await Http.GetJsonAsync<WeatherForecast[]>("WeatherForecast");
  forecasts = await Http.GetJsonAsync<WeatherForecast[]>("api/WeatherForecast");

好的!我终于想出了一个可行的方法。它并不复杂,但我花了 才得到答案,所以我将 post 放在这里,因为我认为它对其他人有用。

在您的控制器上:

[Route("api/[controller]")]
public class SampleController : ControllerBase
    {
    //Etc.
    }

在Startup.cs...

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //Etc.
            app.UseStaticFiles();
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapControllers();
                endpoints.Map("api/{**slug}", HandleApiFallback);
                endpoints.MapFallbackToFile("{**slug}", "index.html");
            });
        }

        private Task HandleApiFallback(HttpContext context)
        {
            context.Response.StatusCode = StatusCodes.Status404NotFound;
            return Task. CompletedTask;
        }