Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set up Photino for .NET 8 Blazor Web App? #108

Open
SommerEngineering opened this issue Jan 21, 2024 · 5 comments
Open

How to set up Photino for .NET 8 Blazor Web App? #108

SommerEngineering opened this issue Jan 21, 2024 · 5 comments
Labels
All OS bug Something isn't working

Comments

@SommerEngineering
Copy link

I have tried to run a .NET 8 Blazor Web App (the new templates added with the .NET 8 release) with Photino.Blazor. Unfortunately, without success so far. Therefore, I have built a minimal working example (MWE): https://devops.tsommer.org/mwe/issues/net8blazor

I have two projects: PhotinoApp and WebApp. The WebApp project is the official .NET 8 template for web apps with minimal changes (simplifications for the MWE). This works perfectly in the local browser.

The PhotinoApp project is also the same template, but with the necessary Photino.Blazor adaptations. Here is, what I have done:

  • Changes in PhotinoApp.csproj:
    • I added <OutputType>WinExe</OutputType>
    • I added this:
       <ItemGroup>
          <Content Update="wwwroot\**">
              <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
          </Content>
      </ItemGroup>
  • Sure, I added the Photino.Blazor package (v2.7.0)

Finally, I changed the Program.cs from this ...

using WebApp.Components;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.WebHost.UseWebRoot("wwwroot").UseStaticWebAssets();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();

... to this ...

using Photino.Blazor;
using UI.Components;

namespace UI;

public class Program
{
    [STAThread]
    public static void Main(string[] _)
    {
        var builder = PhotinoBlazorAppBuilder.CreateDefault();
        builder.Services.AddRazorComponents()
            .AddInteractiveServerComponents();
        
        builder.RootComponents.Add<App>("app");
        
        var app = builder.Build();
        var window = app.MainWindow;
        window.Title = "Title";
        
        AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
        {
            window.ShowMessage("Fatal exception", error.ExceptionObject.ToString());
        };
        
        app.Run();
    }
}

The result looks like this:
Screenshot 2024-01-21 at 16 49 52

The logging shows this:

