dotnet / MobileBlazorBindings

Experimental Mobile Blazor Bindings - Build native and hybrid mobile apps with Blazor
MIT License
1.2k stars 152 forks source link

Add support for hybrid apps (native UI + web UI in same app) #121

Closed Eilon closed 4 years ago

Eilon commented 4 years ago

Adding support for hybrid app scenarios will enable developers to use Blazor for the Web to build parts of their app. This will be done by using a platform-specific embedded WebView on supported platforms, which will host Blazor web components. This can be mixed with Mobile Blazor Bindings for native portions of the app to enable the Blazor syntax and app model everywhere in the application. This will also help demonstrate how truly awesome Blazor is 😁

We are looking to support these platforms:

And here's an idea of what you can do with it in a WPF app (the same exact app works on all platforms):

image

Here are some previous requests for such a feature that will be closed in favor of this tracking issue:

There will be some follow-up work after the initial change:

Eilon commented 4 years ago

The code is now checked in!

Check out the two samples to learn more about how to use this feature:

Eilon commented 4 years ago

Tagging @jspuij who has been working on https://github.com/jspuij/BlazorWebView and with whom we will be collaborating on this project.

@jspuij , I'm looking forward to working with you more on this project!

Eilon commented 4 years ago

And tagging @SteveSandersonMS whose great work went into this!

Eilon commented 4 years ago

If you want to try it out, please clone the repo & build locally. We will have a preview out soon!

VincentH-Net commented 4 years ago

Great to see hybrid apps with all C# logic and a single markup syntax!

I wonder if the idea of C# Markup could also apply to Blazor HTML? (and therefore this hybrid approach). That could even further simplify the mix - C# for markup and logic, both mobile and web.

So instead of adding a separate HTML-like markup syntax on top of C# like mobile blazor bindings does, go the other way: Add C# HTML markup helpers on top of Blazor. The object model for HTML will be different from the Forms one (same as with Blazor syntax for mobile and web), but devs will be able to use C# + .NET for markup and logic. That means less friction, less cognitive load, no language bridging tools/frameworks/patterns needed.

A bit radical, but so was creating markup in Forms in C# instead of XAML.

jspuij commented 4 years ago

@VincentH-Net, although for F#, elmish already works on .net: https://elmish.github.io/elmish/ IF you want to go the F# way entirely, Bolero is very cool as well, and runs on top of Blazor, with MVU built in: https://fsbolero.io/

redradist commented 4 years ago

@Eilon By some reason I got the following error:

Screenshot_20200702_163728_com companyname hybridapp 1

Also would be nice to add example for Android HibridMessageAppSample

VincentH-Net commented 4 years ago

Thanks @jspuij for pointing out https://fsbolero.io/. Basically I want something for C#, MVU and MVVM, similar to their F#: image

So devs get to select and mix language, pattern and markup syntax any way they like, with maximum skill reuse. I already prototyped this for mobile C# markup in MAUI (top: MVU, bottom: MVVM): image

I will be looking into Bolero to see how they create F# markup in Blazor webassembly, and try a similar approach in C#. That will give devs hot reload of C# Markup with https://www.livesharp.net/

Eilon commented 4 years ago

@redradist - can you share the steps you took when you saw that error? I'm not surprised if there are some threading issues but any info you can provide will help get this fixed.

Eilon commented 4 years ago

@VincentH-Net - I'm working with the .NET MAUI team to do our best to give everybody everything that they need to be productive. For this repo the focus is on using Blazor to author .NET MAUI apps, in addition to the other ways already being planned for .NET MAUI apps (C#-based and XAML-based). In addition to these, do you feel there is a gap that you'd like to see addressed?

redradist commented 4 years ago

@Eilon

@redradist - can you share the steps you took when you saw that error? I'm not surprised if there are some threading issues but any info you can provide will help get this fixed.

I did nothing special, just compiled and run on my Android device and saw such screen

jspuij commented 4 years ago

@Eilon @redradist I will spend some time on this this weekend. Very busy week sorry.

Eilon commented 4 years ago

@redradist I am able to reproduce this issue now in my Android emulator. It might be a simple fix to switch to the right thread. I will post here when I learn more.

Eilon commented 4 years ago

@redradist it looks like it was an easy fix: https://github.com/xamarin/MobileBlazorBindings/commit/d835416246b1d2ac5079dd8ffdbeb4bf2dd1cc1e

If you pull the latest changes, hopefully you'll see it working on Android now!

redradist commented 4 years ago

@Eilon Now it works, thanks !!

But there are compilation errors for projects other than HybridAppSample

redradist commented 4 years ago

@Eilon

@redradist it looks like it was an easy fix: d835416

If you pull the latest changes, hopefully you'll see it working on Android now!

I also think that HybridApp should reference to Blazor WebAssembly project, because it is easier to integrate and maintain Web Client and HybridApp

Eilon commented 4 years ago

@redradist thank you for the feedback. There should be no need for Web Assembly because the app code already runs as 100% C# code! There is a tiny bit of JS code just to communicate between the WebView browser components and the rest of the app, but the user doesn't write any code that is run as WASM/JS. Please let me know if you have additional thoughts on this.

Also, I just added the Android version of HybridMessageApp! Check it out in this commit: https://github.com/xamarin/MobileBlazorBindings/commit/0effaabc2e915bd3280b955527ba51b6281d1896

Can you share which compilation errors you're seeing in the app? I sometimes do a git clean -xdf or a Rebuild in VS to ensure that old content isn't messing things up. Unfortunately I also sometimes have problems getting things to compile and I have not been able to figure out what is causing it.

redradist commented 4 years ago

@Eilon

@redradist thank you for the feedback. There should be no need for Web Assembly because the app code already runs as 100% C# code! There is a tiny bit of JS code just to communicate between the WebView browser components and the rest of the app, but the user doesn't write any code that is run as WASM/JS. Please let me know if you have additional thoughts on this.

Also, I just added the Android version of HybridMessageApp! Check it out in this commit: 0effaab

Can you share which compilation errors you're seeing in the app? I sometimes do a git clean -xdf or a Rebuild in VS to ensure that old content isn't messing things up. Unfortunately I also sometimes have problems getting things to compile and I have not been able to figure out what is causing it.

@Eilon I mean the I do not want to copy my Blazor WebAssembly project in MobileBinings ... From my point of view would be good the following structure of the projects: BlazorWebAssembly HibridApp // Referenced to BlazorWebAssembly ASP.NET // For API for BlazorWebAssembly and HibridApp Android // Referenced to HibridApp iOS // Referenced to HibridApp

image

I do not want to copy part in Red Rectangle from Blazor WebAssembly to HybridApp

As for me it would be nice if Blazor WebAssembly would be shared between Web App and HybridApp

redradist commented 4 years ago

@Eilon Below I have attached screen with errors: image

Eilon commented 4 years ago

@redradist ah I see, you want to share the same components/pages you have in your Blazor Web App also in your Blazor Hybrid App? I've been talking to @jspuij about what would need to happen to make this work. It probably doesn't work well right now, but I think it's definitely something we want to have good support for!

As for the errors:

  1. For the macOS project, unless you're building on a Mac (which you aren't), right-click on the two macOS projects and select Unload. This will prevent those errors from appearing.
  2. For the Android projects, I will take a look at those. I've seen the first 2 errors (Weather app) before, and I thought I fixed it, but it keeps coming back ☹️ For the 2nd two errors (Todo app), I've never seen that before. Did you try cleaning the project and/or closing VS and doing a git clean -xdf?
Eilon commented 4 years ago

I submitted a fix for the Android Weather app resource issue. Apparently the fix is to not check them in, thus avoiding it breaking all the time when other things change. The resource file will be auto-generated on each build.

But if you can let me know more about the last 2 Android resource issues in the Todo app and I will try to investigate.

redradist commented 4 years ago

@redradist ah I see, you want to share the same components/pages you have in your Blazor Web App also in your Blazor Hybrid App? I've been talking to @jspuij about what would need to happen to make this work. It probably doesn't work well right now, but I think it's definitely something we want to have good support for!

As for the errors:

  1. For the macOS project, unless you're building on a Mac (which you aren't), right-click on the two macOS projects and select Unload. This will prevent those errors from appearing.
  2. For the Android projects, I will take a look at those. I've seen the first 2 errors (Weather app) before, and I thought I fixed it, but it keeps coming back frowning_face For the 2nd two errors (Todo app), I've never seen that before. Did you try cleaning the project and/or closing VS and doing a git clean -xdf?

@Eilon I think if it is possible to share webassembly without coping in this repo https://github.com/Daddoon/BlazorMobile than it should be possible to do

One advantage of this is that WebView version could be developed independent of Mobile and Browser versions

It would be also nice to have ability to use API from razor pages (maybe it is possible already I have not checked) and also to know on which platform code is running (Browser or WebView like in repo above)

jspuij commented 4 years ago

@redradist What @Eilon is referring to, is that the current version of the WebView in MobileBlazorBindings does not yet support Static Web Assets in Razor Class Libraries. However, you can probably get it to work now if you want by roughly following the first part of this tutorial: https://jspuij.github.io/BlazorWebView.Docs/pages/prepare.html

This will take the parts out of a WebAssembly project and move them to a shared RCL library. You will probably need the EmbeddedFileProvider that @Eilon uses to add the wwwroot folder to the shared assembly, for as long as Static Web Assets are not supported yet.

Full support for Static Web Assets will come, this is a very first preview.

Regarding support for razor pages: There is no webserver (just a handler that intercepts the Http Requests from the browser), there is no ASP.NET core, so I'm not sure how you'd see Razor Pages working together with Blazor in this instance. This is the fundamental difference between this solution and BlazorMobile: BlazorMobile runs a web server internally.

I'd advise against platform detection. If you're the end developer you can set a variable with the platform yourself depending on the entry point of the application (every platform has it's own main method) or a preprocessor constant. When you're a library developer you really should be doing feature detection instead of platform detection. E.g. webassembly does not support threading yet. You could try and detect the Mono runtime to determine that you're running webassembly, but this has two disadvantages:

So it's better to try and create a thread and catch the exception, or detect threading support some other way, instead of relying on the platform.

However if you do want to detect the platform there is: https://docs.microsoft.com/en-us/xamarin/essentials/device-information?tabs=ios

redradist commented 4 years ago

@jspuij

@redradist What @Eilon is referring to, is that the current version of the WebView in MobileBlazorBindings does not yet support Static Web Assets in Razor Class Libraries. However, you can probably get it to work now if you want by roughly following the first part of this tutorial: https://jspuij.github.io/BlazorWebView.Docs/pages/prepare.html

This will take the parts out of a WebAssembly project and move them to a shared RCL library. You will probably need the EmbeddedFileProvider that @Eilon uses to add the wwwroot folder to the shared assembly, for as long as Static Web Assets are not supported yet.

Full support for Static Web Assets will come, this is a very first preview.

The repo https://github.com/Daddoon/BlazorMobile already supports Static Files that was added to *.zip file according this tutorial https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/webview?tabs=windows

I hope you will add it, it'll simplify working with Web version and Mobile version

Regarding support for razor pages: There is no webserver (just a handler that intercepts the Http Requests from the browser), there is no ASP.NET core, so I'm not sure how you'd see Razor Pages working together with Blazor in this instance. This is the fundamental difference between this solution and BlazorMobile: BlazorMobile runs a web server internally.

By Razor Pages I mean Blazor Pages ;)

