asp.net 将WebView2 REST调用路由到本地.NET 5控制器

xzabzqsa  于 2023-04-13  发布在  .NET
关注(0)|答案(1)|浏览(165)

我目前正在设计一个Angular SPA Web客户端,支持.NET5 REST。它都在同一个Visual Studio项目中,并且构建/运行良好。
我现在正在研究将其作为Windows桌面应用程序分发的可能性。我能够让Electron.NET工作,但它似乎是一个迂回的解决方案(Node?!)。我也不特别喜欢在分布式应用程序中资源是可见/可更改的。
这让我开始研究在WPF中使用WebView 2(微软似乎正在对MSTeams进行类似的过渡。)我发现了一些示例,但它们只用途:
1.仅远程内容(“www.bing.com”)

  1. local content, but only img / html / etc
  2. postmessage等来使用自定义对象进行通信。
    这些都不是我想要的。嗯,这不完全正确。我需要#2来加载Angular SPA,但是当WebView 2托管的Angular调用HttpClient时,我希望在主机应用程序中拦截该请求,并将其路由到我的REST控制器。这将允许我保持几乎所有代码的完整性,并可能提供一个更小、更模糊的exe。
    这可能吗?显而易见?我的愿望有根本性的缺陷吗?(这不是第一次)
olmpazwi

olmpazwi1#

Chromium.AspNetCore.Bridge提供了一个解决方案,它使用owin在内存中托管服务器端代码,并提供一个RequestInterceptor来将所有请求干净地中继到“服务器”代码。
上面的链接有工作示例,但很简单:

App.xaml.cs:

private IWebHost _host;
private AppFunc _appFunc;

public AppFunc AppFunc
{
    get { return _appFunc; }
}

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");

    _ = Task.Run(async () =>
      {
          var builder = new WebHostBuilder();

          builder.ConfigureServices(services =>
          {
              var server = new OwinServer();
              server.UseOwin(appFunc =>
              {
                  _appFunc = appFunc;
              });

              services.AddSingleton<IServer>(server);
          });

          _host = builder
              .UseStartup<Startup>()
              .UseContentRoot(Directory.GetCurrentDirectory())
              .Build();

          await _host.RunAsync();
      });            
}

MainWindow.xaml.cs

private AppFunc _appFunc;
public MainWindow()
{
    InitializeComponent();

    Browser.CoreWebView2InitializationCompleted += Browser_CoreWebView2InitializationCompleted;
}

private void Browser_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
    if (e.IsSuccess)
    {
        _appFunc = ((App)Application.Current).AppFunc;
        Browser.CoreWebView2.WebResourceRequested += BrowserWebResourceRequestedAsync;
        Browser.CoreWebView2.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All);
    }
}

private async void BrowserWebResourceRequestedAsync(object sender, CoreWebView2WebResourceRequestedEventArgs e)
{
    var deferral = e.GetDeferral();

    var request = new ResourceRequest(e.Request.Uri, e.Request.Method, e.Request.Headers, e.Request.Content);

    var response = await RequestInterceptor.ProcessRequest(_appFunc, request);

    var coreWebView2 = (CoreWebView2)sender;

    e.Response = coreWebView2.Environment.CreateWebResourceResponse(response.Stream, response.StatusCode, response.ReasonPhrase, response.GetHeaderString());

    deferral.Complete();
}

相关问题