Alexandre
Alexandre

Reputation: 7232

Hosting Razor pages and API (AspnetCore) inside a WPF dotnet core project

dotnet core 3 is out! So, I need to host aspnetcore inside a WPF application.

Tried this approach but since VS uses csproj Project node to determine the output, it doesn't work.

There is two nuget packages that called my attention:

Microsoft.AspNetCore.Mvc.Razor.Extensions

AND

Microsoft.Extensions.Hosting

But have no idea how to implement this on WPF :(

Any clues?

Upvotes: 1

Views: 2066

Answers (2)

Jacqueline Loriault
Jacqueline Loriault

Reputation: 700

this is actually pretty easy to do, I have done it with a twitch bot I am building you need to have both a wpf and a asp.net core website in the solution. add a project reference to your asp.net core website and right click the project and under settings change it from console app to Class libary. back in your wpf app in the App.xaml.cs code file you need to override the OnStartup and from there launch your webserver. its a little tricky at first but it works well when setup. there is one side effect to this tho and that is the wwwroot folder from the web app does not get copied at build time so you need to either manully copy it or use a post build event in the web app. this is my post build event as an example:

xcopy /E /Y "$(ProjectDir)wwwroot" "F:\Repos\StreamTools\ControlCenter\bin\Debug\netcoreapp3.1\wwwroot"

this is my App.xaml.cs :

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StreamTools.Core;
using System.Diagnostics;
using System.Windows;

namespace StreamTools.ControlCenter
{
    public partial class App : Application
    {
        private IHost webHost;

        protected override void OnStartup(StartupEventArgs e)
        {
            webHost = Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(builder => builder.UseStartup<Web.Startup>())
                .ConfigureAppConfiguration(configBuilder =>
                {
                    configBuilder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
                    configBuilder.AddEnvironmentVariables();
                    if (Debugger.IsAttached)
                    {
                        configBuilder.AddUserSecrets<App>();
                    }
                })
                .Build();
            webHost.StartAsync();
            webHost.Services.GetService<IHostApplicationLifetime>().ApplicationStopping.Register(OnAppStopping);
        }

        private void OnAppStopping()
        {
            webHost.Dispose();
        }

        protected override void OnExit(ExitEventArgs e)
        {
            webHost.StopAsync();
            base.OnExit(e);
        }
    }
}

Due to the way kestrel works I'm not sure if its a bug or how its just built you have to wire up the IHostApplicationLifetime and force call to the dispose method. without that event trap closing the wpf app will not stop the web server. I have not found any other option for that part.

if you want to get really fancy, you can also use SignalR for a bit of IPC communication between the wpf app and the web server. thats what I do so when messages from the bot come in they can be displayed on the page which is used in my case as an obs source for stream notifications etc.

Hope this helps you out. and happy coding

Upvotes: 3

James Finch
James Finch

Reputation: 11

With WPF you can use a WebBrowser element set to the URL of your ASP.NET hosted location (localhost I'm assuming in this case). Make sure to use kestrel standalone and not IIS. I may be misunderstanding your question, but you would essentially be using WPF as a shell to display your ASP.NET web app. Not unlike what a web browser does. You would not actually be hosting from WPF.

Upvotes: 1

Related Questions