I'd advise against platform detection. If you're the end developer you can set a variable with the platform yourself depending on the entry point of the application (every platform has it's own main method) or a preprocessor constant. When you're a library developer you really should be doing feature detection instead of platform detection. E.g. webassembly does not support threading yet. You could try and detect the Mono runtime to determine that you're running webassembly, but this has two disadvantages:

* iOS, macOS and Android in a hybrrid app also use Mono. So this solution will incorrectly assume that it runs on webassembly for these platforms.

* Some day WebAssembly will support threads, and then you will have to update your code because it assumed that threads are unavailable on a platform.

So it's better to try and create a thread and catch the exception, or detect threading support some other way, instead of relying on the platform.

However if you do want to detect the platform there is: https://docs.microsoft.com/en-us/xamarin/essentials/device-information?tabs=ios

I need platform detection to know what API I can call from Blazor Pages ( Mobile is available ?? ) At least I want to know if Mobile or Browser version

Take a look how it was done in https://github.com/Daddoon/BlazorMobile , it is pretty clear and straightforward, I can call from Blazor page Xamarin.Essential API or other (like Xamarin.Forms) that is available to me

jspuij commented 4 years ago

I need platform detection to know what API I can call from Blazor Pages ( Mobile is available ?? ) At least I want to know if Mobile or Browser version

You really don't. You can set an App.Mobile static boolean on true from the mobile entry point, and don't set it from the webassembly entry point. But it would be better to create a class "SupportedFeatures", add a property "GeoLocation" to it, and set it to true or false depending on detection, or constant at the start of the application. Or you can do a little fancier and register different services for the same interface depending on the platform in the DI container.

Take a look how it was done in https://github.com/Daddoon/BlazorMobile , it is pretty clear and straightforward, I can call from Blazor page Xamarin.Essential API or other (like Xamarin.Forms) that is available to me.

Yes, and it calls the Xamarin platform detection internally:

https://github.com/Daddoon/BlazorMobile/blob/c4a7bf1084120bb9fef0813348f3b75bbccdf9d6/src/BlazorMobile/Services/BlazorXamarinDeviceService.cs

and if it does not detect a mobile or desktop platform, it assumes webassembly or SSB:

https://github.com/Daddoon/BlazorMobile/blob/f73bc35cd674a71dbc095cdafa7b98412fc2faed/src/BlazorMobile.Web/Components/BlazorMobileComponent.cs#L73-L77

However it's fundamentally the wrong approach. It seems simple at first, but you will tie the availability of a feature to a specific platform. Then when a platform gains the capability, you find yourself checking 100 pages where you have if statements or switch statements depending on the platform.

Eilon commented 4 years ago

Using DI to inject different services on each platform is my default recommendation. There might be cases where it doesn't work, but I expect those to be relatively rare. You can learn about backend-specific services here: https://docs.microsoft.com/en-us/mobile-blazor-bindings/advanced/backend-specific-services and apply similar logic in your apps.

VincentH-Net commented 4 years ago

@VincentH-Net - I'm working with the .NET MAUI team to do our best to give everybody everything that they need to be productive. For this repo the focus is on using Blazor to author .NET MAUI apps, in addition to the other ways already being planned for .NET MAUI apps (C#-based and XAML-based). In addition to these, do you feel there is a gap that you'd like to see addressed?

Thanks @Eilon , my apologies for my late reaction - I first wanted to compare Mobile Blazor Bindings to C# Markup hands-on. I did that in this blog post C# Markup versus Mobile Blazor Bindings in .NET MAUI.

The comparison may be valuable for devs looking into either. This is what it looks like: MBBvsCSM

The gap I'd like to see addressed is create C# Markup for regular Blazor, so MAUI developers can also build web apps and hybrid apps with all C# markup. That is not a topic for this repo, I agree. Eager to see how this will all pan out

Eilon commented 4 years ago

Ah, I think I see. So you want Blazor-style programming, but from C#, not markup? I think that's an interesting idea. I agree this isn't the repo for it because this is all about using existing Blazor for native and hybrid scenarios. I think creating an issue or discussion on https://github.com/dotnet/aspnetcore would be a great place to gather broader input on that idea.

Eilon commented 4 years ago

And, I would add that, generally speaking, any feature that Blazor itself gets, would pretty much "just work" in Mobile Blazor Bindings. We don't really customize Blazor at all - we just plug into its existing build/compilation system and its component system. It's just that the components are native, not HTML (but Blazor doesn't care).

Eilon commented 4 years ago

I'm closing this issue now that the main feature is code complete and checked in. There are also new templates, and we'll have new docs to go along with it. Stay tuned for the upcoming release!

VincentH-Net commented 4 years ago

And, I would add that, generally speaking, any feature that Blazor itself gets, would pretty much "just work" in Mobile Blazor Bindings. We don't really customize Blazor at all - we just plug into its existing build/compilation system and its component system. It's just that the components are native, not HTML (but Blazor doesn't care).

@Eilon Interesting. You must know your way around the Blazor architecture quite well. Would you be in for it if I contact you in a month or so, see if you can give me some pointers?

Eilon commented 4 years ago

@VincentH-Net - all the work here is from sitting atop the shoulders of giants! I've learned a thing or two along the way, though. Feel free to contact me at elipton !at! microsoft.com.