Photino.NET: "Photino".SetTitle(Photino.Blazor App)
Photino.NET: "Photino.Blazor App".SetUseOsDefaultSize(False)
Photino.NET: "Photino.Blazor App".SetUseOsDefaultLocation(False)
Photino.NET: "Photino.Blazor App".SetWidth(1000)
Photino.NET: "Photino.Blazor App".SetHeight(900)
Photino.NET: "Photino.Blazor App".SetLeft(0)
Photino.NET: "Photino.Blazor App".SetTop(100)
Photino.NET: "Title".Load(/)
Photino.NET: "Title" ** File "/" could not be found.
Photino.NET: "Title".Load(app://localhost/)
Inspection is enabled by default for process or parent application with 'com.apple.security.get-task-allow' entitlement linked against old SDK. Use `inspectable` API to enable inspection on newer SDKs.
2024-01-21 16:49:31.604 dotnet[22308:3715586] void * _Nullable NSMapGet(NSMapTable * _Nonnull, const void * _Nullable): map table argument is NULL

Can anyone help me with this 😀 ? Has anyone gotten the new .NET 8 Web App template to work with Photino?

Should we solve the issue, we could directly add a new example project to the Photino.Blazor repo so that other users can find the solution more easily and quickly.

@ottodobretsberger ottodobretsberger added bug Something isn't working All OS labels Feb 1, 2024
@ottodobretsberger
Copy link
Contributor

Thank you for reporting this. I have added this to our backlog of issue to investigate.

@MikeYeager
Copy link
Collaborator

@SommerEngineering We noticed that your sample doesn't have an index.html page in wwwroot. You'll notice that all of our samples (located in the Photino.Blazor project) have one that helps bootstrap Blazor. The most basic version of that file is this:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <base href="/" />
</head>
<body>
    <app>Loading...</app>
    <script src="_framework/blazor.webview.js"></script>
</body>
</html>

That will take care of the immediate issue. Beyond that, there is still a problem with these lines:

        builder.Services.AddRazorComponents()
            .AddInteractiveServerComponents();

I'm not a Blazor guru by any stretch, but I can't see why you'd want to run Blazor in server mode inside of Photino. By default, the builder sets up for desktop mode. I tried a few things to add server support as well, just for fun, but I wasn't able to get it working. Here is what the default builder does:

       public static PhotinoBlazorAppBuilder CreateDefault(string[] args = default)
       {
           // 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.
           // var jsRuntime = DefaultWebAssemblyJSRuntime.Instance;
           var builder = new PhotinoBlazorAppBuilder();
           builder.Services.AddBlazorDesktop();

           // 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
           // in the future, while giving `new BlazorDesktopHostBuilder` as an opt-out of opinionated
           // settings.
           return builder;
       }

and the default Build():

       public PhotinoBlazorApp Build(Action<IServiceProvider> serviceProviderOptions = null)
       {
           // register root components with DI container
           // Services.AddSingleton(RootComponents);

           var sp = Services.BuildServiceProvider();
           var app = sp.GetRequiredService<PhotinoBlazorApp>();

           serviceProviderOptions?.Invoke(sp);

           app.Initialize(sp, RootComponents);
           return app;
       }

@SommerEngineering
Copy link
Author

Thanks for the response, @MikeYeager and @ottodobretsberger.

We noticed that your sample doesn't have an index.html page in wwwroot.

That's right: I strictly followed the new template from Microsoft for .NET 8. The new Blazor web app template from Microsoft does not use index.html. When you look at the App.razor file, you will see that Microsoft has inserted the content of index.html (with some changes) there. I was surprised myself when I saw this 😀.

I can't see why you'd want to run Blazor in server mode inside of Photino. By default, the builder sets up for desktop mode.

I don't know, either. As I said, I have only tried to get the Microsoft template for .NET 8 to run with Photino. The desktop mode will then probably fit 👍 .

I tried a few things to add server support as well, just for fun, but I wasn't able to get it working.

Thanks for trying it out. Having the standard .NET 8 template for "Web Apps" work with Photino would certainly lower the barrier to entry for many potential users.

As you may have seen, I have now got the .NET 8 web app running with Photino.NET. For this purpose, I added another project to the solution. This worked wonderfully by running the web server asynchronously. With a CancellationTokenSource I can then terminate the web server when the Photino window has been closed. Here is all the code in the Program.cs:

using System.Drawing;
using PhotinoNET;
using PhotinoNetApp.Components;

//
// Standard .NET 8 template for web apps:
//
var builder = WebApplication.CreateBuilder();

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.WebHost.UseWebRoot("wwwroot");
builder.WebHost.UseStaticWebAssets();

// I specified the URL with a port:
builder.WebHost.UseUrls("http://localhost:5000");

var app = builder.Build();

app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

//
// End of standard template
//

// Using a cancellation token source, so we can exit the web server later:
using var webServerCancellation = new CancellationTokenSource();

// Run the webserver async in the background (no await used here):
var webServerTask = app.RunAsync(webServerCancellation.Token);

// Create the Photino window:
var window = new PhotinoWindow()
    .SetTitle("Test App")
    .SetUseOsDefaultSize(false)
    .SetSize(new Size(1024, 900))
    .Center()
    .SetResizable(true)

    // ... and load the web content at the URL / port:
    .Load("http://localhost:5000");

// Wait until the Photino window was closed:
window.WaitForClose();

// Cancel the webserver using the token:
webServerCancellation.Cancel();

// Wait for the server to stop:
await webServerTask;

@RaySinner
Copy link

I'm also really looking forward to a solution to this problem.

@Jinjinov
Copy link

I know that this doesn't solve your problem, but my Photino Blazor app runs with .NET 8

https://github.com/Jinjinov/OpenHabitTracker

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
All OS bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants