SlideShare a Scribd company logo
Writing
JavaScript
for C#'s
Blazor
#CODEPALOUSA
Ed Charbeneau
Author:
Sr. Developer Advocate
Progress Software,
Telerik UI for Blazor
“Blazor: A Beginner's Guide” (free)
Тwitter: @EdCharbeneau
Тwitch: Twitch.tv/EdCharbeneau
Why do we need it?
Blazor is really, really, new!
C# Doesn’t have a full API surface for the Browser’s Web APIs
Writing java script for Csharp's Blazor
Why do don’t we need it?
LocalStorage
◦ dotnet add package Blazored.LocalStorage
MediaQueries
◦ dotnet add package BlazorPro.BlazorSize
File Uploads
◦ dotnet add package Telerik.UI.for.Blazor
• Commercial library
.NET 5
◦ SEO support, <Head>
What’s the JavaScript Interop
A Blazor app can invoke JavaScript functions from .NET methods
and .NET methods from JavaScript functions.
How do we do it?
C# API
DotNetObjectReference<T>
◦ Value (T instance)
◦ Dispose()
IJSRuntime
◦ .InvokeAsync<T>(fname, p)
◦ .InvokeVoidAsync(fname, p)
JAVASCRIPT API
DotNetObjectReference
◦ number | string (guid)
◦ invokeMethodAsync(fname, p)
◦ dispose
Parameters & Values must be JSON serializeable
How do we do it?
CONVENTION
Use namespaces
window.namespace.function
window.myFoo = {
doFoo: function() {}
}
UNLESS
The function already exists on the
window object.
window.alert
Parameters & Values must be JSON serializeable
Scenarios
One Way
Round-Trip
Round-Trip Callback
Scenarios: One Way
Invoke JavaScript from C#
Fire and forget
No return value
private readonly IJSRuntime jsRuntime;
private async ValueTask Cancel() =>
await jsRuntime.InvokeVoidAsync($“namespace.functionName“, parameters);
C# JS window.alert
Void
C#
window.namespace = { function: functionName() } JS
Scenarios: Round Trip (C# > JS)
Invoke JavaScript from C#
Return value
C# JS invokeMethod
Value
string name = await js.InvokeAsync<string>("prompt", "What is your name?");
Result = $"Your name is: {name}";
C#
Scenarios: Round Trip (JS >< C#)
[JSInvokable] Attribute
Invoke C# Static Method from JS
JS C# RaiseEvent
Value
[JSInvokable]
[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
Task.FromResult(new int[] { 1, 2, 3 });
returnArrayAsyncJs: function () {
DotNet.invokeMethodAsync(‘namespace', 'ReturnArrayAsync')
.then(data => {
data.push(4);
console.log(data);
});
},
C#
JS
Scenarios: Round-Trip Callback
Invoke JavaScript from .NET
Invoke C# Instance Method from JS
DotNetObjectReference
Dispose, dispose, dispose
C# JS
Function.callbac
k
Value
R
RInstance.method
Scenarios: Round-Trip Callback
public class GeoLocation
{
public async ValueTask GetCurrentPosition(...) =>
await js.InvokeVoidAsync
("blazorGeolocation.getCurrentPosition",
DotNetObjectReference.Create(this), options);
[JSInvokable]
public void RaiseOnGetPosition(Position p) =>
[JSInvokable]
public void RaiseOnGetPositionError(Error err) =>
window.blazorGeolocation = {
getCurrentPosition: function (geolocationRef, options) {
navigator.geolocation
.getCurrentPosition(onSuccess, onError, options);
},
function onSuccess(result) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPosition’,
blazorGeolocation.toSerializeable(result));
};
function onError(er) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPositionError’,
er.code);
};
};
JSC#
Scenarios: Round-Trip Callback
public class GeoLocation
{
public async ValueTask GetCurrentPosition(...) =>
await js.InvokeVoidAsync
("blazorGeolocation.getCurrentPosition",
DotNetObjectReference.Create(this), options);
[JSInvokable]
public void RaiseOnGetPosition(Position p) =>
[JSInvokable]
public void RaiseOnGetPositionError(Error err) =>
window.blazorGeolocation = {
getCurrentPosition: function (geolocationRef, options) {
navigator.geolocation
.getCurrentPosition(onSuccess, onError, options);
},
function onSuccess(result) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPosition’,
blazorGeolocation.toSerializeable(result));
};
function onError(er) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPositionError’,
er.code);
};
};
JSC#
Scenarios: Round-Trip Callback
public class GeoLocation
{
public async ValueTask GetCurrentPosition(...) =>
await js.InvokeVoidAsync
("blazorGeolocation.getCurrentPosition",
DotNetObjectReference.Create(this), options);
[JSInvokable]
public void RaiseOnGetPosition(Position p) =>
[JSInvokable]
public void RaiseOnGetPositionError(Error err) =>
window.blazorGeolocation = {
getCurrentPosition: function (geolocationRef, options) {
navigator.geolocation
.getCurrentPosition(onSuccess, onError, options);
},
function onSuccess(result) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPosition’,
blazorGeolocation.toSerializeable(result));
};
function onError(er) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPositionError’,
er.code);
};
};
JSC#
Scenarios: Round-Trip Callback
public class GeoLocation
{
public async ValueTask GetCurrentPosition(...) =>
await js.InvokeVoidAsync
("blazorGeolocation.getCurrentPosition",
DotNetObjectReference.Create(this), options);
[JSInvokable]
public void RaiseOnGetPosition(Position p) =>
[JSInvokable]
public void RaiseOnGetPositionError(Error err) =>
window.blazorGeolocation = {
getCurrentPosition: function (geolocationRef, options) {
navigator.geolocation
.getCurrentPosition(onSuccess, onError, options);
},
function onSuccess(result) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPosition’,
blazorGeolocation.toSerializeable(result));
};
function onError(er) {
return geolocationRef
.invokeMethodAsync('RaiseOnGetPositionError’,
er.code);
};
};
JSC#
Pub-Sub
JS C#
DOM EventA
DOM EventB
Channel
Component (A)
Component (AB)
Component (B)
Component (AB)
Pub-Sub: Init
JS C#
Channel
Component (A)
.addEventListener
DOM EventA
Pub-Sub: De-dupe
JS C#
Channel
Component (A)
.addEventListener
DOM EventA
DOM EventB Component (AB)
DOM EventA
Pub-Sub: Dispose
JS C#
DOM EventA
DOM EventB
Channel
Component (A)
Component (AB)
Component (B)
Component (AB)
.removeEventListener
.Dispose
Pub-Sub: Developer Experience
JS C#
DOM EventA
DOM EventB
Channel
Component (A)
Component
(AB)
Component (B)
Component
(AB)
<MediaQueryList>
<MediaQuery>
<MediaQuery>
<MediaQuery>
<MediaQuery>
mediaQueryLists: MediaQueryListItem[]
MediaQueryListItem {
id: number | string;
dotnetCallback: (ev: MediaQueryListEvent)
mediaQueries: MediaQueryList[];
}
Component Lifecycle Awareness
SetParametersAsync()
OnInitializedAsync()
OnParametersSetAsync()
OnAfterRenderAsync(bool
firstRender)
ShouldRender()
Avoid JavaScript interop during
Initialization. Because Blazor can
utilize Server rendering, JavaScript
may not be available.
Use OnAfterRenderAsync for
initializing JavaScript.
Tools, testing?
Npm
Jest
TypeScript
Rollup
Typescript
DotNetObjectReference type is number | string (int | guid)
Remove .json files from NuGet Packages
{
"compilerOptions": {
"outDir": "./wwwroot",
"target": "ES6",
"moduleResolution": "node",
"lib": [ "ES2016", "DOM"]
},
"exclude": [
"node_modules",
"wwwroot",
"**/*.test.ts"
]
}
tsconfig.json
_content/Namespace/resource.*
Razor Class Library
Assets go in wwwroot
wwwroot becomes => _content/Namespace/*
Do provide minified and standard formats
Example
<script src="_content/BlazorPro.BlazorSize/blazorSize.min.js"></script>
QUESTIONS
Resources
1. EdCharbeneau.com
• Free Ebook & examples
• GitHub
• Twitter
• Twitch
2. Blogs.Telerik.com

More Related Content

PPTX
Secrets of a Blazor Component Artisan
PDF
jQuery plugin & testing with Jasmine
KEY
Integration Testing With Cucumber How To Test Anything J A O O 2009
PDF
Jumping Into WordPress Plugin Programming
PDF
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
PDF
JavaScript, React Native and Performance at react-europe 2016
PDF
React Native - Getting Started
PDF
ComponenKit and React Native
Secrets of a Blazor Component Artisan
jQuery plugin & testing with Jasmine
Integration Testing With Cucumber How To Test Anything J A O O 2009
Jumping Into WordPress Plugin Programming
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
JavaScript, React Native and Performance at react-europe 2016
React Native - Getting Started
ComponenKit and React Native

What's hot (20)

PDF
How to React Native
KEY
Writing your Third Plugin
PDF
React Native +Redux + ES6 (Updated)
PPTX
Grails Plugin
PDF
So, you want to be a plugin developer?
PDF
An easy guide to Plugin Development
PDF
Functional testing your Grails app with GEB
PDF
Writing Software not Code with Cucumber
PDF
React native
PDF
Play Framework on Google App Engine - Productivity Stack
PPTX
Concurrent Rendering Adventures in React 18
PDF
React Native Workshop - React Alicante
PDF
Front Ends for Back End Developers - Spring I/O 2017
PDF
Lessons from a year of building apps with React Native
PDF
Introduction to Griffon
PDF
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
PDF
Introduction to VueJS & The WordPress REST API
PDF
Taming Functional Web Testing with Spock and Geb
PDF
‘Hello, world!’ application how to dockerize golang application
PDF
Server side rendering with React and Symfony
How to React Native
Writing your Third Plugin
React Native +Redux + ES6 (Updated)
Grails Plugin
So, you want to be a plugin developer?
An easy guide to Plugin Development
Functional testing your Grails app with GEB
Writing Software not Code with Cucumber
React native
Play Framework on Google App Engine - Productivity Stack
Concurrent Rendering Adventures in React 18
React Native Workshop - React Alicante
Front Ends for Back End Developers - Spring I/O 2017
Lessons from a year of building apps with React Native
Introduction to Griffon
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
Introduction to VueJS & The WordPress REST API
Taming Functional Web Testing with Spock and Geb
‘Hello, world!’ application how to dockerize golang application
Server side rendering with React and Symfony
Ad

Similar to Writing java script for Csharp's Blazor (20)

PPTX
Writing JavaScript for C# Blazor.pptx
PDF
Blazor, lo sapevi che...
PPTX
"Hands-on development experience using wasm Blazor", Furdak Vladyslav.pptx
PDF
Blazor certification training - Dot Net Tricks
PPTX
PPTX
Blazor - An Introduction
PDF
Pre-render Blazor WebAssembly on static web hosting at publishing time
PDF
Blazor web apps
PPTX
Codegen2021 blazor mobile
PPTX
Blazor Full-Stack
PDF
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
PPTX
Goodbye JavaScript Hello Blazor
PPTX
Building Web Apps with WebAssembly and Blazor
PDF
Amir Zuker: Building web apps with web assembly and blazor - Architecture Nex...
PPTX
Blazor and Azure Functions - a serverless approach
PPTX
.NET Fest 2018. Dino Esposito. ASP.NET Blazor—the C# Angular or the return of...
PPTX
Blazor.pptx
PDF
Blazor in Action 1st Edition Chris Sainty
PPTX
Full stack web development with c# and web assembly - Blazor.Net
PDF
Blazor in Action 1st Edition Chris Sainty
Writing JavaScript for C# Blazor.pptx
Blazor, lo sapevi che...
"Hands-on development experience using wasm Blazor", Furdak Vladyslav.pptx
Blazor certification training - Dot Net Tricks
Blazor - An Introduction
Pre-render Blazor WebAssembly on static web hosting at publishing time
Blazor web apps
Codegen2021 blazor mobile
Blazor Full-Stack
"Hidden difficulties of debugger implementation for .NET WASM apps", Andrii R...
Goodbye JavaScript Hello Blazor
Building Web Apps with WebAssembly and Blazor
Amir Zuker: Building web apps with web assembly and blazor - Architecture Nex...
Blazor and Azure Functions - a serverless approach
.NET Fest 2018. Dino Esposito. ASP.NET Blazor—the C# Angular or the return of...
Blazor.pptx
Blazor in Action 1st Edition Chris Sainty
Full stack web development with c# and web assembly - Blazor.Net
Blazor in Action 1st Edition Chris Sainty
Ad

More from Ed Charbeneau (16)

PPTX
Blazor Stability Testing Tools for Bullet Proof Applications
PPTX
Secrets of a Blazor Component Artisan (v2)
PPTX
Modernizing Web Apps with .NET 6.pptx
PPTX
Modernizing Web Apps with .NET 6.pptx
PPTX
Razor into the Razor'verse
PPTX
PPTX
Giving Clarity to LINQ Queries by Extending Expressions R2
PPTX
The future of .NET lightning talk
PPTX
Into the next dimension
PPTX
Giving Clarity to LINQ Queries by Extending Expressions
PPTX
What is new in Q2 2015
PPTX
TelerikNEXT What's new in UI for ASP.NET AJAX
PPTX
Journey to JavaScript (from C#)
PPTX
Refactoring css
PPTX
Don't be a stereotype: Rapid Prototype
PPTX
A crash course in responsive design
Blazor Stability Testing Tools for Bullet Proof Applications
Secrets of a Blazor Component Artisan (v2)
Modernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptx
Razor into the Razor'verse
Giving Clarity to LINQ Queries by Extending Expressions R2
The future of .NET lightning talk
Into the next dimension
Giving Clarity to LINQ Queries by Extending Expressions
What is new in Q2 2015
TelerikNEXT What's new in UI for ASP.NET AJAX
Journey to JavaScript (from C#)
Refactoring css
Don't be a stereotype: Rapid Prototype
A crash course in responsive design

Recently uploaded (20)

PDF
KodekX | Application Modernization Development
PDF
cuic standard and advanced reporting.pdf
PDF
Modernizing your data center with Dell and AMD
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Approach and Philosophy of On baking technology
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
A Presentation on Artificial Intelligence
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
KodekX | Application Modernization Development
cuic standard and advanced reporting.pdf
Modernizing your data center with Dell and AMD
Mobile App Security Testing_ A Comprehensive Guide.pdf
MYSQL Presentation for SQL database connectivity
NewMind AI Weekly Chronicles - August'25 Week I
Understanding_Digital_Forensics_Presentation.pptx
“AI and Expert System Decision Support & Business Intelligence Systems”
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Encapsulation_ Review paper, used for researhc scholars
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
NewMind AI Monthly Chronicles - July 2025
Approach and Philosophy of On baking technology
Per capita expenditure prediction using model stacking based on satellite ima...
Review of recent advances in non-invasive hemoglobin estimation
A Presentation on Artificial Intelligence
Diabetes mellitus diagnosis method based random forest with bat algorithm
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Building Integrated photovoltaic BIPV_UPV.pdf
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...

Writing java script for Csharp's Blazor

  • 2. Ed Charbeneau Author: Sr. Developer Advocate Progress Software, Telerik UI for Blazor “Blazor: A Beginner's Guide” (free) Тwitter: @EdCharbeneau Тwitch: Twitch.tv/EdCharbeneau
  • 3. Why do we need it? Blazor is really, really, new! C# Doesn’t have a full API surface for the Browser’s Web APIs
  • 5. Why do don’t we need it? LocalStorage ◦ dotnet add package Blazored.LocalStorage MediaQueries ◦ dotnet add package BlazorPro.BlazorSize File Uploads ◦ dotnet add package Telerik.UI.for.Blazor • Commercial library .NET 5 ◦ SEO support, <Head>
  • 6. What’s the JavaScript Interop A Blazor app can invoke JavaScript functions from .NET methods and .NET methods from JavaScript functions.
  • 7. How do we do it? C# API DotNetObjectReference<T> ◦ Value (T instance) ◦ Dispose() IJSRuntime ◦ .InvokeAsync<T>(fname, p) ◦ .InvokeVoidAsync(fname, p) JAVASCRIPT API DotNetObjectReference ◦ number | string (guid) ◦ invokeMethodAsync(fname, p) ◦ dispose Parameters & Values must be JSON serializeable
  • 8. How do we do it? CONVENTION Use namespaces window.namespace.function window.myFoo = { doFoo: function() {} } UNLESS The function already exists on the window object. window.alert Parameters & Values must be JSON serializeable
  • 10. Scenarios: One Way Invoke JavaScript from C# Fire and forget No return value private readonly IJSRuntime jsRuntime; private async ValueTask Cancel() => await jsRuntime.InvokeVoidAsync($“namespace.functionName“, parameters); C# JS window.alert Void C# window.namespace = { function: functionName() } JS
  • 11. Scenarios: Round Trip (C# > JS) Invoke JavaScript from C# Return value C# JS invokeMethod Value string name = await js.InvokeAsync<string>("prompt", "What is your name?"); Result = $"Your name is: {name}"; C#
  • 12. Scenarios: Round Trip (JS >< C#) [JSInvokable] Attribute Invoke C# Static Method from JS JS C# RaiseEvent Value [JSInvokable] [JSInvokable] public static Task<int[]> ReturnArrayAsync() Task.FromResult(new int[] { 1, 2, 3 }); returnArrayAsyncJs: function () { DotNet.invokeMethodAsync(‘namespace', 'ReturnArrayAsync') .then(data => { data.push(4); console.log(data); }); }, C# JS
  • 13. Scenarios: Round-Trip Callback Invoke JavaScript from .NET Invoke C# Instance Method from JS DotNetObjectReference Dispose, dispose, dispose C# JS Function.callbac k Value R RInstance.method
  • 14. Scenarios: Round-Trip Callback public class GeoLocation { public async ValueTask GetCurrentPosition(...) => await js.InvokeVoidAsync ("blazorGeolocation.getCurrentPosition", DotNetObjectReference.Create(this), options); [JSInvokable] public void RaiseOnGetPosition(Position p) => [JSInvokable] public void RaiseOnGetPositionError(Error err) => window.blazorGeolocation = { getCurrentPosition: function (geolocationRef, options) { navigator.geolocation .getCurrentPosition(onSuccess, onError, options); }, function onSuccess(result) { return geolocationRef .invokeMethodAsync('RaiseOnGetPosition’, blazorGeolocation.toSerializeable(result)); }; function onError(er) { return geolocationRef .invokeMethodAsync('RaiseOnGetPositionError’, er.code); }; }; JSC#
  • 15. Scenarios: Round-Trip Callback public class GeoLocation { public async ValueTask GetCurrentPosition(...) => await js.InvokeVoidAsync ("blazorGeolocation.getCurrentPosition", DotNetObjectReference.Create(this), options); [JSInvokable] public void RaiseOnGetPosition(Position p) => [JSInvokable] public void RaiseOnGetPositionError(Error err) => window.blazorGeolocation = { getCurrentPosition: function (geolocationRef, options) { navigator.geolocation .getCurrentPosition(onSuccess, onError, options); }, function onSuccess(result) { return geolocationRef .invokeMethodAsync('RaiseOnGetPosition’, blazorGeolocation.toSerializeable(result)); }; function onError(er) { return geolocationRef .invokeMethodAsync('RaiseOnGetPositionError’, er.code); }; }; JSC#
  • 16. Scenarios: Round-Trip Callback public class GeoLocation { public async ValueTask GetCurrentPosition(...) => await js.InvokeVoidAsync ("blazorGeolocation.getCurrentPosition", DotNetObjectReference.Create(this), options); [JSInvokable] public void RaiseOnGetPosition(Position p) => [JSInvokable] public void RaiseOnGetPositionError(Error err) => window.blazorGeolocation = { getCurrentPosition: function (geolocationRef, options) { navigator.geolocation .getCurrentPosition(onSuccess, onError, options); }, function onSuccess(result) { return geolocationRef .invokeMethodAsync('RaiseOnGetPosition’, blazorGeolocation.toSerializeable(result)); }; function onError(er) { return geolocationRef .invokeMethodAsync('RaiseOnGetPositionError’, er.code); }; }; JSC#
  • 17. Scenarios: Round-Trip Callback public class GeoLocation { public async ValueTask GetCurrentPosition(...) => await js.InvokeVoidAsync ("blazorGeolocation.getCurrentPosition", DotNetObjectReference.Create(this), options); [JSInvokable] public void RaiseOnGetPosition(Position p) => [JSInvokable] public void RaiseOnGetPositionError(Error err) => window.blazorGeolocation = { getCurrentPosition: function (geolocationRef, options) { navigator.geolocation .getCurrentPosition(onSuccess, onError, options); }, function onSuccess(result) { return geolocationRef .invokeMethodAsync('RaiseOnGetPosition’, blazorGeolocation.toSerializeable(result)); }; function onError(er) { return geolocationRef .invokeMethodAsync('RaiseOnGetPositionError’, er.code); }; }; JSC#
  • 18. Pub-Sub JS C# DOM EventA DOM EventB Channel Component (A) Component (AB) Component (B) Component (AB)
  • 19. Pub-Sub: Init JS C# Channel Component (A) .addEventListener DOM EventA
  • 20. Pub-Sub: De-dupe JS C# Channel Component (A) .addEventListener DOM EventA DOM EventB Component (AB) DOM EventA
  • 21. Pub-Sub: Dispose JS C# DOM EventA DOM EventB Channel Component (A) Component (AB) Component (B) Component (AB) .removeEventListener .Dispose
  • 22. Pub-Sub: Developer Experience JS C# DOM EventA DOM EventB Channel Component (A) Component (AB) Component (B) Component (AB) <MediaQueryList> <MediaQuery> <MediaQuery> <MediaQuery> <MediaQuery> mediaQueryLists: MediaQueryListItem[] MediaQueryListItem { id: number | string; dotnetCallback: (ev: MediaQueryListEvent) mediaQueries: MediaQueryList[]; }
  • 23. Component Lifecycle Awareness SetParametersAsync() OnInitializedAsync() OnParametersSetAsync() OnAfterRenderAsync(bool firstRender) ShouldRender() Avoid JavaScript interop during Initialization. Because Blazor can utilize Server rendering, JavaScript may not be available. Use OnAfterRenderAsync for initializing JavaScript.
  • 25. Typescript DotNetObjectReference type is number | string (int | guid) Remove .json files from NuGet Packages { "compilerOptions": { "outDir": "./wwwroot", "target": "ES6", "moduleResolution": "node", "lib": [ "ES2016", "DOM"] }, "exclude": [ "node_modules", "wwwroot", "**/*.test.ts" ] } tsconfig.json
  • 26. _content/Namespace/resource.* Razor Class Library Assets go in wwwroot wwwroot becomes => _content/Namespace/* Do provide minified and standard formats Example <script src="_content/BlazorPro.BlazorSize/blazorSize.min.js"></script>
  • 27. QUESTIONS Resources 1. EdCharbeneau.com • Free Ebook & examples • GitHub • Twitter • Twitch 2. Blogs.Telerik.com