In-Depth

Edit Local Images/Text from a .NET MAUI Blazor Hybrid App

Blazor code can now browse local file systems and open up local files and edit them in native Windows apps.

With .NET 6 and the latest Visual Studio 2022 preview, developers can create a hybrid Blazor/.NET MAUI app that can work with local machines in ways that ordinary Blazor (web) apps can't.

Blazor code can now browse local file systems and open up local files and edit them in native Windows apps, for example. This couldn't be done before in Blazor because it runs in the JavaScript security context, with limited access to underlying platform resources like the file system.

What's more, native UI can be mixed and matched with Blazor UI (displayed in a BlazorWebView control) in a hybrid Blazor/.NET MAUI app, which is actually a capability dating back to experimental Mobile Blazor Bindings from a couple years ago. Back in June of last year, Microsoft's Eilon Lipton, who worked on the Mobile Blazor Bindings project, explained how that effort led to Microsoft execs granting permission to "productize" that project and bake the functionality into .NET MAUI.

Mixing and Matching Native and Web UI
[Click on image for larger view.] Mixing and Matching Native and Web UI (source: Microsoft).

Since then, the tech has been fine-tuned, and Microsoft's Daniel Roth introduced the new .NET.MAUI/Blazor hybrid mobile/desktop capabilities with the debut of .NET 6 in November 2021 in a video titled ".NET MAUI Blazor - Build Hybrid Mobile, Desktop, and Web apps."

Here's how the program manager on the ASP.NET team described the idea:

Blazor enables building client-side web UI with .NET, but sometimes you need more than what the web platform offers. Sometimes you need full access to the native capabilities of the device. You can now host Blazor components in .NET MAUI apps to build cross-platform native apps using web UI. The components run natively in the .NET process and render web UI to an embedded web view control using a local interop channel. This hybrid approach gives you the best of native and the web. Your components can access native functionality through the .NET platform, and they render standard web UI. .NET MAUI Blazor apps can run anywhere .NET MAUI can (Windows, Mac, iOS, and Android) although our primary focus for .NET 6 is on desktop scenarios.

.NET MAUI, however, "slipped the schedule" and didn't debut with .NET 6 last November, instead being re-targeted for a Q2 2022 debut. That means a VS 2022 preview needs to be used.

To put this new functionality through its paces, I used Microsoft Visual Studio Community 2022 Version 17.1.0 Preview 2.0, which features three .NET MAUI offerings: a regular .NET MAUI app, a Blazor .NET MAUI app and a class library:

.NET MAUI Preview Options
[Click on image for larger view.] .NET MAUI Preview Options

You can use the Visual Studio Installer to make sure your version supports .NET MAUI previews:

VS 2022 Installation Details
VS 2022 Installation Details

With that all in place, I created a new .NET MAUI Blazor app and worked up some quick-and-dirty examples of the new functionality dealing with:

  • Editing images in Microsoft Paint
  • Editing text in the word processor of your choice: Notepad, WordPad, Notepad++ and so on
  • Opening local folders
  • Opening and saving files to local filesystem

Here's what the app looks like, building on the stock Blazor template:

Testing App
[Click on image for larger view.] Testing App

Roth's video demoed the functionality in both an Android app and a desktop app. As I would rather suffer a root canal than mess with an Android emulator on my ancient machine and deal with all that HAXM garbage, I took his word for the Android stuff.

The key to accessing the local resources is the System.Diagnostics.Process.Start method, which he used to display text he got from Notepad in the file system right in his native client application. "Can't do that from a web application!" he exclaimed. Here's his code:

<button @onclick="GetMessage">Edit</button>
<p>@message</p>

@code {
  string message = "Hello!";

  void GetMessage() 
  {
    var file = Path.GetTempFileName();
    File.WriteAllText(file, "Enter message here");
    var p = System.Diagnostics.Process.Start("notepad", file);
    p.WaitForExit();
    message = File.ReadAllText(file);
  }
}

You can use System.Diagnostics.Process.Start to directly start executable (.exe) files in the C:\Windows\System32 folder, which includes programs like Notepad (notepad.exe), Microsoft Paint (mspaint.exe) and WordPad (write.exe) for working with local files, like this:

