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
Ad

More Related Content

What's hot (20)

How to React Native
How to React NativeHow to React Native
How to React Native
Dmitry Ulyanov
 
Writing your Third Plugin
Writing your Third PluginWriting your Third Plugin
Writing your Third Plugin
Justin Ryan
 
React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)
Chiew Carol
 
Grails Plugin
Grails PluginGrails Plugin
Grails Plugin
guligala
 
So, you want to be a plugin developer?
So, you want to be a plugin developer?So, you want to be a plugin developer?
So, you want to be a plugin developer?
ylefebvre
 
An easy guide to Plugin Development
An easy guide to Plugin DevelopmentAn easy guide to Plugin Development
An easy guide to Plugin Development
Shinichi Nishikawa
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEB
GR8Conf
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
Ben Mabey
 
React native
React nativeReact native
React native
Omid Nikrah
 
Play Framework on Google App Engine - Productivity Stack
Play Framework on Google App Engine - Productivity StackPlay Framework on Google App Engine - Productivity Stack
Play Framework on Google App Engine - Productivity Stack
Marcin Stepien
 
Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18
Maurice De Beijer [MVP]
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
Ignacio Martín
 
Front Ends for Back End Developers - Spring I/O 2017
Front Ends for Back End Developers - Spring I/O 2017Front Ends for Back End Developers - Spring I/O 2017
Front Ends for Back End Developers - Spring I/O 2017
Matt Raible
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
Ryan Boland
 
Introduction to Griffon
Introduction to GriffonIntroduction to Griffon
Introduction to Griffon
James Williams
 
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
Iván López Martín
 
Introduction to VueJS & The WordPress REST API
Introduction to VueJS & The WordPress REST APIIntroduction to VueJS & The WordPress REST API
Introduction to VueJS & The WordPress REST API
Caldera Labs
 
Taming Functional Web Testing with Spock and Geb
Taming Functional Web Testing with Spock and GebTaming Functional Web Testing with Spock and Geb
Taming Functional Web Testing with Spock and Geb
C4Media
 
‘Hello, world!’ application how to dockerize golang application
‘Hello, world!’ application how to dockerize golang application‘Hello, world!’ application how to dockerize golang application
‘Hello, world!’ application how to dockerize golang application
Katy Slemon
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
Ignacio Martín
 
Writing your Third Plugin
Writing your Third PluginWriting your Third Plugin
Writing your Third Plugin
Justin Ryan
 
React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)React Native +Redux + ES6 (Updated)
React Native +Redux + ES6 (Updated)
Chiew Carol
 
Grails Plugin
Grails PluginGrails Plugin
Grails Plugin
guligala
 
So, you want to be a plugin developer?
So, you want to be a plugin developer?So, you want to be a plugin developer?
So, you want to be a plugin developer?
ylefebvre
 
An easy guide to Plugin Development
An easy guide to Plugin DevelopmentAn easy guide to Plugin Development
An easy guide to Plugin Development
Shinichi Nishikawa
 
Functional testing your Grails app with GEB
Functional testing your Grails app with GEBFunctional testing your Grails app with GEB
Functional testing your Grails app with GEB
GR8Conf
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
Ben Mabey
 
Play Framework on Google App Engine - Productivity Stack
Play Framework on Google App Engine - Productivity StackPlay Framework on Google App Engine - Productivity Stack
Play Framework on Google App Engine - Productivity Stack
Marcin Stepien
 
Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18Concurrent Rendering Adventures in React 18
Concurrent Rendering Adventures in React 18
Maurice De Beijer [MVP]
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
Ignacio Martín
 
Front Ends for Back End Developers - Spring I/O 2017
Front Ends for Back End Developers - Spring I/O 2017Front Ends for Back End Developers - Spring I/O 2017
Front Ends for Back End Developers - Spring I/O 2017
Matt Raible
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
Ryan Boland
 
Introduction to Griffon
Introduction to GriffonIntroduction to Griffon
Introduction to Griffon
James Williams
 
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
GR8Conf 2015 - Spring Boot and Groovy. What more do you need?
Iván López Martín
 
Introduction to VueJS & The WordPress REST API
Introduction to VueJS & The WordPress REST APIIntroduction to VueJS & The WordPress REST API
Introduction to VueJS & The WordPress REST API
Caldera Labs
 
Taming Functional Web Testing with Spock and Geb
Taming Functional Web Testing with Spock and GebTaming Functional Web Testing with Spock and Geb
Taming Functional Web Testing with Spock and Geb
C4Media
 
‘Hello, world!’ application how to dockerize golang application
‘Hello, world!’ application how to dockerize golang application‘Hello, world!’ application how to dockerize golang application
‘Hello, world!’ application how to dockerize golang application
Katy Slemon
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
Ignacio Martín
 

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

