I am making Rhino plugins with Single Page Applications web apps for UIs inside a Eto.WebView. These UI need a local server to run properly, and so far I have been successful with a basic System.Net.Http server where I coded all the functionalities myself (GET, POST, MIME types serving, etc).
But this approach has its limits, and I set myself up to try to create a proper ASP.NET server.
Unfortunately, the slightest mention of any type or method from the Microsoft.NET.Sdk.Web shared framework causes a System.IO.FileNotFound exception for the Microsoft.AspNetCore assembly (see picture). This is not a regular package reference issue, because as mentioned in this documentation page the NuGet packages for ASP.NET are almost all depreciated and are now part of the shared framework.
Add the FrameworkReference property → Did not change anything
Change the property to → Cannot build the library because it identifies the project as an application/service and needs an executable entry (Main function)
Created a full blank Rhino Plugin project with the VS template, to which I added a few lines that called ASP.NET data types. Combined with the two changes above → Rhino still cannot find the assembly and SDK.
Created a full blank ASP.NET Web App project with the newest VS template, to which I added only the needed part to make it compile as a .rhp Rhino plugin. → Rhino still cannot find the assemblies
Disabled global and implicit using statements to make sure I have access to the right namespaces, I am able to find the shared framework without issues.
Added true property to the project file, did not change anything.
Added a single environment target (i.e win64) during publishing → does not change anything.
So my question is :
Is it even possible to use ASP.NETinside of Rhino? If yes, how?
Open to any suggestions on how to solve this, or on similar workflows that could work and still be more scalable than a hand-written C# HTTP server.
You are right, both the WebView from Eto or WPF directly can load static web pages.
These threads have discussed it at length, and we had no problem reproducing it :
That is, with static web pages.
When we tried using compiled Single-Page-Applications that rely on React or Vue, we have not managed to get the WebView to load it properly on its own. It was mostly struggling with file serving and routing. Those framework use client-side routing, Server-Side rendering, etc, which are a hassle (when possible) with WebView.
There are other advantages to running our own server, mostly being a proper way to define controller endpoints for requests. Every example for static pages were using the WebView.DocumentLoading or similar events to basically list out all different interactions, which isn’t optimal.
Are there any example on how using web frameworks can be done differently that creating our own server ?
@fraguada Thank’s a lot for that reference, it was very helpful !
Using CEF is a very nice approach, much more straightforward and versatile compared to my embedded server method.
I’ve managed to reproduce it inside a fresh new plugin when targeting net48, but not with net7.0.
Rhino can load the same exact plugin built for .NET Framework 4.8 just fine, but when trying to load / debug the net7.0-windows version it instantly crashes upon loading CefSharp.dll with no further explanation.
Here’s an extract of the debugging output :
I made sure that the proper DLL are exported to the net7.0-windows build folder, since CefSharp has regular packages and netcore packages for net5.0+. See .csproj properties below.
I also tried in a plugin that has no references to the net48 packages at all, to no avail.
*<!-- Package References -->*
*<ItemGroup>*
* <PackageReference Include="chromiumembeddedframework.runtime" Version="126.2.18" />*
* <PackageReference Include="chromiumembeddedframework.runtime.win-x64" Version="126.2.18" />*
* <PackageReference Include="chromiumembeddedframework.runtime.win-x86" Version="126.2.18" />*
* <PackageReference Include="RhinoCommon" Version="8.9.24194.18121" IncludeAssets="compile;build" />*
* <PackageReference Include="System.Drawing.Common" Version="8.0.7" />*
*</ItemGroup>*
*<!-- Different CEF Packages depending and making sure the needed .DLL and .EXE are in the output dir. -->*
*<ItemGroup Condition="'$(TargetFramework)' == 'net7.0-windows'">*
* <PackageReference Include="CefSharp.Common.NETCore" Version="126.2.180" />*
* <PackageReference Include="CefSharp.Wpf.NETCore" Version="126.2.180" />*
*</ItemGroup>*
*<ItemGroup Condition="'$(TargetFramework)' == 'net48'">*
* <PackageReference Include="CefSharp.Common" Version="126.2.180" />*
* <PackageReference Include="CefSharp.Wpf" Version="126.2.180" />*
*</ItemGroup>*
I will be working with the .NET Framework for now, but I wonder if I found a fundamental incompatibility between CefSharp.dll netcore version and Rhino8.
Thanks for your help anyway, let me know if you plan on investigating this
I only used CefSharp up to Rhino 7. I would need to cook up an example with .NET 7.0 but not sure when I will get to that. Another thing to note is that Rhino 8 uses webview 2 which you might be able to leverage instead of using CefSharp. My initial reason for using CefSharp was to support vue and more modern frameworks that were not supported with webview 1. Maybe @curtisw can chime in about that, but I believe if you use an Eto WebView you can leverage the existing libraries and web engine (I believe it would be Edge on Windows) and not have to rely on CefSharp.
@fraguada I found the solution for CefSharp and NET 7.0, it is cause by the CEF cache location that needs to be overridden. Otherwise, the browser runs as a singleton process and conflicts with Rhino, cause startup crash.
I tried and reviewed the different WebView options before. You are right, Rhino8 has an updated Eto.WebView control that leverages WebView2 and is compatible with modern web pages.
This was our current workflow before I looked into other options, leading me to write here.
Eto :
Unfortunately using the new Eto.WebView control is not backwards compatible with Rhino7, where the default browser is Internet Explorer 7. Trying to make the Eto control load a more recent browser (Edge being installed by default since Win10) is possible, but I personally never got it to work. Also, there is a method to excecute JavaScript in the view, but no ways of doing anything like DataBinding in CefSharp. Or did I miss that completely?
WebView2 :
For the WPF WebView2 control from Microsoft, I found dealing with checking that the runtime is properly installed on the end-user machine more tricky than the benefits it offers, as well as some other issues. Additionally, binding .NET entities with WebView2 is not as straightforward as it is with CefSharp, but this could be my preference only.
In the end CefSharp is working very well currently, including multi-targeting for .NET Framework and NET 7. The only trick I had to resort to was to use their CefSharp.Wpf.HwndHost browser control instead of the native WPF implementation, which sadly has terrible performance.