This blog post will show you how to access WebCam in the Blazor application.
To access the web camera from the user machine, we will use the HTML5 video
element and navigator
API of the browser. Using blazor javascript interoperability API, we will invoke the C# method from JavaScript and then call the StateHasChanged method from C#.
See the following image for JavaScript->C# method mapping
As you can see from the above picture, we are using Blazor DotNetObjectReference
class to mediate between JavaScript and C#.
Let's add the javascript file and add the following functions.
Invoke an instance .NET method
To invoke an instance .NET method from JavaScript (JS):
- Pass the .NET instance by referencing JS by wrapping the example in a DotNetObjectReference and calling Create on it.
- Invoke a .NET instance method from JS using
invokeMethodAsync
orinvokeMethod
(Blazor WebAssembly only) from the passed DotNetObjectReference. The .NET instance can also be passed as an argument when invoking other .NET methods from JS. - Dispose of the DotNetObjectReference.
export async function init(videoElementRef, dotnetObjectRef) {
console.log("Init");
try {
var stream = await navigator.mediaDevices.getUserMedia({ video: true });
onSuccess(stream, videoElementRef);
dotnetObjectRef.invokeMethodAsync("OnSuccess");
}
catch (e) {
onFailure(e, dotnetObjectRef)
}
}
function onSuccess(stream, videoElementRef) {
videoElementRef.srcObject=stream;
videoElementRef.play();
}
function onFailure(exception, dotnetObjectRef) {
console.log("Exception occurred", exception);
dotnetObjectRef.invokeMethodAsync("onFailure", exception.message);
}
Here I am using the JavaScript module technique. The above code is self-explanatory; expect the dotnetObjectRef reference, which is blazor class, to interact with C#
@if (!string.IsNullOrEmpty(errorMessage))
{
@errorMessage
}
<video id="video" @ref="VideoElementRef"></video>
Corresponding to JavaScript, I have the C# method as shown below.
@code {
private ElementReference VideoElementRef { get; set; }
private string errorMessage = "";
private string jsModulePath = "./camra.js";
private Task<IJSObjectReference> moduleRef;
[Inject]
private IJSRuntime jSRuntime { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
moduleRef = jSRuntime.InvokeAsync<IJSObjectReference>("import", jsModulePath).AsTask();
var module = await moduleRef;
await module.InvokeVoidAsync("init", VideoElementRef, DotNetObjectReference.Create(this));
}
}
[JSInvokable]
public void OnSuccess()
{
StateHasChanged();
}
[JSInvokable]
public void onFailure(string e)
{
errorMessage = e;
StateHasChanged();
}
}