Writing JavaScript for C# Blazor.pptx
Writing JavaScript for C# Blazor.pptxWriting JavaScript for C# Blazor.pptx
Writing JavaScript for C# Blazor.pptx
Ed Charbeneau
 
huhu
huhuhuhu
huhu
Dung Trương
 
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Frédéric Harper
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App Engine
Andy McKay
 
mobl
moblmobl
mobl
zefhemel
 
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
Frédéric Harper
 
Mobile webapplication development
Mobile webapplication developmentMobile webapplication development
Mobile webapplication development
Ganesh Gembali
 
HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...
HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...
HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...
Frédéric Harper
 
HTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHexHTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHex
Tadayasu Sasada
 
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads Toulouse - Guillaume Cerquant - UIViewCocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads France
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
dion
 
Phone gap 12 things you should know
Phone gap 12 things you should knowPhone gap 12 things you should know
Phone gap 12 things you should know
ISOCHK
 
Designing and developing mobile web applications with Mockup, Sencha Touch an...
Designing and developing mobile web applications with Mockup, Sencha Touch an...Designing and developing mobile web applications with Mockup, Sencha Touch an...
Designing and developing mobile web applications with Mockup, Sencha Touch an...
Matteo Collina
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
Thierry Wasylczenko
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)
Davide Cerbo
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
guest9bcef2f
 
Android Support Library
Android Support LibraryAndroid Support Library
Android Support Library
Alexey Ustenko
 
Top100summit 谷歌-scott-improve your automated web application testing
Top100summit  谷歌-scott-improve your automated web application testingTop100summit  谷歌-scott-improve your automated web application testing
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
anistar sung
 
WebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsWebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.js
Robert Nyman
 
Writing JavaScript for C# Blazor.pptx
Writing JavaScript for C# Blazor.pptxWriting JavaScript for C# Blazor.pptx
Writing JavaScript for C# Blazor.pptx
Ed Charbeneau
 
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Frédéric Harper
 
Cross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App EngineCross Domain Web
Mashups with JQuery and Google App Engine
Cross Domain Web
Mashups with JQuery and Google App Engine
Andy McKay
 
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
HTML pour le web mobile, Firefox OS - Devfest Nantes - 2014-11-07
Frédéric Harper
 
Mobile webapplication development
Mobile webapplication developmentMobile webapplication development
Mobile webapplication development
Ganesh Gembali
 
HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...
HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...
HTML, not just for desktops: Firefox OS - Congreso Universitario Móvil - 201...
Frédéric Harper
 
HTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHexHTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHex
Tadayasu Sasada
 
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads Toulouse - Guillaume Cerquant - UIViewCocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads Toulouse - Guillaume Cerquant - UIView
CocoaHeads France
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
dion
 
Phone gap 12 things you should know
Phone gap 12 things you should knowPhone gap 12 things you should know
Phone gap 12 things you should know
ISOCHK
 
Designing and developing mobile web applications with Mockup, Sencha Touch an...
Designing and developing mobile web applications with Mockup, Sencha Touch an...Designing and developing mobile web applications with Mockup, Sencha Touch an...
Designing and developing mobile web applications with Mockup, Sencha Touch an...
Matteo Collina
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
Thierry Wasylczenko
 
Non Conventional Android Programming (English)
Non Conventional Android Programming (English)Non Conventional Android Programming (English)
Non Conventional Android Programming (English)
Davide Cerbo
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
guest9bcef2f
 
Android Support Library
Android Support LibraryAndroid Support Library
Android Support Library
Alexey Ustenko
 
Top100summit 谷歌-scott-improve your automated web application testing
Top100summit  谷歌-scott-improve your automated web application testingTop100summit  谷歌-scott-improve your automated web application testing
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
MOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app developmentMOPCON 2014 - Best software architecture in app development
MOPCON 2014 - Best software architecture in app development
anistar sung
 
WebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsWebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.js
Robert Nyman
 
Ad

More from Ed Charbeneau (18)

Blazor Stability Testing Tools for Bullet Proof Applications
Blazor Stability Testing Tools for Bullet Proof ApplicationsBlazor Stability Testing Tools for Bullet Proof Applications
Blazor Stability Testing Tools for Bullet Proof Applications
Ed Charbeneau
 
Secrets of a Blazor Component Artisan (v2)
Secrets of a Blazor Component Artisan (v2)Secrets of a Blazor Component Artisan (v2)
Secrets of a Blazor Component Artisan (v2)
Ed Charbeneau
 
Modernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptxModernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptx
Ed Charbeneau
 
Modernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptxModernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptx
Ed Charbeneau
 
Blazor Full-Stack
Blazor Full-StackBlazor Full-Stack
Blazor Full-Stack
Ed Charbeneau
 
Goodbye JavaScript Hello Blazor
Goodbye JavaScript Hello BlazorGoodbye JavaScript Hello Blazor
Goodbye JavaScript Hello Blazor
Ed Charbeneau
 
Razor into the Razor'verse
Razor into the Razor'verseRazor into the Razor'verse
Razor into the Razor'verse
Ed Charbeneau
 
Blazor
BlazorBlazor
Blazor
Ed Charbeneau
 
Giving Clarity to LINQ Queries by Extending Expressions R2
Giving Clarity to LINQ Queries by Extending Expressions R2Giving Clarity to LINQ Queries by Extending Expressions R2
Giving Clarity to LINQ Queries by Extending Expressions R2
Ed Charbeneau
 
The future of .NET lightning talk
The future of .NET lightning talkThe future of .NET lightning talk
The future of .NET lightning talk
Ed Charbeneau
 
Into the next dimension
Into the next dimensionInto the next dimension
Into the next dimension
Ed Charbeneau
 
Giving Clarity to LINQ Queries by Extending Expressions
Giving Clarity to LINQ Queries by Extending ExpressionsGiving Clarity to LINQ Queries by Extending Expressions
Giving Clarity to LINQ Queries by Extending Expressions
Ed Charbeneau
 
What is new in Q2 2015
What is new in Q2 2015What is new in Q2 2015
What is new in Q2 2015
Ed Charbeneau
 
TelerikNEXT What's new in UI for ASP.NET AJAX
TelerikNEXT What's new in UI for ASP.NET AJAXTelerikNEXT What's new in UI for ASP.NET AJAX
TelerikNEXT What's new in UI for ASP.NET AJAX
Ed Charbeneau
 