System.Diagnostics.Process.Start("mspaint");

Note that while I'm dealing with programs that access the local file system, you can also start other programs, like Calculator (calc.exe). For executable files in other folders, you have to provide the path.

Following are code snippets I used to demo the functionality listed above.

Editing Images
In my contrived quick-and-dirty examples, I simply pointed a variable to the local resource I wanted to use and supplied the variable as the second parameter in the Process.Start method (with the first parameter being the executable file):

<div>
  <img src="/images/image1.jpg" @onclick="EditImage1"/>
  <button @onclick="EditImage1">Edit this Image in Microsoft Paint<button>
</div>

@code {
  private void EditImage1()
  {
    var file1 = 
      @"C:\Users\david\source\repos\NewMauiBlazorApp\NewMauiBlazorApp\wwwroot
      \images\image1.jpg";
    System.Diagnostics.Process.Start("mspaint", file1);
  }
}

Editing Text
Opening the text editor of your choice is simple. If it's in the System32 folder, you just need:

System.Diagnostics.Process.Start("notepad");

If you want to use the third-party Notepad++ that's installed on your machine, it would be:

System.Diagnostics.Process.Start(@"C:\Program Files\Notepad++\notepad++.exe");

Like Roth showed, you can also grab user-entered text in your app and open it up in a text editor -- in this case WordPad -- like this:

<input type="text" @onchange="nOnInputEvent" />

@directions

@code {

  private string ninputValue = "";
  private string directions = 
    "Type in text and press Enter to edit the text in a WordPad file";
  private void nOnInputEvent(ChangeEventArgs changeEvent)
  {
    var textFile = @"C:\Users\david\source\repos\NewMauiBlazorApp\
      NewMauiBlazorApp\TextFile1.txt";
    ninputValue = changeEvent.Value.ToString();
    File.WriteAllText(textFile, ninputValue);
    System.Diagnostics.Process.Start("write", textFile);
  }
}

While I used an existing text file in my app's folder, you can request a temporary file name, as Roth did in his example above.

Opening a Local Folder
I grabbed some code off the web and ended up with this:

<button @onclick="OpenFolder">Open Folder</button>
@code {
  void OpenFolder()  
  {
    var folder= @"C:\Program Files";
    var oFolder = new System.Diagnostics.ProcessStartInfo() 
    { 
      FileName = folder, UseShellExecute = true 
    };
    System.Diagnostics.Process.Start(oFolder);
  }
}

Opening a Local File
To open up a specific file, you just need to specify the location:

var lFile= @"C:\Program Files\notepad++\readme.txt";

Note that when Process.Start opens a text file with the .txt extension when the app to use it is not specified, it uses the native Notepad app. However, when I simply pointed to an .html file (which my machine is configured to open in Edge by default), Visual Studio told me: "The specified executable is not a valid application for this OS platform."

Of course, all of the above are just proof-of-concept contrivances to illustrate the new functionality in Blazor hybrid apps. But the new capabilities do open up many new real-world possibilities in addition to providing developers with both web and native functionality and letting experienced web-tech devs do desktop stuff in a familiar manner.

Or, as Roth concluded: ".NET MAUI and Blazor combined make it easy to build cross-platform native client apps using your existing web development code and skills. Be sure to give it a try. I think you'll be amazed at what you can build."

A more recent video (Jan. 11) of an ASP.NET Community Standup titled "Blazor WebAssembly on .NET 6" details more things that can be done with Blazor and .NET MAUI. In it, ultimate Blazor guru Steve Sanderson explains that "one of the features of MAUI is that we can add Blazor components to our native desktop applications" and then demonstrates Blazor/WPF functionality.

"The important thing to understand here is this is not going to run Blazor WebAssembly, okay," Sanderson said. "It's going to run the Blazor components, but not under Blazor WebAssembly, not under Blazor Server -- under a different kind of runtime altogether, which is just natively running the Blazor component in the .NET runtime that's already inside this application."

About the Author

David Ramel is an editor and writer at Converge 360.

comments powered by Disqus

Featured

Subscribe on YouTube