The Practical Client
Integrating Blazor and JavaScript Code
It would be great if you could call Blazor C# methods from your JavaScript code. Right now, that's not quite possible: Simply calling Blazor C# from JavaScript won't work (you'll get a message about a call dispatcher not being available).
What you can do, however, is once your Blazor code is running, call JavaScript code from your C# code. Once you've done that, your JavaScript code can, in turn, call Blazor code. This opens up the possibility of leveraging some of your existing JavaScript code from Blazor code -- library routines that call Web Services and return the results to your application might be good candidates.
The major caveat about Blazor: As I noted in my previous column on how to create a basic "Hello, World" Blazor solution, this is all "experimental" technology: use at your own risk. As an example, I got to write this column twice. While in the middle of describing how to integrate JavaScript and C# in Blazor 0.4.0, version 0.5.0 dropped and everything got both a lot easier and a lot different. In Blazor 0.5.0, it's possible to add Blazor to any HTML page, including one generated using server-side code. But the process of integrating JavaScript and C# changed dramatically. It could happen to you, too.
And one last warning: Be aware that this column is all about the technology. The case study in this column does nothing useful (well, except run to completion).
Setting up the Solution
For this case study (as in the last column), I made sure that that all the available updates for Visual Studio and Blazor were applied (including the .NET Core 2.1 SDK and latest Blazor language services). For this case study, I created a new Blazor solution by selecting File > New > Project > ASP.NET Core Web Application, clicking the OK button to display the New ASP.NET Core Web Application dialog and selecting the Blazor application. This gives me a single project, which I called BlazorAndJS.
Writing the JavaScript
Integrating JavaScript and Blazor is a little awkward because you can't add JavaScript to a Blazor C# file. However, you can add JavaScript to the Index.html page under the wwwroot folder in the project. That page (or any HTML page that works with Blazor), now just needs a script tag that references _framework/blazor.webassembly.js. Don't panic that this JavaScript file isn't part of your application -- it's generated as part of building your app (if you turn on Show All Files in Solution Explorer and do a search, you'll find it).
To hold my JavaScript, I added a script element in Index.html to hold my JavaScript code after that webassembly element. As a result, inside my body element, my page first looked like this:
<app>Loading...</app>
<script src="_framework/blazor.webassembly.js"></script>
<script>
</script>
My next step was to add a JavaScript function to my Index.html page to be called from Blazor code. Any JavaScript function will do so I wrote this function that accepts a single parameter (called name) from the Blazor code:
<script>
function SayHelloJS(name) {
In this function, all I'm going to do is call a Blazor method (I said this case study didn't do anything useful).
To call a Blazor method, you use the invokeMethodAsync function of the JavaScript DotNet object. You must pass that method the name of the assembly holding your C# code and the name of the "JavaScript-invokable" static method that you want to call (more on "JavaScript-invokable" later). Following those two parameters, you can pass any parameters required by the C# method -- in this case, I passed my function's name parameter.
Since this method returns a Promise, I can use the then function to specify both what I want done with any data returned from that Blazor method (I chose to display it) and what to do with any error message (again, I've chosen to display it):
DotNet.invokeMethodAsync("BlazorAndJS", "SayHelloCS", name)
.then(data => alert(data), reason => alert(reason));
}
Writing the C# Code
Now it's a matter of writing my C# Blazor code. My first step is to write the C# code that will call my JavaScript function and pass it a name. For that, I followed the same path I used in my previous column and, in my project's Index.cshtml file, overrode its OnInitAsync method.
My Index.cshtml file, therefore, begins like this:
@page "/"
<h1>Hello, World!</h1>
@functions {
protected override async Task OnInitAsync() {
To call a JavaScript method from this C# code, you must use the InvokeAsync method of the IJSRuntime object that's stored in the Current property of the JSRuntime class. That method must be passed the full name of the JavaScript function you want to call and any parameters that the function accepts. In my case, to call my JavaScript function, the C# code looks like this:
await JSRuntime.Current.InvokeAsync<string>("SayHelloJS", "Peter");
}
And, of course, I need the C#, static, JavaScript-invokable SayHello method that my SayHelloJS JavaScript code calls. Making a C# method JavaScript-invokable in Blazor is easy: Just add the JSInvokable attribute to the method.
So, to create my JavaScript-invokable method, I just add this code to my Index.cshtml file, following my override of the OnInitAsync method:
[JSInvokable]
public static string SayHelloCS(string name)
{
return "Hello, " + name;
}
There's more to say here -- you can, for example, call non-static (instance) methods in your C# code from JavaScript and you can return values from JavaScript to C#. I'll look at that functionality in my next column. By that time, no doubt, more will have changed in Blazor <sigh>.
About the Author
Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.