Journey to JavaScript (from C#)
Journey to JavaScript (from C#)Journey to JavaScript (from C#)
Journey to JavaScript (from C#)
Ed Charbeneau
 
Refactoring css
Refactoring cssRefactoring css
Refactoring css
Ed Charbeneau
 
Don't be a stereotype: Rapid Prototype
Don't be a stereotype: Rapid PrototypeDon't be a stereotype: Rapid Prototype
Don't be a stereotype: Rapid Prototype
Ed Charbeneau
 
A crash course in responsive design
A crash course in responsive designA crash course in responsive design
A crash course in responsive design
Ed Charbeneau
 
Blazor Stability Testing Tools for Bullet Proof Applications
Blazor Stability Testing Tools for Bullet Proof ApplicationsBlazor Stability Testing Tools for Bullet Proof Applications
Blazor Stability Testing Tools for Bullet Proof Applications
Ed Charbeneau
 
Secrets of a Blazor Component Artisan (v2)
Secrets of a Blazor Component Artisan (v2)Secrets of a Blazor Component Artisan (v2)
Secrets of a Blazor Component Artisan (v2)
Ed Charbeneau
 
Modernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptxModernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptx
Ed Charbeneau
 
Modernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptxModernizing Web Apps with .NET 6.pptx
Modernizing Web Apps with .NET 6.pptx
Ed Charbeneau
 
Goodbye JavaScript Hello Blazor
Goodbye JavaScript Hello BlazorGoodbye JavaScript Hello Blazor
Goodbye JavaScript Hello Blazor
Ed Charbeneau
 
Razor into the Razor'verse
Razor into the Razor'verseRazor into the Razor'verse
Razor into the Razor'verse
Ed Charbeneau
 
Giving Clarity to LINQ Queries by Extending Expressions R2
Giving Clarity to LINQ Queries by Extending Expressions R2Giving Clarity to LINQ Queries by Extending Expressions R2
Giving Clarity to LINQ Queries by Extending Expressions R2
Ed Charbeneau
 
The future of .NET lightning talk
The future of .NET lightning talkThe future of .NET lightning talk
The future of .NET lightning talk
Ed Charbeneau
 
Into the next dimension
Into the next dimensionInto the next dimension
Into the next dimension
Ed Charbeneau
 
Giving Clarity to LINQ Queries by Extending Expressions
Giving Clarity to LINQ Queries by Extending ExpressionsGiving Clarity to LINQ Queries by Extending Expressions
Giving Clarity to LINQ Queries by Extending Expressions
Ed Charbeneau
 
What is new in Q2 2015
What is new in Q2 2015What is new in Q2 2015
What is new in Q2 2015
Ed Charbeneau
 
TelerikNEXT What's new in UI for ASP.NET AJAX
TelerikNEXT What's new in UI for ASP.NET AJAXTelerikNEXT What's new in UI for ASP.NET AJAX
TelerikNEXT What's new in UI for ASP.NET AJAX
Ed Charbeneau
 
Journey to JavaScript (from C#)
Journey to JavaScript (from C#)Journey to JavaScript (from C#)
Journey to JavaScript (from C#)
Ed Charbeneau
 
Don't be a stereotype: Rapid Prototype
Don't be a stereotype: Rapid PrototypeDon't be a stereotype: Rapid Prototype
Don't be a stereotype: Rapid Prototype
Ed Charbeneau
 
A crash course in responsive design
A crash course in responsive designA crash course in responsive design
A crash course in responsive design
Ed Charbeneau
 
Ad

Recently uploaded (20)

HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
Are Cloud PBX Providers in India Reliable for Small Businesses (1).pdf
Are Cloud PBX Providers in India Reliable for Small Businesses (1).pdfAre Cloud PBX Providers in India Reliable for Small Businesses (1).pdf
Are Cloud PBX Providers in India Reliable for Small Businesses (1).pdf
Telecoms Supermarket
 
TrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token ListingTrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token Listing
Trs Labs
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Vaibhav Gupta BAML: AI work flows without Hallucinations
Vaibhav Gupta BAML: AI work flows without HallucinationsVaibhav Gupta BAML: AI work flows without Hallucinations
Vaibhav Gupta BAML: AI work flows without Hallucinations
john409870
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Social Media App Development Company-EmizenTech
Social Media App Development Company-EmizenTechSocial Media App Development Company-EmizenTech
Social Media App Development Company-EmizenTech
Steve Jonas
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Unlocking the Power of IVR: A Comprehensive Guide
Unlocking the Power of IVR: A Comprehensive GuideUnlocking the Power of IVR: A Comprehensive Guide
Unlocking the Power of IVR: A Comprehensive Guide
vikasascentbpo
 
Cybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure ADCybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure AD
VICTOR MAESTRE RAMIREZ
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 
HCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser EnvironmentsHCL Nomad Web – Best Practices and Managing Multiuser Environments
HCL Nomad Web – Best Practices and Managing Multiuser Environments
panagenda
 
Are Cloud PBX Providers in India Reliable for Small Businesses (1).pdf
Are Cloud PBX Providers in India Reliable for Small Businesses (1).pdfAre Cloud PBX Providers in India Reliable for Small Businesses (1).pdf
Are Cloud PBX Providers in India Reliable for Small Businesses (1).pdf
Telecoms Supermarket
 
TrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token ListingTrsLabs Consultants - DeFi, WEb3, Token Listing
TrsLabs Consultants - DeFi, WEb3, Token Listing
Trs Labs
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
Linux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdfLinux Professional Institute LPIC-1 Exam.pdf
Linux Professional Institute LPIC-1 Exam.pdf
RHCSA Guru
 
Vaibhav Gupta BAML: AI work flows without Hallucinations
Vaibhav Gupta BAML: AI work flows without HallucinationsVaibhav Gupta BAML: AI work flows without Hallucinations
Vaibhav Gupta BAML: AI work flows without Hallucinations
john409870
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc
 
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul Shares 5 Steps to Implement AI Agents for Maximum Business Efficien...
Noah Loul
 
Social Media App Development Company-EmizenTech
Social Media App Development Company-EmizenTechSocial Media App Development Company-EmizenTech
Social Media App Development Company-EmizenTech
Steve Jonas
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Unlocking the Power of IVR: A Comprehensive Guide
Unlocking the Power of IVR: A Comprehensive GuideUnlocking the Power of IVR: A Comprehensive Guide
Unlocking the Power of IVR: A Comprehensive Guide
vikasascentbpo
 
Cybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure ADCybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure AD
VICTOR MAESTRE RAMIREZ
 
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
AI Changes Everything – Talk at Cardiff Metropolitan University, 29th April 2...
Alan Dix
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)Into The Box Conference Keynote Day 1 (ITB2025)
Into The Box Conference Keynote Day 1 (ITB2025)
Ortus Solutions, Corp
 
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath MaestroDev Dives: Automate and orchestrate your processes with UiPath Maestro
Dev Dives: Automate and orchestrate your processes with UiPath Maestro
UiPathCommunity
 
TrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business ConsultingTrsLabs - Fintech Product & Business Consulting
TrsLabs - Fintech Product & Business Consulting
Trs Labs
 
Procurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptxProcurement Insights Cost To Value Guide.pptx
Procurement Insights Cost To Value Guide.pptx
Jon Hansen
 

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