With this release, we’re introducing the commenting functionality that extends the collaborative capabilities of Unite UX. Now you don’t have to leave the app to give feedback about the design or the implementation of your components. Just click on the spot and leave your thoughts. Use @ to mention anyone that has access to your project to notify them via email. Resolve the threads that are already fixed and build your design system just as intended.
The new Unite UX comes with some predefined flows that explain in detail how to get started using the product. You will see guided tutorials, tips and tricks and key functionalities, highlighted to help you get most of the product in no time. So, make sure not to skip it, but even if you do, you can always go back to it using the ‘?’ button in the toolbar.
The 1.5.0 release brings a new type of component parts—links. Sometimes, the components are complex and some of the parts are hidden in the components tree. To improve the visibility of some parts and at the same time preserve the top-right to bottom-left styling from one place algorithm, we’ve extracted such parts and visualize them as links to their original parts where they can be edited. This will improve the overall visibility of the parts and preserve the natural way of styling things.
The performance of the Unite UX is of highest importance for the team. With this release, we managed to locate and fix some bottlenecks, making the app blazing fast. No more endless loading indicator—everything will load before you know it.
The 1.5.0 release includes 2 new components: The Card and the TextArea in the list of supported components. At the same time, we’ve optimized the existing component parts to be more intuitive and easier to style—we have included the No Records template for the grid and redesigned the Button Group templates. And last but not least, all common drop-down (popup, list and items) templates are extracted to separate page in order to be styled globally.
Performance and quality come hand in hand. That’s why we’re always trying to fix as many things as we can—especially the things that are reported from our users. Here are the things we’ve fixed in the 1.4.0 release:
If you still haven’t had the chance to try Unite UX, you can start your 21-day trial now.
]]>Visual Studio has had its first major release in about 18 months (depending on how you look at it). This release adds a ton of new features and capabilities to the IDE. Now, is a great time to start learning about them.
The user experience of the IDE has been updated to be more consistent and more user friendly. This includes new icons, new fonts, new personalization and more.
The icons have been updated to be consistent across different icons while remaining legible and familiar to the user.
You’ve probably noticed in the image above that there are icons for a light and dark theme. While themes are not new to Visual Studio, Visual Studio now offers you the ability to sync your Visual Studio theme with your operating system theme.
The dark theme has been updated also to better align with the Microsoft design guidelines and improve accessibility.
Visual Studio now includes a Theme Converter, which converts Visual Studio Code themes to Visual Studio themes.
Visual Studio now includes inlay hints for code completion, code lens and more. Inlay hints can display parameter name hints for literals, function calls and more.
In this image, you can see that Visual Studio tells you that the type for variable imageUrl
is string
and contact
is of type Contact
. Further down the image, the RedirectToAction
method has a parameter named actionName
, which this sample is using the Details
action.
Note, this feature is not on by default. You can enable it by going to the Tools > Options > Text Editor > C# or Basic > Advanced then select Inlay Hints.
You might be saying that all these user interfaces are nice, but Visual Studio is slow enough already. Well, that might have been the case for earlier versions of Visual Studio, but that is not the case for Visual Studio 2022.
It’s faster in part now that Visual Studio 2022 is a 64-bit application. This means that the main process (devenv.exe) is no longer limited to 4GB of memory. Now Visual Studio can load larger projects and load more projects at once. You’ll also avoid the “out of memory” errors that Visual Studio was seeing before when opening large solutions, files or objects into memory.
Solution loading and file searching is now faster as well. Visual Studio now stores additional information about the solution in the .sln file. This information is used to speed up the loading of the solution. This information is also used to speed up the file searching.
To continue on the speeding-up Visual Studio theme, Microsoft also improved the Fast up to date feature to better check to see if a project or its dependencies are up to date or need to be rebuilt.
Visual Studio 2022 has added and enhanced the debugging features of Visual Studio.
Let’s talk about breakpoints first. There are two new breakpoints that you can set in Visual Studio—temporary and dependent breakpoints—as shown in the image below.
The Temporary breakpoint is used to set a breakpoint that will only break once. Once Visual Studio hits that breakpoint, it deletes it. This is helpful if you want to set a breakpoint only to validate that something is working, and you aren’t debugging the code.
The Dependent breakpoint is used to set a breakpoint that will only break when another breakpoint is hit.
Previous versions of Visual Studio added a feature called “Run to Cursor.” This feature was used to execute code up to the code at the cursor.
However, if you had any breakpoints between where you were and where you wanted to run to, Visual Studio would stop at all those breakpoints. Now with Force Run To Cursor, you can run to the cursor without hitting any breakpoints. If you hold the shift key down while hovering over the Run to Cursor glyph, Visual Studio will change the glyph to a Force Run To Cursor glyph and will run to the cursor without hitting any breakpoints.
The Force Run to Cursor is also available in the Debug menu.
For more on breakpoints or debugging tips and tricks in Visual Studio, check out this video:
IntelliCode improves IntelliSense by using AI to help you find the right code completion. IntelliCode is context-aware and will help you find the right code completion when you are typing a method call, a property or a variable.
In the image below, I start to create a new method after the GetContactsAsync
method. After I type public async
, IntelliCode is inferring that I want to create a DeleteContactAsync
method with a parameter of type contactId
. If that is what I want, I can hit the Tab
key twice to insert the suggestion.
We now have multiple-repository support, which includes the ability to track changes across all the repositories in a project. If you open a solution that has multiple Git repositories in it, Visual Studio will connect/activate those repositories. Right now, this is limited to a max of 10 repositories.
You will be able to tell if Visual Studio has connected to or activated your different Git repositories by looking at the repository picker on the status bar (located at the lower right corner), which will tell you the number of active repositories you have.
The Git integration with Visual Studio has been improved and include support for multiple repositories, including improvements to both the Solution Explorer and Code Editors.
Hot Reload is a feature of Visual Studio that allows you to modify your application’s managed code while that application is running without the need to hit a breakpoint or pause the application. This is a cool feature that will save you a lot of time without pausing or stopping your application to see how the source code changes you made changed your application.
However, the support for this feature is still in progress. There are some scenarios and products that are not yet supported.
Visual Studio 2022 for Mac is coming. The Visual Studio team wants to make a modern .NET IDE tailored for the Mac that will look familiar to those using Visual Studio for Windows while using native macOS UI. For more on the Visual Studio 2022 for Mac and/or to join the private beta, please visit here.
While technically not released with Visual Studio 2022, Microsoft released .NET 6 at the same time and includes the .NET 6 SDK in the Visual Studio installation. So now is the time to start migrating your .NET 5, and earlier, projects to .NET 6. As Barry Dorrans @blowdart points out, .NET 5 moves to end of life in May of 2022.
Some more details on the support policy for .NET are below.
Version | Original Release Date | Latest Patch Version | Patch Release Date | Support Level | End of Support |
---|---|---|---|---|---|
.NET 6 | November 08, 2021 | 6.0.0 | November 08, 2021 | LTS | November 08, 2024 |
.NET 5 | November 10, 2020 | 5.0.12 | November 08, 2021 | Current | May 08, 2022 |
.NET Core 3.1 | December 3, 2019 | 3.1.21 | November 08, 2021 | LTS | December 3, 2022 |
Source: .NET Support Policy
So, what’s stopping you from upgrading your IDE and version of .NET?
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
Most .NET developers are looking forward to .NET Multi-platform App UI (MAUI)—the evolution of Xamarin.Forms with .NET 6. Going forward, developers should have much more confidence in the technology stack and tools as .NET MAUI empowers native cross-platform solutions on mobile and desktop.
While it is a long flight until we reach the sands of MAUI, developer excitement is palpable in all the news/content as we tinker and prepare for .NET MAUI. Like the grains of sand, every piece of news/article/video/tutorial/stream contributes towards developer knowledge and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here's what is noteworthy for the week of December 13, 2021:
The .NET Podcast app was a cornerstone demo during .NET Conf—a unified app running on multiple platforms and showcasing the flexibility of code sharing across Blazor, .NET MAUI and ASP.NET Core. The source code for the .NET Podcast app was recently open sourced, but running it locally involved a few steps—who knew a real world app had some moving pieces and architectural dependencies.
James Montemagno produced a video showcasing local development walkthrough with the .NET Podcast app—a how-to guide on grabbing source code and running the app locally.
Aside from .NET MAUI and Blazor code, the .NET Podcast app has Azure Container Service dependencies, uses GitHub Actions and utilizes backend APIs powered by ASP.NET Core. This is a great real-world sample app perfect for developer exploration and James shows how to have the full end-to-end demo running on developer local machine.
Developers have always been told that one needs a Mac to build for iOS from Xamarin.Forms/.NET MAUI while on a Windows machine. Turns out, this is not entirely true thanks to a wonderful feature—Xamarin Hot Restart, which enables developers to quickly test code changes on an iOS device during app development. Armed with an iOS device and a connecting cable, developers can directly deploy apps to the device from Xamarin.Forms with Visual Studio while running on Windows.
Gerald Versluis produced a video exploring iOS development without a Mac and dived head first into Xamarin Hot Restart. As usual, Gerald makes the technology accessible to anyone—starting with the basics of Xamarin Hot Restart, developer setup, installing iTunes and connecting to physical iOS device.
With a paid Apple Developer Program subscription, developers can set up Visual Studio on Windows to directly deploy/test apps to iOS devices—and even publish apps to the App Store.
Building client apps with .NET? You could be building web/desktop/mobile apps across a variety of platforms with some solid tooling. And nothing else celebrates .NET on the client side like .NET FrontEnd Day—a full day virtual conference, with focus on building frontend apps using .NET.
With a successful first year under the belt, .NET FrontEnd Day is gearing up for the second edition on Feb 10, 2022 and just announced their list of speakers. Rest assured, there would be no dearth of .NET MAUI and Blazor love—developers should register and tune in.
.NET has come a long way and the future of the .NET developer ecosystem looks bright. There is, however, a lot to take in and the bigger picture story from experienced .NET developers help.
Ed Charbeneau produced a video on the .NET of Today and Tomorrow, recapping some historical perspective and looking ahead at the future with .NET 6.
Ed talks about the .NET unification story and how .NET UI tooling from Progress Telerik can help .NET developers be more successful. It did not take long for Ed to dive into modern web development with .NET 6 and Blazor and exploring the code-sharing future with Hybrid apps using Blazor on top of .NET MAUI—all backed by solid demos and code walkthroughs.
.NET 6 is out and there was a lot of .NET developer content shared at .NET Conf. While most developers are still taking it all in, Dave Brock wrote up an article on favorite things in .NET 6.
Dave correctly points out some of the major objectives with .NET 6—lower barrier to entry into .NET, improving app startup/performance metrics, elevated client app development experience and faster developer inner loop.
While most of Dave's favorites lean towards modern web development, many point to the core benefits of .NET 6 for .NET MAUI developers as well. Some of the .NET 6 excitement centers around Hot Reload, C# 10 features, Minimal APIs and Blazor improvements—the present unified reality of .NET is looking pretty good.
That's it for now.
We'll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>Let’s talk Angular—one of the most popular modern web application development platforms. With a long history, matured tooling and rich developer ecosystem, it is not difficult to see why Angular is the SPA framework of choice for building modern web/mobile apps.
However, how does Angular work for desktop apps? The classic software answer applies—it depends. There are strategies for code sharing with web, but a lot also depends on the type of app being built and the desktop integrations desired.
PWAs and ElectronJS are established ways of bringing web code to desktop apps, and they are both good options for Angular. For .NET developers, .NET MAUI is the next-generation platform for building native cross-platform apps for mobile and desktop. And with Blazor hybrid apps, Blazor code for web apps is very welcome in .NET MAUI for mobile/desktop.
However, a lot of .NET shops in the past few years have been doing .NET in the backend and building SPA apps with JS on the frontend—can any of those investments come over to .NET MAUI land? Let’s talk about Angular, but the ways to enable desktop apps with web technologies should be about the same irrespective of the JS framework—so React, Vue and others should feel welcome too.
Angular goodness on desktop—let’s do this.
This post was written and published as part of the 2021 C# Advent.
If you’re new to the Angular world, one of the best ways to get started is the Angular CLI. The prerequisites to building with Angular are an LTS Node.js version for the runtime and npm for dependencies. It’s easy to globally install the Angular CLI tool, like so:
npm install -g @angular/cli
We can then fire up a new Angular app—the template walks you through a few settings before creating the project.
ng new angularcli
The Angular CLI tool installs the necessary Angular npm packages and other dependencies—once done, we can navigate inside the project and see all the code/configurations.
cd angularcli
Ready to run your Angular app locally? The Serve command compiles the app in memory, launches the server and watches local files for deploying changed components of the app.
ng serve --open
Voilà. That’s how easy it is to start making modern web apps with Angular. And while you’re getting started, it may be worth getting some UI ammunition to deliver good UX and performance—Kendo UI for Angular can help.
Kendo UI for Angular delivers components to meet app requirements for data handling, performance, UX, design, accessibility and so much more—100+ fully native components for building high-quality modern Angular UI in no time.
Now that we have a basic Angular web app running, let’s talk about options to get that Angular goodness on desktop apps.
One of the easiest ways for a web app to work on desktop is PWA—web apps can be progressively better citizens on mobile/desktop platforms. PWAs are essentially web apps, but with hooks to have native-like features—be installable on desktop and have service workers bring in offline support, push notifications, hardware access and more. It is pretty easy to start turning a regular Angular web app into a PWA—just a simple command:
ng add @angular/pwa
This actually touches a few things in an existing Angular app—a new manifest file is dropped in that tells the browser how the app should behave when installed by the user. The starter set has a variety of app icons for pinning to home screen, Touchbar and more—the default icons are added to an Asset's directory.
{
"name": "angularpwa",
"short_name": "angularpwa",
"theme_color": "#1976d2",
"background_color": "#fafafa",
"display": "standalone",
"scope": "./",
"start_url": "./",
"icons": [
{
"src": "assets/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"purpose": "maskable any"
},
{
"src": "assets/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"purpose": "maskable any"
},
...
...
]
}
The startup index.html page now has a reference to the new web manifest file.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angularpwa</title>
<base href="https://www.telerik.com/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="https://www.telerik.comfavicon.ico">
<link rel="manifest" href="https://www.telerik.commanifest.webmanifest">
<meta name="theme-color" content="#1976d2">
</head>
<body>
<app-root></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
</body>
</html>
A default caching service worker is dropped in as well, with configuration file namely ngsw-config.json—this indicates which types of assets can be cached.
{
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/*.js"
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
]
}
}
]
}
The ServiceWorker config file needs to be referenced in the angular.json file—the ngswConfigPath links the ServiceWorker, enabling production configuration in build schematics.
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angularpwa": {
"projectType": "application",
"schematics": {
"@schematics/angular:application": {
"strict": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/angularpwa",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"src/styles.css"
],
"scripts": [],
"serviceWorker": true,
"ngswConfigPath": "ngsw-config.json"
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"outputHashing": "all",
"serviceWorker": true,
"ngswConfigPath": "ngsw-config.json"
},
...
...
}
}
}
}
}
}
And finally, the app.module.ts now imports in ServiceWorkerModule and registers the ServiceWorker.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
registrationStrategy: 'registerWhenStable:30000'
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
That’s a run-down of all the moving pieces that start transforming a regular Angular app into a PWA. However, we cannot just run the app with Angular Serve command—service workers do not work with in-memory compilations. We need a production build, like so:
ng build --prod
Once the build is done with Production configuration, we can see the artifacts in the Distribution directory—everything is compiled down to deployable plain HTML/JS/CSS.
cd dist/angularpwa
Next up, we need a small HTTP sever to expose the built files out to the browser as apps and fire things up.
npm i -g http-server
http-server -p 8080 -c-1
Excellent—we can navigate to local HTTP server IP and see our PWA in action! Notice the install option, which indicates that the user can install and run this app on desktop without the browser chrome.
If we open up Developer Tools on our browser, we can also see the default caching Service Worker being registered and running. This is just the start—developers can now start adding all the customizations to make a nice modern PWA with Angular.
Another strong contender for bringing Angular apps to desktop is Electron—the popular open-source battle-tested way of hosting web apps on desktop.
Electron helps in building robust cross-platform desktop apps that are essentially HTML/CSS/JS, but with strong integrations with the host OS when running as a desktop app. Electron does pack two things to provide a consistent runtime and rendering canvas—Node.js and the Chromium engine.
Starting from a standard Angular CLI app, it is not difficult to add Electron support—let’s bring in the Electron package as a dev dependency.
npm install electron@latest --save-dev
Now, to configure all things Electron inside an Angular project, let’s add a simple App.js file. To bootstrap Electron to run on desktop, we essentially need to new-up a browser window with specified dimensions and load our Angular app’s URL. We also need listeners for when the app windows open/close—here’s the code:
const {
app,
BrowserWindow
} = require('electron')
const url = require("url");
const path = require("path");
let appWindow
function initWindow() {
appWindow = new BrowserWindow({
width: 1000,
height: 800,
webPreferences: {
nodeIntegration: true
}
})
appWindow.loadURL(
url.format({
pathname: path.join(__dirname, `/dist/index.html`),
protocol: "file:",
slashes: true
})
);
appWindow.on('closed', function () {
appWindow = null
})
}
app.on('ready', initWindow)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
if (win === null) {
initWindow()
}
})
Next up, we need to configure our Angular app to build itself and Bootstrap from the App.js file—here is the setup in package.json with the main entry point and a build script to start Electron:
{
"name": "angularelectron",
"version": "0.0.0",
"main": "app.js",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"start:electron": "ng build --base-href ./ && electron ."
},
...
...
}
That’s all—now we can fire up our app, and see Angular hosted within the Electron shell.
npm run start:electron
We have a full Chromium engine embedded inside the app—so we could do things like opening up Chrome DevTools from code:
appWindow.webContents.openDevTools()
.NET MAUI is the evolution of Xamarin.Forms and represents a modern cross-platform .NET solution to reach mobile and desktop platforms. Blazor is very welcome in .NET MAUI—essentially .NET MAUI bootstrapping the app and Blazor code rendering within the BlazorWebView. This is obviously a good story for app modernization—Blazor and .NET MAUI both run on .NET 6 and developers can now share code between web/desktop.
But what if you already had investments in JavaScript? What if you were already building modern web apps with JS SPA frameworks? Would any of that be brought over to .NET MAUI? Let’s take a look at the Angular story.
As we’ve seen getting started with the Angular CLI, Angular web apps do depend on Node.js and Node modules—which is not something we have with .NET MAUI running on .NET 6. However, let’s compile our Angular CLI app, like so:
ng build --prod
If we look in the dist folder, the artifacts of the build are pure web assets—all the TypeScript, Node dependencies and other things get compiled down to basic HTML/JS/CSS.
If we take a look at the index.html file, it simply references all the JavaScript and knows how to display the root app component.
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>Angularcli</title>
<base href="https://www.telerik.com/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="https://www.telerik.comfavicon.ico">
<link rel="stylesheet" href="https://www.telerik.comstyles.ef46db3751d8e999.css"></head>
<body>
<app-root></app-root>
<script src="https://www.telerik.comruntime.8711a0b48f514fd6.js" type="module"></script><script src="https://www.telerik.compolyfills.24f5ee6314fed4d1.js" type="module"></script><script src="https://www.telerik.commain.756852958de70a14.js" type="module"></script>
</body></html>
Let us start a .NET MAUI project with the Maui-Blazor template—essentially a hybrid app with full native capabilities, but with Blazor UI rendered through a modern WebView for mobile and desktop platforms.
However, could we swap out Blazor with Angular? They’re both modern web frameworks rendering UI for the browser, but with different runtimes—maybe the WebView will not care? Let’s bring the compiled Angular CLI app files into our .NET MAUI-Blazor app and drop them in the wwwroot directory as static files, like so:
The index.html files acts as the starting point for the Blazor inside .NET MAUI app—what if we replace it with the one we get from the Angular app? Let’s go look in the MainPage.xaml file:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui"
xmlns:local="clr-namespace:MauiAngular"
x:Class="MauiAngular.MainPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<b:BlazorWebView HostPage="wwwroot/index.html">
<!-- <b:BlazorWebView.RootComponents>
<b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</b:BlazorWebView.RootComponents> -->
</b:BlazorWebView>
</ContentPage>
This is where the rubber meets the road—the .NET MAUI app throws up the big BlazorWebView component for Blazor to do its thing. BlazorWebView is essentially a wrapper—rendering Webiew2 on Windows, WKWebView on macOS or whichever is the latest relevant WebView component based on the platform where the app is running on.
Here in the MainPage.xaml, we can still point it to go render the wwwroot/index.html file, but we have it swapped with the Angular file now. And we stop Blazor from rendering its base Root component—so it should be all Angular driving the UI within the WebView. We hesitantly do a .NET MAUI build:
dotnet build -t:Run -f net6.0-ios
Voilà—we get the Angular CLI app now running inside of .NET MAUI on iOS!
Let’s do a desktop build:
dotnet build -t:Run -f net6.0-maccatalyst
Works on macOS, and Windows should be no different.
Since we fed the BlazorWebView with HTML/CSS/JS, it did not care that we did not render any Blazor UI—web UI is web UI. And now it is welcome inside .NET MAUI cross-platform apps. Angular code would need a JS Interop to talk to .NET code, but the promise to bring Angular to .NET desktop/mobile apps is just starting.
Angular is wonderful and enables developers to build modern web apps. But much of the Angular goodness—components, data-binding, routing and more, can be brought over to desktop apps. While PWAs and Electron are the present reality, .NET MAUI represents the promise of tomorrow to bring Angular to Windows/macOS desktop. Let’s reuse code!
]]>Barcodes can be found everywhere—no matter whether it is on the shipping package in logistics, on an invoice in accounting or on a component parts in industrial factories. They are widely used to help quickly share specific information.
With the R3 2021 release of Telerik UI for Xamarin suite, we’ve expanded our Barcode control to include a new Data Matrix component. Together with the QR Code and PDF417, DataMatrix is among the most popular two-dimensional barcode symbologies. DataMatrix is also available in our UI for WinUI, UI for WPF and UI for WinForms suites.
Data Matrix is a very efficient, two-dimensional (2D) barcode symbology consisting of black and white “cells,” or dots, arranged in either a square or rectangular pattern, also known as a matrix. The information to be encoded can be text or numeric data. With a usual data size from a few bytes up to 1,556 bytes (or up to up to 2,335 alphanumeric characters), DataMatrix barcode is one of the smallest barcodes while encoding the same data as other barcodes.
Every Data Matrix is composed of two solid adjacent borders in an “L” shape (called the “finder pattern”) and two other borders consisting of alternating dark and light “cells” or modules (called the “timing pattern”). Within these borders are rows and columns of cells encoding information. The finder pattern is used to locate and orient the data matrix while the timing pattern provides a count of the number of rows and columns in the matrix.
What are the specific benefits of Data Matrix over other 2D barcodes?
As always, we have ensured to provide you with various configuration options, so you get the exact DataMatrix barcode you need. Let’s quickly go through the list of the available settings:
The Encodation property determines the type of content encoded by the DataMatrix barcode. It’s important to choose the proper encodation, as this reduces the barcode size and improves readability. Possible options are ASCII, Text and C40. Details on each of these can be found in our documentation here: Data Matrix Symbology Encodation.
Although the most popular DataMatrix is square, similar to the QR code, you also have the option to define it as a rectangle. This is controlled through the SymbolSize property. In addition to the shape, you can choose whether the size should be automatically determined by using “SquareAuto” or “RectangleAuto,” or manually define it by using values such as Square32x32 or Rectangle16x48.
The TextEncoding property defines character encoding used to encode the barcode contents. By default, it is set to UTF-8, which uses more bits per character and may increase the size of the barcode image. TextEncoding is of type System.Text.Encoding and you can check the available values in MS Docs: System.Text.Encoding Class.
Let’s add a simple DataMatrix barcode to the Xamarin.Forms page.
xmlns:telerik="clr-namespace:Telerik.XamarinForms.Barcode;assembly=Telerik.XamarinForms.Barcode"
<
telerik:RadBarcode
x:Name
=
"dataMatrix"
>
<
telerik:RadBarcode.Symbology
>
<
telerik:DataMatrix
Encodation
=
"Ascii"
SymbolSize
=
"SquareAuto"
/>
</
telerik:RadBarcode.Symbology
>
</
telerik:RadBarcode
>
string
productName =
"Product Name: Telerik UI for Xamarin"
;
string
productPage =
"Product Page: https://www.telerik.com/xamarin-ui"
;
string
documentation =
"Documentation: https://docs.telerik.com/devtools/xamarin/"
;
string
release =
"Recent Release: R3 2021"
;
dataMatrix.Value = $
"{productName}\n{productPage}\n{documentation}\n{release}"
;
Check the result in Android emulator:
The R3 2021 release is available for download in customers’ accounts. If you are new to Telerik UI for Xamarin, you can learn more about it via the product page. It comes with a 30-day free trial, giving you some time to explore the toolkit and consider using it for your current or upcoming Xamarin development.
We would love to hear what you think, so should you have any questions and/or comments, please share them in our Telerik UI for Xamarin Feedback Portal.
A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
Most .NET developers are looking forward to .NET Multi-platform App UI (MAUI)—the evolution of Xamarin.Forms with .NET 6. Going forward, developers should have much more confidence in the technology stack and tools as .NET MAUI empowers native cross-platform solutions on mobile and desktop.
While it is a long flight until we reach the sands of MAUI, developer excitement is palpable in all the news/content as we tinker and prepare for .NET MAUI. Like the grains of sand, every piece of news/article/video/tutorial/stream contributes towards developer knowledge and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here's what is noteworthy for the week of December 6, 2021:
.NET Conf 2021 was a massive success—great .NET content from Microsoft folks and speakers from all around the world. One of the key demo apps during the .NET Conf keynotes was a modern .NET Podcast app—a showcase of .NET MAUI and Blazor working together on top of .NET 6.
James Montemagno wrote up a .NET Conf Recap post pointing to some wonderful session recordings and behold—the .NET Podcast app now open sourced. This took some coordination and is a great showcase of a full-featured .NET MAUI app with Blazor and Azure Container Apps goodness baked in—a nicely architected codebase for developers to explore.
Maddy Montaquila and David Ortinau hosted the latest .NET MAUI Community Standup with an epic beginning and with special guest THE Jonathan Dick. On the cards was pointers to .NET Conf goodness around .NET MAUI/Blazor/C# and recapping exciting community blog updates.
David and Jon dug deep into Xamarin.Forms—the present reality that isn't shabby at all with latest service release and lots of community PRs. Next up was what we're all waiting on to close out the year strong—the next .NET MAUI release, aka Preview 11, due out soon. There is much to be excited about—Multi-Window support, Layout improvements, new controls/Handlers and performance tuning.
The next wave of tooling update riding out with Visual Studio 17.2 is scheduled to bring in Visual Diagnostics—a web DOM like view/selection of UI elements within a running .NET MAUI app and changing properties on the fly. David and Jon also did a lot of honest Q/A—the future looks productive for .NET MAUI developers.
Both Xamarin.Forms and .NET MAUI provide abstraction over native UI across platforms—developers get to write C#/XAML that gets rendered as native controls on each respective platform. What if you wanted to customize the look and feel or some behavior of the native UI, perhaps on a per platform basis? This is where the evolution to .NET MAUI really makes a difference.
In Xamarin.Forms, one would have to write custom Effects or worst case, a whole custom renderer overriding a native platform implementation—this was not for the faint-hearted.
.NET MAUI makes native UI customizations easy with the new Handler architecture, which provides hooks to tap into native control behavior. Gerald Versluis produced a video on customizing .NET MAUI controls with Handlers and Mappers—an encore after some APIs changed with latest .NET MAUI Previews.
Gerald talks through how to override the Handler implementations through specific Mappers, with PrependToMapper, ModifyMapper or AppendToMapper methods—thus providing developers full flexibility as to how/when to customize control behavior.
Blazor Hybrid apps with .NET MAUI is a great story—brings in the goodness of web to native mobile/desktop apps. However, what if you had investments in JavaScript, like in modern frontend apps with JS SPA frameworks? All this talk of modernizing desktop apps with web code got you thinking if your JS code can make it over the bridge if you give up NodeJs or JSX dependencies?
For modern frontend apps written with Angular/React/other SPA frameworks, PWA and Electron present two lucrative ways to bring the goodness over to desktop audiences. However, Blazor gets to use the BlazorWebView on top of .NET MAUI—and shouldn't a WebView component be able to render any web content?
A curious developer tried just that—would it be possible to render a fully compiled Angular web app inside a .NET MAUI app through the BlazorWebView? Do a full build of an Angular app and you essentially get HTML, JS and CSS—BlazorWebView does not care and is happy to render.
Been hearing the buzz about .NET MAUI Community Toolkit but haven't given it a spin yet? Brandon Minnick produced a short video from .NET Conf giving you the essential rundown of .NET MAUI Community Toolkit and how to get started using it.
.NET MAUI Community Toolkit is an open source toolkit meant to augment the .NET MAUI developer experience with Extensions, Behaviors, Converters, UI Elements and more—nothing stopping you from being more productive.
That's it for now.
We'll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>For the second straight November, .NET developers have received an early holiday gift: a new release of the .NET platform. Last month, Microsoft made .NET 6 generally available—and hosted a virtual conference to celebrate its new features.
What were the goals of .NET 6? If you look at themesof.net, you can quickly see the themes of the .NET 6 release, which include some of the following:
We could spend the next 10 blog posts writing about all the new .NET 6 improvements and features. I’d love to do that, but I haven’t even started shopping for the holidays.
Instead, I’d like to show off some of my favorite things that I’ll be using on my .NET 6 projects. Most of these changes revolve around web development in ASP.NET Core 6 since this site focuses on those topics.
Way back in April, I wrote here about the Hot Reload capability in .NET 6. We’ve come a long way since then, but I felt the same as I do now: This is the biggest boost to a .NET web developer’s productivity over the last few years. If you aren’t familiar with Hot Reload, let’s quickly recap.
The idea of “hot reload” has been around for quite a few years: You save a file, and the change appears almost instantaneously. Once you work with hot reloading, it’s tough to go back.
As the .NET team tries to attract outsiders and new developers, not having this feature can be a non-starter to outsiders: It’s table stakes for many developers. The concept is quite popular in the frontend space, and .NET developers have been asking for this for a while. (Admittedly, introducing hot reload to a statically typed language is much more complex than doing it for a traditionally interpreted language like JavaScript.)
With .NET 6, you can use Hot Reload to make changes to your app without needing to restart or rebuild it. Hot Reload doesn’t just work with static content, either—it works with most C# use cases and also preserves the state of your application as well—but you’ll want to hit up the Microsoft Docs to learn about unsupported app scenarios.
Here’s a quick example to show how the application state gets preserved in a Blazor web app. If I’m in the middle of an interaction and I update the currentCount
from 0
to 10
, will things reset? No! Notice how I can continue increasing the counter, and then my counter starts at 10 when I refresh the page.
You can leverage Hot Reload in whatever way you prefer: Powerful IDEs like JetBrains Rider and Visual Studio 2022 have this capability. You can also utilize it from the command line if you prefer (yes, we do). It’s important to mention that this works for all ASP.NET Core Web apps.
Have you ever wanted to write simple APIs in ASP.NET Core quickly but felt helpless under the bloat of ASP.NET Core MVC, wishing you could have an Express-like model for writing APIs?
The ASP.NET team has rolled out minimal APIs—a new, simple way to build small microservices and HTTP APIs in ASP.NET Core. Minimal APIs hook into ASP.NET Core’s hosting and routing capabilities and allow you to build fully functioning APIs with just a few lines of code.
Minimal APIs do not replace building APIs with MVC—if you are building complex APIs or prefer MVC, you can keep using it as you always have—but it’s an excellent approach to writing no-frills APIs. We wrote about it in June, but things have evolved a lot since then. Let’s write a simple API to show it off.
First, the basics: Thanks to lambdas, top-level statements, and C# 10 global usings, this is all it takes to write a “Hello, Telerik!” API.
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello, Telerik!");
app.Run();
Of course, we’ll want to get past the basics. How can I really use it? Using WebApplication
, you can add middleware just like you previously would in the Configure
method in Startup.cs
. In .NET 6, your configuration takes place in Program.cs instead of a separate Startup
class.
var app = WebApplication.Create(args);
app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();
// ...
app.Run();
If you want to do anything substantial, though, you’ll want to add services using a WebApplicationBuilder
(again, like you typically would previously in the ConfigureServices
method in Startup.cs
):
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<MyCoolService>();
builder.Services.AddSingleton<MyReallyCoolService>();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() {
Title = builder.Environment.ApplicationName, Version = "v1" });
});
var app = builder.Build();
// ...
app.Run();
Putting it all together, let’s write a simple CRUD API that works with Entity Framework Core and a DbContext
. We’ll work with some superheroes because, apparently, that’s what I do. With the help of record types, we can make our data models a little less verbose, too.
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<SuperheroDb>(o => o.UseInMemoryDatabase("Superheroes"));
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() {
Title = builder.Environment.ApplicationName, Version = "v1" });
});
var app = builder.Build();
app.MapGet("/superheroes", async (SuperheroDb db) =>
{
await db.Superheroes.ToListAsync();
});
app.MapGet("/superheroes/{id}", async (SuperheroDb db, int id) =>
{
await db.Superheroes.FindAsync(id) is Superhero superhero ?
Results.Ok(superhero) : Results.NotFound();
});
app.MapPost("/superheroes", async (SuperheroDb db, Superhero hero) =>
{
db.Superheroes.Add(hero);
await db.SaveChangesAsync();
return Results.Created($"/superheroes/{hero.Id}", hero);
});
app.MapPut("/superheroes/{id}",
async (SuperheroDb db, int id, Superhero heroInput) =>
{
var hero = await db.Superheroes.FindAsync(id);
if (hero is null)
return Results.NotFound();
db.Update(heroInput);
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/superheroes/{id}",
async (SuperheroDb db, int id) =>
{
var hero = await db.Superheroes.FindAsync(id);
if (hero is null)
return Results.NotFound();
db.Superheroes.Remove(hero);
await db.SaveChangesAsync();
return Results.Ok();
});
app.Run();
record Superhero(int Id, string? Name, int maxSpeed);
class SuperheroDb : DbContext
{
public SuperheroDb(DbContextOptions<SuperheroDb> options)
: base(options) { }
public DbSet<Superhero> Superheroes => Set<Superhero>();
}
As you can see, you can do a lot with minimal APIs while keeping them relatively lightweight. If you want to continue using MVC, that’s your call—but with APIs in .NET, you no longer have to worry about the overhead of MVC if you don’t want it. If you want to learn more, David Fowler has put together a comprehensive document on how to leverage minimal APIs—it’s worth checking out.
Looking at the code sample above, it’s easy to wonder if this is all a race to see what we can throw in the Program.cs
file and how easy it is to get messy. This can happen in any app—I don’t know about you, but I’ve seen my share of controllers that were rife for abuse.
It’s essential to see the true value of this model—not how cool and sexy it is to write an entire .NET CRUD API in one file, but the ability to write simple APIs with minimal dependencies and exceptional performance. If things look unwieldy, organize your project as you see fit, just like you always have.
How often have you used custom middleware, libraries or solutions to log simple HTTP requests? I’ve done it more than I’d like to admit. .NET 6 introduces HTTP Logging middleware for ASP.NET Core apps that log information about HTTP requests and responses for you, like:
You can also select which logging properties to include, which can help with performance too.
To get started, add this in your project’s middleware:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpLogging();
// other stuff here, removed for brevity
}
To customize the logger, you can use AddHttpLogging
:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("X-Request-Header");
logging.ResponseHeaders.Add("X-Response-Header");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
}
If we want to pair this with a minimal API, here’s how it would look:
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("X-Request-Header");
logging.RequestHeaders.Add("X-Response-Header");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
app.UseHttpLogging();
app.MapGet("/", () => "I just logged the HTTP request!");
app.Run();
.NET 6 ships with many great updates to Blazor, the client-side UI library that’s packaged with ASP.NET Core. I want to discuss my favorite updates: error boundaries, dynamic components and preserving pre-rendered state.
Blazor error boundaries provide an easy way to handle exceptions within your component hierarchy. When an unhandled exception occurs in Blazor Server, it’s treated as a fatal error because the circuit hangs in an undefined state. As a result, your app is as good as dead, it loses its state, and your users are met with an undesirable An unhandled error has occurred message, with a link to reload the page.
Inspired by error boundaries in React, the ErrorBoundary
component attempts to catch recoverable errors that can’t permanently corrupt state—and like the React feature, it also renders a fallback UI.
I can add an ErrorBoundary
around the @Body
of a Blazor app’s default layout, like so.
<div class="main">
<div class="content px-4">
<ErrorBoundary>
@Body
</ErrorBoundary>
</div>
</div>
If I get an unhandled exception, I’ll get the default fallback error message.
Of course, you can always customize the UI yourself.
<ErrorBoundary>
<ChildContent>
@Body
</ChildContent>
<ErrorContent>
<p class="custom-error">Woah, what happened?</p>
</ErrorContent>
</ErrorBoundary>
If you’d like the complete treatment, check out my post from earlier this summer. It still holds up (even the MAUI Man references).
What happens if you want to render your components dynamically when you don’t know your types ahead of time? It previously was a pain in Blazor through a custom render tree or declaring a series of RenderFragment
components. With .NET 6, you can render a component specified by type. When you bring in the component, you set the Type
and optionally a dictionary of Parameters
.
<DynamicComponent Type="@myType" Parameters="@myParameterDictionary" />
I find dynamic components especially valuable when working with form data—you can render data based on selected values without iterating through a bunch of possible types. If this interests you (or if you like rockets), check out the official documentation.
Despite all the performance and trimming improvements with Blazor WebAssembly, initial load time remains a consideration. To help with this, you can prerender apps from the server to help with its perceived load time. This means that Blazor can immediately render your app’s HTML while it is wiring up its dynamic bits. That’s great, but it also previously meant that any state was lost.
Help has arrived. To persist state, there’s a new persist-component-state
tag helper that you can utilize:
<component type="typeof(App)" render-mode="ServerPrerendered" />
<persist-component-state />
In your C# code, you can inject PersistComponentState
and register an event to retrieve and ultimately persist the objects. On subsequent loads, your OnInitializedAsync
method can retrieve data from the persisted state—if it doesn’t exist, it’ll get the data from your original method (typically a service of some sort).
To see it in action, check out the Microsoft documentation.
Along with .NET 6, we’ve also got a new version of C#—C# 10. It ships with some great new features, like file-scoped namespaces, global usings, lambda improvements, extended property patterns, null argument checks and much more. Check out Joseph Guadagno’s blog post for more details, as well as Microsoft’s blog post.
]]>Health checks are part of the middleware and libraries provided by ASP.NET Core to help report the health of application infrastructure components.
Because through them we can monitor the functioning of an application in real time, in a simple and direct way. ⚕️
To know if an API is running in a healthy way or not, we use a health check to validate the status of a service and its dependencies through an endpoint in the API of the REST service.
This allows us to quickly and in a standardized manner decide if the service or our dependences is off.
This endpoint uses a separate service that assesses the availability of the functions of the rest of the system and also the state of its dependencies.
The information collected during the check can include performance calculations, runtime or connection to other downstream services. After completing the evaluation, an HTTP code and a JSON object are returned depending on the evaluation of the services in the health check.
Now that we know the basics about health checks, we can implement an example and see in practice how it works.
You can access the full source code here.
Open a PowerShell console in the folder where you want to create the project, then give the command below. This command will create an ASP.NET 5 Web API project with the name “HealthCheck.” Once it’s created, you can open the file “HealthCheck.csproj” with Visual Studio.
dotnet new webapi -n HealthCheck --framework net5.0
Then create a new controller named “HealthController” and add the following code:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using System.Net;
using System.Threading.Tasks;
namespace HealthCheck.Controllers
{
[Controller]
[Route("health")]
public class HealthController : ControllerBase
{
private readonly ILogger<HealthController> _logger;
private readonly HealthCheckService _service;
public HealthController(ILogger<HealthController> logger, HealthCheckService service)
{
_logger = logger;
_service = service;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var report = await _service.CheckHealthAsync();
_logger.LogInformation($"Get Health Information: {report}");
return report.Status == HealthStatus.Healthy ? Ok(report) : StatusCode((int)HttpStatusCode.ServiceUnavailable, report);
}
}
}
Our controller will contain the method responsible for checking the API health. When it receives a request, it will check it, and then it will return a JSON with the response content and, as a good practice, we added a method to log the execution.
Open the file “Startup.cs” and inside it find the method “ConfigureServices”. Inside it, add this code snippet:
services.AddHealthChecks();
Now you can start the application, and you will see the /health route that we just created. You can use Fiddler to make the request like in the image below:
When we sent a request to the /health route, the application returned a JSON object with some information:
Entries: A dictionary-type object in this case is empty.
Status: 2 - Derives from the “HealthStatus” enum and as the summary means: “Indicates that the health check determined that the component was healthy.”
TotalDuration: Health Check runtime information.
In simple terms, our API is “healthy”—no problems were found and we now have a route just to check this.
In addition to the integrity of the application, we can also check other basic factors such as the connection to a database.
In this case, we will use Redis as a database. You need to have it running on your machine in a Docker image or directly. If you want you can use any other database just change the connection string.
For that, we need to install the package: “AspNetCore.HealthChecks.Redis” - Version=“5.0.2”.
You can install it in the project with NugetPackage or from the console with the command:
dotnet add package AspNetCore.HealthChecks.Redis
Now let’s create a “Helper” class where we’ll put the connection string with Redis. Then create a folder called “Helpers” in the project, and inside it create a static class called “UtilsHelpers” and inside it put the following code:
public static string GetConnectionString()
{
return "localhost:6379";
}
In the file “Startup.cs” add the method responsible for verifying the connection with Redis. It will use the connection string that we just created.
So the Startup’s “ConfigureServices” method should look like this:
public void ConfigureServices(IServiceCollection services)
{
//Here is HealthCheck and the connection to Redis
services.AddHealthChecks()
.AddRedis(redisConnectionString: UtilsHelpers.GetConnectionString(), name: "Redis instance");
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "HealthCheck", Version = "v1" });
});
}
If your connection to Redis or another database you have used is OK, when you make the request through Fiddler, we will get the following result, showing the information about the connection:
Another interesting function that the ASP.NET Core health checks provide is a graphical interface with a kind of fun dashboard so that we can view the events that took place during the checks and the history of the entire execution.
So, let’s implement it and see this working. For that, we need to install the following dependencies in the project:
Now at the “Startup” of the project, we will add the configurations of the libraries that we just installed in the project, then replace the method “ConfigureServices” with this one below. You can see in the comments the responsibility of each configuration.
public void ConfigureServices(IServiceCollection services)
{
//Here is HealthCheck and the connection to Redis
services.AddHealthChecks()
.AddRedis(redisConnectionString: UtilsHelpers.GetConnectionString(), name: "Redis instance");
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "HealthCheck", Version = "v1" });
});
// Here is the GUI setup and history storage
services.AddHealthChecksUI(options =>
{
options.SetEvaluationTimeInSeconds(5); //Sets the time interval in which HealthCheck will be triggered
options.MaximumHistoryEntriesPerEndpoint(10); //Sets the maximum number of records displayed in history
options.AddHealthCheckEndpoint("Health Checks API", "/health"); //Sets the Health Check endpoint
}).AddInMemoryStorage(); //Here is the memory bank configuration
}
And the “Configure” method replace it with this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "HealthCheck v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
//Sets the health endpoint
endpoints.MapHealthChecks("/health");
});
//Sets Health Check dashboard options
app.UseHealthChecks("/health", new HealthCheckOptions
{
Predicate = p => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
//Sets the Health Check dashboard configuration
app.UseHealthChecksUI(options => { options.UIPath = "/dashboard"; });
}
Our dashboard is almost ready to work. Now, in the “UtilsHelpers” class, add the following method:
public static string ToJSON(this object @object) => JsonConvert.SerializeObject(@object, Formatting.None);
Important! To use the “SerializeObject” method, you need to install “Newtonsoft.Json” - Version=“13.0.1” as dependency.
And now, in the “HealthController” replace the “Get” method with this:
[HttpGet]
public async Task<IActionResult> Get()
{
var report = await _service.CheckHealthAsync();
var reportToJson = report.ToJSON();
_logger.LogInformation($"Get Health Information: {reportToJson}");
return report.Status == HealthStatus.Healthy ? Ok(reportToJson) : StatusCode((int)HttpStatusCode.ServiceUnavailable, reportToJson);
}
Finally, we can see our dashboard. For that, start the application and go to “localhost:PORT/dashboard”. If you followed all the previous steps, you will see in your browser this beautiful dashboard with the verification data:
An interesting feature is the possibility of customizing the checks, choosing how we want to return the results.
For this we need to create a class that will inherit the interface “IHealthCheck”. Then create a folder called “Custom” and inside it create a class named “CustomHealthChecks” and put the code below in it:
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace HealthCheck.Custom
{
public class CustomHealthChecks : IHealthCheck
{
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var catUrl = "https://http.cat/401";
var client = new HttpClient();
client.BaseAddress = new Uri(catUrl);
HttpResponseMessage response = await client.GetAsync("");
return response.StatusCode == HttpStatusCode.OK ?
await Task.FromResult(new HealthCheckResult(
status: HealthStatus.Healthy,
description: "The API is healthy (。^▽^)")) :
await Task.FromResult(new HealthCheckResult(
status: HealthStatus.Unhealthy,
description: "The API is sick (‘﹏*๑)"));
}
}
}
In this class, we are creating a method that makes a request to a “cat” API and returns the result with a funny Kaomoji.
But it’s not done yet—we need to do the class dependency injection.
So at startup, we’re going to add the check in the class right after the Redis check, so the “ConfigureServices” method should look like this:
public void ConfigureServices(IServiceCollection services)
{
//Here is HealthCheck and the connection to Redis
services.AddHealthChecks()
.AddRedis(redisConnectionString: UtilsHelpers.GetConnectionString(), name: "Redis instance")
.AddCheck<CustomHealthChecks>("Custom Health Checks"); //Here is the custom class dependency injection
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "HealthCheck", Version = "v1" });
});
// Here is the GUI setup and history storage
services.AddHealthChecksUI(options =>
{
options.SetEvaluationTimeInSeconds(5); //Sets the time interval in which HealthCheck will be triggered
options.MaximumHistoryEntriesPerEndpoint(10); //Sets the maximum number of records displayed in history
options.AddHealthCheckEndpoint("Health Checks API", "/health"); //Sets the Health Check endpoint
}).AddInMemoryStorage(); //Here is the memory bank configuration
}
Now we can start the application again and we will have the following result in the dashboard:
In this article, we saw the importance of doing the health check in our APIs and how to implement it in a simple way with health check resources. We also learned how to use the dashboard’s graphical interface and customize the results.
I hope this article is helpful in creating your health checks! See you soon.
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
Most .NET developers are looking forward to .NET Multi-platform App UI (MAUI)—the evolution of Xamarin.Forms with .NET 6. Going forward, developers should have much more confidence in the technology stack and tools as .NET MAUI empowers native cross-platform solutions on mobile and desktop.
While it is a long flight until we reach the sands of MAUI, developer excitement is palpable in all the news/content as we tinker and prepare for .NET MAUI. Like the grains of sand, every piece of news/article/video/tutorial/stream contributes towards developer knowledge and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here's what is noteworthy for the week of November 29, 2021:
.NET developers building web apps are understandably excited about Blazor—C# code front and back with familiar Razor syntax and productive tooling. With .NET MAUI, the story gets better with Blazor goodness now welcome on native cross-platform apps for mobile and desktop. Eilon Lipton did an awesome session at .NET Conf covering the promise of Blazor on native apps—powered by .NET MAUI.
Developers get to write true Blazor code and bring in Razor Class Libraries into native apps bootstrapped by .NET MAUI—all possible with the modern light weight BlazorWebView component, while maintaining full native device API access. This promise of Blazor on mobile/desktop with .NET MAUI should be the foundation of migrating/modernizing older apps while sharing code with web apps—the future looks good!
Nish Anil and Vivek Sridhar hosted the latest Microsoft Reactor show called SamosaChai.NET—what better way to learn .NET than over the classic Indian snack time. The guest was none other than James Montemagno who talked through building mobile/desktop apps with .NET MAUI and Blazor.
Over friendly banter, James walked through the .NET MAUI basics, from getting started with the templated solutions to building the complex .NET Conf podcast app. If you are still on the fence about .NET MAUI, this is a great starting point to see the future of cross-platform app development with .NET.
Matt Soucoup hosted the latest .NET MAUI podcast and invited James Montemagno and David Ortinau for company. On the cards was celebrating all things .NET 6—the release, tooling, .NET Conf and of course, .NET MAUI. When friends hang out live on air, they share customer stories and quality ramblings about the state of modern .NET.
Key takeaways include developer flexibility with .NET—the right tools for the right job without being forced into it. Client developers with .NET have a native desktop and mobile technology stacks to reach just about any device. Web developers doing .NET could be doing some flavor of ASP.NET or Blazor, but many enterprises also have investments in JS stacks with Angular/React—all of which is now welcome in cross-platform native apps with .NET MAUI. Choice in technology stack is a good thing and .NET developers love the flexibility.
DotNetCurry, better known as 'DNC', produces a free digital magazine publication bringing the latest from the .NET/JavaScript worlds, presented by Microsoft MVP's and industry veterans. DNC Magazine recently hit the 50th edition—big congratulations are due for continued efforts to maintain quality and reaching the milestone. The 50th edition does not disappoint and is packed with loads of .NET/JS content, including big coverage of .NET MAUI.
Gerald Versluis turned off his usual camera/microphone and took to the keyboard to write up a piece of what developers can expect with .NET MAUI. Gerald covers the .NET MAUI basics, the new Handler architecture, Host Builder model, bringing in Blazor goodness and several other benefits that .NET MAUI brings to the table. Going offline for a bit? This 50th edition DNC Magazine is a must to download and soak in all the latest developer content.
For good reason, the MVVM design pattern works well for XAML/C# codebases and much of the core features are supported out of the box in Xamarin.Forms/.NET MAUI. When you need just a little bit more help, but want to stay away from heavier MVVM frameworks, you may look at TinyMvvm, an open-source light-weight MVVM library custom built for Xamarin.Forms.
Wondering what the future holds with TinyMvvm with .NET MAUI? Developer Daniel Hindrikes has you covered. After the 3.0 release, the first preview of TinyMvvm for .NET MAUI is now out and ready for you to give things a spin. Not surprisingly, the MauiAppBuilder Host Builder pattern to bootstrap .NET MAUI apps works well with dependency injection—it would be really simple to use an extension method with a resolver and get rolling using TinyMvvm for .NET MAUI apps.
That's it for now.
We'll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
Most .NET developers are looking forward to .NET Multi-platform App UI (MAUI)—the evolution of Xamarin.Forms with .NET 6. Going forward, developers should have much more confidence in the technology stack and tools as .NET MAUI empowers native cross-platform solutions on mobile and desktop.
While it is a long flight until we reach the sands of MAUI, developer excitement is palpable in all the news/content as we tinker and prepare for .NET MAUI. Like the grains of sand, every piece of news/article/video/tutorial/stream contributes towards developer knowledge and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here's what is noteworthy for the week of November 22, 2021:
Hot off the heels of .NET 6 launch at .NET Conf, three developer advocate stooges invited an old friend to relive all the excitement: Ed Charbeneau, Alyssa Nicoll, Sam Basu and Jeff Fritz hosted the Future of .NET webinar.
This was a fun 2 hours breaking down all the big announcements from a developer's perspective and whipping up quick demos to showcase the hot bits. Discussions evolved around the significance of .NET 6, VS 2022 launch, C# 10 features, .NET MAUI updates and bringing Blazor goodness to desktop with hybrid apps. With .NET 6 carrying the LTS badge, migration and modernization would be top of mind for lot of existing apps—it was good to see an honest conversation about all the options on the table.
How can a .NET MAUI release go by without some expected YouTube goodness? Gerald Versluis put out a video for all things .NET MAUI Preview 10 and recapped some tooling goodness with VS 2022. Gerald also went on to cover the sweet cross-platform real-time podcast app demo from .NET Conf keynote, showcasing the best of code sharing with .NET MAUI and Hybrid apps with Blazor.
One call to action is clear—if you haven't already, now is a great time to get started with .NET MAUI. The promise is coming together nicely.
James Montemagno and Frank Krueger hosted the latest episode of the Merge Conflict podcast, diving into all the details of .NET 6 and Visual Studio 2022 releases.
While developer excitement is palpable, it was good to see the acknowledgement that there is a lot to take in—developers may need some time to settle in with the new .NET bits and Azure cloud services. James shared some good info on some of the behind-the-scenes work that went in towards making the cross-platform podcast demo app for .NET Conf—something soon to be open sourced for developers to tinker with.
There was a ton of content from passionate developers from around the world at .NET Conf—and some real gems for those interested in .NET MAUI. Javier Suarez did a session on Drawn Controls in .NET MAUI, diving into much of the awesome work that him and the team has been putting together.
Javier started with the basics of .NET MAUI and Microsoft.Maui.Graphics library, giving developers the freedom to render native UI per their needs. Javier then dived into the meat of things—the goodness evolving from the Microsoft.Maui.Graphics.Controls library.
While experimental, this new cross-platform graphics library allows developers to render fully drawn UI components with .NET MAUI, catering to popular design systems like Cupertino, Fluent and Material. Javier showed off some cool demos and talked through performance and extensibility of drawn controls—definitely a wonderful development within the .NET MAUI stack.
Luis Matos continues his excellent series on the MauiAppBuilder—this time diving into much of the code that now powers the bootstrapping of .NET MAUI apps using the generic .NET Builder pattern.
Luis talks about how to initialize a MauiAppBuilder instance using a Static method with default configurations and dives into the MauiAppBuilder Public API. This API is where a lot of the plumbing happens—lot of properties/configurations and a single method called Build() which creates the MauiApp. Luis dives into some tricky internal code unapologetically and teaches us a lot—looking forward to the rest of the series.
That's it for now.
We'll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>Application Programming Interfaces (APIs) are basically HTTP services that are used to communicate between applications in a simple and centralized way.
Microsoft through the ASP.NET framework provides ways to build Web APIs that can be accessed from any client, such as browsers, desktop applications and mobile devices.
ASP.NET Web API can be used to build REST and SOAP services.
Following are some benefits of working with an ASP.NET Web API:
An ASP.NET Core Web API basically consists of one or more controller class that derives from ControllerBase. The ControllerBase class provides many methods and properties that are useful for working with HTTP requests.
As you can see in the image above, a “client” makes an “HTTP request” to the API, which—through the “controller”—identifies the call and makes the Read or Write in the “data access layer.” The “Model” is returned, in this case, a JSON object “Contact: Name” in the “HTTP response.” In simple terms, the API is bridging the “client” and the “data” in a simple and safe way.
Example console API response
Now that we’ve seen the basics of Web APIs, let’s create an API and see in practice how it works.
To create an ASP.NET Core 5 Web API application, we will use:
.NET SDK: The .NET SDK is a toolkit for developers that you’ll need to start developing in the .NET platform. You can download the version here (the .NET 5.0 is recommended because it already contains the anterior versions).
Visual Studio 2019: You can download the Community Version here—it’s free and contains all of the features you need to create, test and deploy a Web API application.
You can download the project’s source code here.
Below we will have some steps to build our application:
Open the Visual Studio 2019 → Click on “Create a new project.”
Choose option “ASP.NET Core Web API.” Click “Next.”
Write the project name (my suggestion is “MyReadingList.WebAPI”) and the solution name folder (my suggestion is “MyReadingList”), then Click “Next.”
In the “Target Framework” choose “.NET 5.0”, and Click “Create.”
By default, our newly created API comes with the basics to run it, with an example controller. If you click on “IIS Express” or press the “F5” key on your keyboard, the application will start and can be accessed through the URL:
https://localhost:44345/swagger/index.html
The GIF below shows the execution of the procedure.
When we created our API, it already had an example called “WeatherForecast” that you just ran, but let’s not waste time with that—we’ll make our own example API: a reading list and then we’ll add our favorite books.
First, let’s create our “Book” Model class, which is a class that represents a “Book” entity. To do this, right-click on the project and add a folder called “Models” and then within Models create a class called “Book”.
public class Book
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string Genre { get; set; }
public bool Read { get; set; }
}
The context class is responsible for interacting with data objects. It manages the entity objects during runtime, which includes filling object values with data coming from a database, tracking changes made and persisting the data to our database.
One way to work with the “context” paradigm is to define a class that derives from DbContext and exposes the model class as a property of DbSet.
The Entity Framework allows us to query, insert, update and delete data using objects known as entities. It maps the entities and relationships that are defined in your entity model and provides functions to perform the following tasks:
In this project, we will use a database called SQLite, which is a C-language library that implements a small, fast, self-contained, highly reliable and full-featured SQL database engine.
We need to install the following packages in the project:
You can do this through the NuGet package manager.
Then still inside the Models folder, create a class called “BookContext” and put the following code in it:
public class BookContext : DbContext
{
public BookContext(DbContextOptions<BookContext> options) : base(options) { }
public DbSet<Book> Books { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Book>().HasKey(b => b.Id);
base.OnModelCreating(builder);
}
}
With this code, we define that “Book” is our context class, which will receive in the database an entity of the same name and will have its properties (name, author, etc.) as columns in the book table.
We also defined that the Id will be the primary key of the table through the OnModelCreating
method.
Let’s create our connection string, which will open a connection to the database we’ll call “ReadingList.db”.
Open the archive “appsettings.json” and put this code before “Logging”:
"ConnectionSqlite": { "SqliteConnectionString": "Data Source=ReadingList.db" },
ASP.NET Core implements dependency injection by default. Now that we have created our Context class, we need to do the dependency injection of this class. ASP.NET Core allows us to do the injection when our application is started.
To do this, open the Startup.cs file and replace the ConfigureServices method with this:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "MyReadingList.WebAPI", Version = "v1" });
});
var connection = Configuration["ConnectionSqlite:SqliteConnectionString"];
services.AddDbContext<BookContext>(options => options.UseSqlite(connection));
}
Now that we have everything set up, we can create the database from the model using “Migrations.”
The migrations feature enables you to make changes to your model and then propagate those changes to your database schema. Migrations are enabled by default in EF Core.
The process is very simple. Go to the folder where the project was created, open a console and enter the commands below.
dotnet ef migrations add InitialModel
And then:
dotnet ef database update
The first command is to support migration and create the initial set of tables for the model. The second is to apply the migration to the database.
Important! If while running the commands you get any errors related to the version of EntityFramework, run this command in the console:
dotnet tool update --global dotnet-ef --version 5.0.9
If everything worked out, you will see the database created at the root of the project—where you opened the console, in the file “ReadingList.db”, that’s where our database is. To open this file and see the tables created as in our model, you will need to download an SQLite-compatible app. If you use Windows, I recommend the “SQLite Viewer Editor”—it is free and can be downloaded directly from the Microsoft Store.
The database in "SQLite Viewer Editor"
In addition to the “Books” table, we also have the “__EFMigrationsHistory” which is automatically created when we apply Migrations and is used to track change versions, like a history.
Now we are going to create a controller to be able to do CRUD operations in our database. To do this, perform the following steps:
using Microsoft.AspNetCore.Mvc;
using MyReadingList.WebAPI.Models;
namespace MyReadingList.WebAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BooksController : Controller
{
private readonly BookContext _context;
public BooksController(BookContext context)
{
_context = context;
}
}
}
With this code we made the context dependency injection in the controller. Next we will implement the methods responsible for performing the operations (CRUD):
HTTP Method | Route | Description | Request body | Response body |
---|---|---|---|---|
GET | /api/books | Get all books | None | Array of books |
GET | /api/books/read=true | Get all books read | None | Array of books |
GET | /api/books/{id} | Get a book by Id | None | Book |
POST | /api/books | Add a new book | Book | Book |
PUT | /api/books/{id} | Update an existing book | Book | None |
DELETE | /api/books/{id} | Delete a book | None | None |
Following the order in the table above, we will implement the API methods responsible for doing CRUD operations in the database. Still in “BooksController,” you can put this code right below the dependency injection:
//Get all books
[HttpGet]
public async Task<ActionResult<IEnumerable<Book>>> GetBooks()
{
return await _context.Books.ToListAsync();
}
//Get all books read
[HttpGet("read")]
public async Task<ActionResult<IEnumerable<Book>>> GetBooksRead()
{
bool read = true;
var books = await _context.Books.ToListAsync();
var booksRead = (from book in books where book.Read == read select book).ToList();
return booksRead;
}
//Get a Book by id
[HttpGet("{id}")]
public async Task<ActionResult<Book>> GetBook(string id)
{
Guid guidId = Guid.Parse(id);
var book = await _context.Books.FindAsync(guidId);
if (book == null)
return NotFound();
return book;
}
//Add a new book
[HttpPost]
[Route("create")]
public async Task<ActionResult<Book>> Create(Book book)
{
_context.Books.Add(book);
await _context.SaveChangesAsync();
return CreatedAtAction("GetBook", new { id = book.Id }, book);
}
//Update an existing book
[HttpPut("{id}")]
public async Task<IActionResult> Update(string id, Book book)
{
if (id != Convert.ToString(book.Id).ToUpper())
return BadRequest();
_context.Entry(book).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!BookExists(id))
return NotFound();
}
return NoContent();
}
//Delete an existing book
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(string id)
{
Guid guidId = Guid.Parse(id);
var book = await _context.Books.FindAsync(guidId);
if (book == null)
return NotFound();
_context.Books.Remove(book);
await _context.SaveChangesAsync();
return NoContent();
}
//Check if the book exists in the database
private bool BookExists(string id)
{
return _context.Books.Any(e => Convert.ToString(e.Id) == id);
}
Now we have the basics we need to create, update, delete and fetch books from the database. To do this, first, run the project by clicking on the run icon in Visual Studio or pressing the “F5” key.
To do the operations we will use Fiddler Everywhere, which can be used to make HTTP requests to Web APIs simply and quickly, and has many other features.
Follow the steps in the image below to add a book to the database via the Create method of the API. Afterward, you can open the ReadingList.db file with SQLite Viewer Editor and see the record in the table.
Important! The example images will have the localhost port set to 44345, but you must change it based on the port your application runs on.
Now that we have inserted our book (you can insert as many as you like, just edit the data sent in the “body”), we can search them through the “GET” route.
For Update, in Fiddler Everywhere create the method “Update book,” in the contents of the “Body” change the data from “read” to “true” and click on “Send.”
The record has now been changed to “read” and can be fetched on the next route.
We will only look for books that have already been read. For that we will use another route, and this route will only return records that have the property “read”=“true”, as you can see in the image below:
To search for a single specific book, we will use the same “GET” route, but passing in the route the Id of the book we want to see details.
To delete a record is very simple—just pass the id of the record you want to delete in the route, as in the example below:
Finally! Our API is 100 percent functional! ✨
In this article, we looked at the basics of ASP.NET Core Web APIs, created a project using Visual Studio, added a database, and performed the four basic operations (CRUD) with Fiddler Everywhere.
Now you can fill your list with your favorite books. Feel free to add new fields and features.
In the next post on APIs we will develop a frontend application and integrate it with our API to display the records. See you soon! ♂️
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
Most .NET developers are looking forward to .NET Multi-platform App UI (MAUI)—the evolution of Xamarin.Forms with .NET 6. Going forward, developers should have much more confidence in the technology stack and tools as .NET MAUI empowers native cross-platform solutions on mobile and desktop.
While it is a long flight until we reach the sands of MAUI, developer excitement is palpable in all the news/content as we tinker and prepare for .NET MAUI. Like the grains of sand, every piece of news/article/video/tutorial/stream contributes towards developer knowledge and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here's what is noteworthy for the week of November 15, 2021:
Welcome to .NET 6. After a year of work from the .NET teams and the developer community, .NET 6 is out in full glory and proudly carries the Long Term Support (LTS) badge. Richard Lander wrote up the epic .NET 6 announcement post and the key point to take away is massive gains in performance.
.NET 6 is the first .NET release that natively supports Apple Silicon for MacOS and Windows Arm64, paving the path for .NET apps to run on new frontiers. .NET 6 is a massive unification effort with web, cloud, desktop, IoT and mobile apps all using the same .NET Libraries—this makes it easy for developers to share code easily across apps/platforms.
Tooling for .NET 6 development gets better across the board, with Hot Reload support everywhere and tons of new language features in C# 10 and F# 6. Just one word sums it all up: yay!
Sitting pretty on top of stable .NET 6 LTS runtime is the next iteration of .NET MAUI—Preview 10 is now out. David Ortinau wrote up the post announcing .NET MAUI Preview 10. The key to note here is how easy it is to get started. The best developer experience with .NET MAUI is through the latest Visual Studio 2022 Preview 17.1, which shipped alongside the GA VS 2022 17.0 version.
All one has to do to get started is to install the 'Mobile development with .NET' workload during VS 2022 setup—all of the .NET MAUI dependencies and mobile platform runtimes/SDKs/simulators are included with a simple checkbox.
.NET MAUI Preview 10 release brings in the Handler implementations of the popular CollectionView and IndicatorView controls, as well as property implementations and improvements with a bunch of other UI controls. The .NET MAUI GA goal is looking closer every single day with platform and tooling updates.
Modern .NET is the developer platform for building anything for anywhere and nothing celebrates .NET quite like .NET Conf. In its 11th year, .NET Conf was held Nov 9-11 this year—2 days of awesome content from Microsoft folks, before a full 24 hours of non-stop livestream with passionate community speakers from all around the world.
Scott Hunter opened .NET Conf with a wonderful keynote, tapping into some well-known faces from the .NET team and together, they did kick up the excitement around the .NET ecosystem. The keynote covered a plethora of topics—.NET 6, C# 10, Minimal APIs, Blazor updates, .NET MAUI updates, Hybrid Apps with Blazor/.NET MAUI, Azure support and a whole lot more. Want to get the latest scoop on .NET? This is the keynote to start with.
After the .NET Conf keynote, Maddy Leger Montaquila took the stage to talk about something dear to all our hearts—all things.NET MAUI. Maddy started with the basics and provided the latest updates with .NET MAUI Preview 10, including the ease of development with Windows Subsystem for Android.
Tooling for .NET MAUI is catching up fast. While Maddy may be a little uncomfortably fond of her Mac, Hot Reload (both XAML and C#) is starting to work just about everywhere. Add the promise of Hybrid apps bringing Blazor goodness and code sharing into desktop, you can see why developers and enterprises cannot wait for the .NET MAUI GA release coming early next year.
No matter the platform or tooling, developer experience is largely shaped by the programming language—C# does not disappoint for .NET MAUI. Along with .NET 6 and VS 2022 launch comes the next language update—welcome to C# 10. Kathleen Dollard wrote up the C# 10 announcement post—covering all the features that make your code run faster and be more prettier/expressive.
The plethora of improvements in C# 10 include some key features that aid in big mobile/cross-platform projects—such as Global Usings, Implicit Usings, File-scoped namespaces, Improvements for Lambda expressions, better parity between Structs and Classes and more. C# 10 is here to allow .NET MAUI developers write cleaner and more easily maintainable code.
That's it for now.
We'll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>With the R3 2021 official release of Telerik UI for Xamarin, we introduced a new feature in our RichTextEditor control. This feature gives you the option to work with images. You can quickly and easily add, edit and remove images in your mobile and desktop apps. In addition, these options come with built-in toolbar items.
This blog post will get you familiar with all the built-in tools you can use to make your work with images in the document easier. You can work with the following image formats: PNG, JPEG, SVG, GIF, WebP.
Let’s review the power of the built-in toolbar items for working with images. Of course, we have prepared a sample demo for you!
The built-in Toolbar items for working with images are:
When the AddImageToolbarItem is tapped/clicked, a PickImage event is fired. If you want to work with images from the device gallery, then you have to grant permissions. You need to manually implement the logic for selecting an image inside the PickImage event handler. The steps needed for permissions are described in our help article.
A sample demo with permissions can be found in our SDK Browser Application and Telerik UI for Xamarin Samples Application.
Mainly the EditImageToolbarItem helps you to resize the current selected image. If you haven’t selected one, the toolbar allows you to pick an image (the RichTextEditor.PickImage event is fired) using the PickButton.
The edit image dialog is highly customizable. For more details visit our help topic.
CutToolbarItem, CopyToolbarItem, PasteHtmlToolbarItem and RemoveImageToolbarItem work in the scenario when there is a selected image. You can cut, copy, paste or remove the currently selected image.
For the demo I will use the ImagePickerToolbarItem. As I shared, this toolbar item can be populated with predefined images.
Here are the RichTextEditor and the RichTextEditor Toolbar definitions in XAML:
<
Grid
RowDefinitions
=
"*,Auto"
>
<
telerikRichTextEditor:RadRichTextEditor
x:Name
=
"richTextEditor"
/>
<
telerikRichTextEditor:RadRichTextEditorToolbar
x:Name
=
"richTextToolbar"
Grid.Row
=
"1"
RichTextEditor
=
"{x:Reference richTextEditor}"
AutoGenerateItems
=
"False"
>
<
telerikRichTextEditor:ImagePickerToolbarItem
x:Name
=
"imagePicker"
Text
=
"Select"
/>
</
telerikRichTextEditor:RadRichTextEditorToolbar
>
</
Grid
>
Our HTML document:
<
html
>
<
head
/>
<
body
>
<
h1
>Sign in for the tournament!</
h1
>
<
p
>Legend:</
p
>
<
p
>Will attend: <
img
src
=
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADdYAAA3WAZBveZwAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAHvSURBVEhLtVTPK0RRGP1E+ZEfSdmwsRDZECU7xR9gI0uxUVYWFpaTkrK1tZSS7PwoG1YzzE9GgzRqshBNmoWkjHzXueOje98808y8ceqrd+853zn3vnffpf9ARNFMmOkxxJSMMY3KdOVwytQN82xYkdKF5zuhKgfsYPsnQELSQlUGUUVDMGVHyIrQlQEMj8wA7OoZ36dFaO84YxqzAlBBpkWhvUMpqsKqQ2YAdnUfYKoXiXcgYNIM0BVlmhXaO04U1SDk1gzALq6wu2qReEdI0ZwZkCumCaG9AyenAat+MAMwDuhvJBLvwIqXzAAJcb9GIB7U5E4J7/FSUSv6MlYI077QNmDuM0THONttQhUE+tYcAZ/4V/qFtgGxtRqMk6geoV1xztQB0zezD+NNofMBMmaJvxsyOOfjIskDFrFh6jF+v2DqEjofuO/7YJoym6Qxi/l5kf3Cr6gX8x8O7brQf8PP1I7GgNloGugfTqR657uWhulF9wtdGClFdTDcsgykMH9ww9QEw2E8W1c5DsqyWBQH/RPBxOc0yhVTAvPWbjFO40Q1S3tpiDBNwdQ+PS4F3YK0lAcYjCDoyc1cF3aROmSqFXn5wKvoRFDcLQTz0yLzjoSiRqx6zxEQL+UKKgraEMarqFfUdVDRgFBFgOgLiDAiqWaRTWAAAAAASUVORK5CYII="
/></
p
>
<
p
>Won't attend: <
img
src
=
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADdYAAA3WAZBveZwAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAADqSURBVEhLvdbBDcIwDAVQj9Z70jV64cCBuXroPh2AKVLsJl9IoSaxS/mSUUmCHxBQQxuFIVFYuZ4bjRP9INJH+klf6U/5Im4ofn4va12R11f9VhnkT/AeLBMuqAZKr6d8XVM9USZN0BGQK+QtSBRvXKlekGh87Asa0YCPN+qFugHECpkBpBdyA0gLOg0gOhSXeiyPGwFEg+pyA0gLOg0gjMzHQFzKknPRNhnV+4dV0wJQbkgDeHw+2iMz9AXYN1n7MXRDLQBxQ70AYoasANINeQGkCf3lzsiT19/j+eH604qci+SC66JzVxhet9WBr/JOEy0AAAAASUVORK5CYII="
/></
p
>
<
p
>Count on me: <
img
src
=
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAVCAYAAACzK0UYAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAN1QAADdUBPdZY8QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMS4xYyqcSwAAAg9JREFUSEutVU1PU0EUPbAxiBGCK1ckFdrXmQcaSIh/gPgD1IV/AYyR31OUDWzcuHAD7CQmJsCKsJACfV99NDGYuKkNLaWc+zpNaDKAbd9NTua9d889982duTPoWAWzoz5yr32orwF0JYCq8Tni8xc+vz3F/JihJnaOhcf0vxG/4dUkTuIj6hxCPTLUtp0iM+Yhv34Gt1bGTCuE2woIGWO+l+HWI6gtD1lH+CXkcky8WYaui/8mX+JFx0d+w8PkeJIgxMsRH/oz/6IpxLsQQhdDqHccj2z+buhmBL0m+pyFs8iXqp3YDT8Zdb093g/OtFqCfoUA+UJsIaSBtq5aBUt13Klp2hBd6heZRP2zEdICk1RZLvXX5kwLHvQfWZMfkcWZBrj1ORP1HR6cFS7QlY00KNgvbAv9ESfITzPjiY00KKh7zCTP0AKG2J0f2GANG7F/6EsPakX0k66/wtSDEs8cqaE9oDe0ddS3GE8fJgk6FmA6U4H7c9CekXjq7PL4mTLS3RbCcaV5+k1kmu8Xy/TCSNothjMXQ+/1uq2lRGfQ+z7jjdTdJlPl3+z0MiP2ww4P26yR+D/jpTPBRAUmurgtmXwXP3fSpzKcJya0Nyty13GdlngV/LYlke8sz7LwTEh/xn0+HCE7yxJuc60asla8Jxp83wqRmxG/oQ5uHp6PU/g9a3/Axl2SK9u47jHgGrx8LucFX4aOAAAAAElFTkSuQmCC"
/></
p
>
<
p
>Maybe, not sure <
img
src
=
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAN1QAADdUBPdZY8QAAABh0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMS4xYyqcSwAAAuFJREFUSEu1Vs1u00AQdiPgAu0FIU4k9a6jlsCNp2iKuPECHDigpk28doJQIfAibbn15wFatc2dA4q9azdOOUJJJWguERARVTLfbtyiUKM0aTLSKFl7Z8bz981osVQuJzJP/RspU8xSS+R0i2/ozBWEuU3K+C+d8aZuco/YYpMwsZgy67PyvpSLNPShcphIsmqGML4M3oESH78NYrotGOng/6n67Z4b0fsdkhevkzk/I+UjTfF0l7k3SaGapRZfgfAXo1gL06V6aBQPQsP2Q8MSf1me8bz7vhbi/hFlYpUURDbzwr8VqeylmWfBZIpV5/BVu9SuddLFIFLIe5Vf4Og97tNi0EE49/S8mL9tB5OR6ojK4TUiDVieMmBY3j+KLsueMkSYt5tifE7qjSyEEwZygOSuGKV6e3gDEdueDGFbN901laMwnNC05x+vo1JegY+ky7GCA7IMtSoKU5RV1SWZj0oS2xTJixMYhlEACFstxIdXaN55oMk+ICY/MEqHuNAvyZdl6EHVwZu6zpwFjZpiCzXfMGyUaazAkIzyxscfI0rrGuLm49C6csIvsCeNtHQmhAaXmvDkd/zFq7HUi7470ZCknzB0Orp8nDFHAbin8ObH+D2x+DcY4ciJO76cmC5yYokthOzr2Kqr4G7AE7GIA/oEaDrqPjFFnRbEgnYPHYky21ZwHiswOMuOl/APPKyQRfehwi7CnGXkpTFS7EKoACvvMmVgF3A+YQAtKVBzJCgM+XTpsI0R/V7iYheFQY+UN1wOrD1qB6OYJ3spW2RllJSBMzJyH6aQm3llqDj4ZFT31WQU+9Mmf2LkPk1FqntJzvgkc+Yp81ZR2p/VjH85wIy3xBr64vGd/834c8K2kVry7gMJ3lDm7MOzAHwsGwvPOlgyom1FniXKegE1nQpy8FZuOX23lXOSexeqYnopmIH7C7rlrKP6OCDiu8I6i5+oPQz7GEZFTu5nqopiDWjaH+xTATZqdUK4AAAAAElFTkSuQmCC"
/></
p
>
<
hr
>
<
h2
>Your options:</
h2
>
<
p
style
=
"font-size:16px"
>Running: </
p
>
<
p
style
=
"font-size:16px"
>Cycling: </
p
>
<
p
style
=
"font-size:16px"
>Paint-ball: </
p
>
<
p
style
=
"font-size:16px"
>Football: </
p
>
<
p
style
=
"font-size:16px"
>Voleyball: </
p
>
</
body
>
</
html
>
And here is the code I used to populate the ImagePickerToolbarItem with images:
private
void
InitializeImages()
{
var resourceNames =
this
.currentAssembly.GetManifestResourceNames();
var imageSources =
new
List<RichTextImageSource>();
foreach
(var resourceName
in
resourceNames)
{
if
(resourceName.Contains(
"sign"
))
{
var imageSource = RichTextImageSource.FromStream(() =>
this
.currentAssembly.GetManifestResourceStream(resourceName), RichTextImageType.Png);
imageSources.Add(imageSource);
}
}
this
.imagePicker.ItemsSource = imageSources;
}
Then Inside the Page’s Constructor, call the InitializeImages() method, then load the HTML document from a stream and assign the result to the Source property of the RichTextEditor. All this after the InitializeComponent():
InitializeComponent();
InitializeImages();
Func<CancellationToken, Task<Stream>> streamFunc = ct => Task.Run(() =>
{
string
fileName =
this
.currentAssembly.GetManifestResourceNames().FirstOrDefault(n => n.Contains(
"pick-image-demo.html"
));
Stream stream =
this
.currentAssembly.GetManifestResourceStream(fileName);
return
stream;
});
this
.
richTextEditor.Source = RichTextSource.FromStream(streamFunc);
This is the result:
We would love to hear what you think, so should you have any questions and/or comments, please share them in our Telerik UI for Xamarin Feedback Portal.
If you are new to Telerik UI for Xamarin, you can learn more about it via the product page. It comes with a 30-day free trial, giving you some time to explore the toolkit and consider using it for your current or upcoming Xamarin development.
Still in a preview stage, our library of UI components for .NET MAUI is growing. We have added new controls and support for macOS. Now your desktop and mobile applications can target Android, iOS, macOS and Windows.
Check out the Telerik UI for .NET MAUI product page and official documentation.
Happy coding with our controls!
]]>Building off of our update from October, today I wanted to take the time to cover what your favorite Telerik and Kendo UI teams at Progress have been working on over the last few weeks. There’s a lot to unpack here, and everything that we mention is available within the latest releases of each of these products. So, if you see something you want to use, simply visit the Your Account page and grab the latest bits!
The Telerik teams at Progress have worked hard to provide all .NET web, desktop and mobile UI components, Document Processing Libraries, Reporting and JustMock tools support for .NET 6 and Visual Studio 2022 immediately after it was made available by Microsoft. Take a look at the dedicated blog post and see how you can benefit right away with the latest and greatest release in the .NET & Telerik worlds.
Angular 13 was released in the beginning of November and I’m happy to say that Kendo UI for Angular has had Day-Zero support! For those of you interested about what this version of Angular brings, we have a great blog post covering What’s New in Angular 13 right here. As for the Kendo UI for Angular components, simply update to the latest version of the packages you have included and you will be good to go.
Head on over to the Kendo UI for Angular docs and demos for more information.
Grid: Column Virtualization with Multi-Column Headers
A big feature that was added to the KendoReact Data Grid with this update is the ability to have multi-column headers when virtualizing our React data table. Previously these two features did not work that well together, but with the 4.10.0
update they can be seamlessly enabled in the same component.
See the KendoReact Data Table Column Virtualization demo for more information.
Editor: Expose Interfaces for onMount, onExecute, onPaste, onFocus and onBlur Events
Helping extend the way React developers implement the KendoReact Editor with this update, we have introduced several new events that can be used when initially rendering the component or when users interact with the content within.
See the KendoReact Editor demos to see the events in action.
Scheduler: Auto Item Height & Adaptive Slot Height
By default, the KendoReact Scheduler component has a set and uniform height when it needs to display all the items, or events, that are available on that day. This, however, may not be ideal in scenarios where days may have more events than others, or there are special days that require the events to stick out a bit more.
This is where the new Adaptive Slot Height feature comes into play, as it allows for the event slots available in a day to adapt to all the events that should be displayed, or even lets you set aspects like minimum height to ensure that even in scenarios where no events will end up being displayed.
In a similar vein, the new Auto Item Height feature deals with same ability to auto-adjust or have a defined height when events are displayed in a horizontal fashion, which is done in views like the TimelineView
and the MonthView
, along with the allDay
section of Day, Week and WorkWeek views.
Here’s a quick link to the React Scheduler Adaptive Slot Height demos and here’s a link to the React Scheduler Auto Item Height demos.
PivotGrid Component
We are excited to announce the release of the new and improved Kendo UI for jQuery PivotGrid! Throughout the years the team has received a lot of feedback around the PivotGrid component specifically, and while we have been able to add features here and there, we realized that to best serve all our Kendo UI developers we needed to rethink the PivotGrid from the ground up. We used the experience found from years of building and supporting such a component to see how we could make something better if we had a chance to do things over. That’s right, the new jQuery PivotGrid is not just an update—it is a brand-new component!
If you are already using the existing jQuery PivotGrid, have no fear—nothing will change with this update. We have introduced this component separately as the “New PivotGrid” so the components can even live side-by-side on the same page. For now, PivotGridv2
may have fewer features and less functionality than the original PivotGrid, but it is taking advantage of an updated design that has also been created from the ground up to ensure the user experience is as good as it can be. We will continue to keep these components together for some time until we have provided feature parity (and even extended past the original) and see evidence that most users have migrated to the new component.
For a full breakdown of features, please refer to the New PivotGrid component demos section.
ColorPicker: New Design
The Kendo UI for jQuery ColorPicker component received a new and improved design with this update! Over the years of providing a ColorPicker for jQuery, as well as our other web-based products, we have received a lot of feedback around this component and have updated the design to account for this feedback.
These changes include brand-new design and also some new UI elements and features: capability to switch from Gradient to Palette view within the same ColorPicker instance; new color preview where you can easily compare old vs. new color; toggleable HEX and RGB inputs with opacity support; and a Contrast Tool to show users the contrast ratio between two colors.
To see this new design, check out the jQuery ColorPicker Overview demo.
PanelBar: Updated Design
With this release, the Kendo UI for jQuery PanelBar component also received an updated design. While the component mostly looks the same, we have updated the rendering and classes applied to the rendered HTML to make the child elements within the PanelBar more distinguishable when all content is expanded. Additionally, the expand and collapse arrows have been updated to use a chevron arrow instead of a filled-in triangle.
See the new design over at the jQuery PanelBar demos.
Grid: Multi-Column Sorting via CTRL + Click
While the Kendo UI for jQuery Grid has had the ability to do multi-column sorting since the early days of the library, with this release we have added more ways for users to interact with columns for sorting. Specifically, this update adds an optional behavior feature that allows end users to sort on a single column when using a regular mouse click and only sort multiple columns when pressing the CTRL button. When clicking on a column header without the CTRL button pressed the Grid will revert to sorting by a single column.
See this new sorting behavior in action by jumping over to the jQuery Grid Sorting demos.
Admin Dashboard Sample Application
With this update, we are also bringing a brand-new sample application to the list of available demo apps built with Kendo UI for jQuery! This application follows the design and application architecture of popular admin dashboard templates that exist in the wild. The Admin Dashboard also uses a broad range of Kendo UI for jQuery components in a single application to help new and veteran Kendo UI users alike.
Head on over to the jQuery Admin Dashboard sample app right here!
Drawer: Amazon Style Navigation Sample
The Kendo UI for jQuery Drawer component has received several requests for a feature that replicates the navigation style of the Amazon menu. When a user clicks on a menu item, the Drawer component animates to the next “level” of the drawer to display a new set of menu items. From there users can navigate deeper or use the provided built-in navigation to move back to previous levels.
This has been implemented as a part of one of our jQuery Knowledge Base articles as it requires a little more code than would normally be found in one of our demos.
All Components: Improved Accessibility
With this update, we also continue our streak of improving the accessibility of all Kendo UI for jQuery components. These additions range from tackling reported accessibility issues within our backlog as well as strengthening the automated accessibility testing that we do internally. The result is that the latest edition of our jQuery components continue to be the premier jQuery UI library for accessibility compliance.
Visual Studio 2022 Support
Visual Studio 2022 was recently released, and with this update we can say that Kendo UI for jQuery and its helpful Visual Studio tooling officially supports Visual Studio 2022!
This month we excited to share that along with the .NET 6 and Visual Studio 2022 support, Telerik UI for Blazor brings a refreshed and enhanced Visual Studio Code extension! You can enjoy the uplifted UX and configure project themes and color swatches with a couple of clicks at project creation. You can also jumpstart a Blazor project with the new Admin Dashboard project template with pre-built layout and functionality. Rearrange the layout as it fits your needs, and simply plug in your data and bind it to the components—including Grid, Tile Layout, Drawer, Calendar, Form, various Chart types, Card and more.
Starting with Telerik UI for Blazor 2.29 release, we now ship the product source code for our active license holders (available in Your Account -> Downloads section).
Both Telerik UI for ASP.NET Core and ASP.NET MVC provide support for Visual Studio 2022, meaning you can develop with Telerik components, use project templates and extensions in the latest version of the IDE. Following the latest technology trends, we also provided compatibility for .NET 6 preview versions throughout the year, and we are now happy to share that Telerik UI for ASP.NET Core supports the official release of .NET 6.
We also added a few enhancements and new features across both ASP.NET MVC and Core offerings and will review in detail below.
Easy Access to Client- and Server-Side APIs
Both client- and server-side APIs are now easily accessible from the Telerik web UI component demos—check out the updates in the Data Grid demo.
Shared Data Source With the ScrollView Component
The ScrollView UI component (also known as Carousel) can now reference external data source and accept DataSource Name as string in its .DataSource configuration method.
New Features and Views in ColorPicker UI Component
The ColorPicker component now provides enriched Gradient and Palette views, plus a handy option for the users to perform a switch between predefined colors (Palette) and custom colors (Gradient). It also exposes for input both RGB and HEX formats and an option to configure its default format.
Telerik UI ColorPicker Gradient and Palette Views
Last but not least, the component provides options for checking the color contrast ratio between two colors following the Web Content Accessibility Guidelines (WCAG) AA and AAA levels.
Modernization of the PanelBar Component Rendering
The Telerik PanelBar component received a slightly refreshed look and feel, which is mostly noticeable when all content is expanded. The rendering and class updates make sure child items stand out better and the panel expand/collapse arrow has been changed to a chevron.
Telerik UI for ASP.NET Core Responsive Panel
To complete the support for referencing Telerik components using both HTML and TAG helpers in ASP.NET Core applications, we added the option to plug the Responsive Panel UI component using Html.Kendo().ResponsivePanel() configuration.
Telerik UI for ASP.NET MVC brings two flavors of a new resource—Admin Dashboard brand-new demo application and Visual Studio project template. Both provide the same use case showcasing Telerik components in an ASP.NET MVC application and include many UI components in action, including Grid, Tile Layout, Drawer, Calendar, Form, various Chart types, Card and more.
The November updates span across the Telerik AJAX components as well! We made sure to include in the release of Telerik UI for ASP.NET AJAX multiple accessibility improvements, implementation of several feedback portal items, a new demo and support for Web Live Preview.
Reporting Integration Demo
Based on your feedback, we added a dedicated demo showcasing the integration between the RadGrid UI component and Telerik Reporting and how you can pass and display ASP.NET AJAX Grid data in a WebForms Report Viewer.
Support for Web Live Preview
You can now configure your Telerik ASP.NET AJAX controls directly in the browser as well as in Visual Studio Designer using the powerful capabilities of Microsoft Web Live Preview (WLP). The CSS Auto-Sync functionality allows you to customize the appearance of the Telerik controls and layout of the page without leaving Visual Studio.
The Calendar and Scheduling control is essential in scenarios where users need to keep track of their schedule and efficiently manage their meetings. With the built-in Scheduling UI app, users can quickly create, modify and delete appointments. With R3 2021 Service Pack release, we’ve enhanced that functionality by providing you with a few events to get a notification as soon as an appointment is changed through the Scheduling UI.
Additionally, the R3 2021 Service Pack release brings one more event you’ve requested—MonthChangedevent. We’ll look into those new features in detail below.
When the Calendar is in Month view, users can quickly navigate between months with a single gesture. Now with the new MonthChanged event, you can track when the current month is updated and implement custom logic accordingly—for example, load some events for that month.
Appointment change events would be pretty helpful in many scenarios—whether you’d need to preserve the appointment’s data in a database, you’d need to notify the user a particular change has been made, and more.
As their names imply, AppointmentAdded is raised when a new Appointment is created, AppointmentDeleted when the user has deleted a concrete appointment, and AppointmentUpdated when the user has modified a property of an existing appointment.
The tricky part here is in the case of recurring appointments. When the app user adds an exception occurrence, or updates or deletes an occurrence (all these options are available through the built-in Scheduling UIs), AppointmentUpdated event is raised, as actually the recurrence rule of the appointment has been updated.
All three events provide event arguments of type AppointmentChangedEventArgs. AppointmentChangedEventArgs holds all the needed details related to the concrete appointment change, such as the appointment itself and, in the case of repeating appointments, the occurrence and the occurrence action (possible values: None, Add, Update and Delete).
The screencast below demonstrates notification messages shown on appointment changes with short info on the concrete updates. You can check the exact implementation in our documentation here: Calendar & Scheduling: Appointments Changes Events Example.
For more information on the R3 2021 SP for Telerik UI for Xamarin, visit our Release Notes.
We are thrilled to announce the Telerik UI for WinUI v0.6.0 release that comes with a new control as part of our expanding UI suite, support for the latest stable Windows App SDK release and a Visual Studio Extension. Let’s unpack the latest goodies!
The desktop version of Telerik UI for WinUI supports the latest stable Windows App SDK (Project Reunion) 0.8.5. We are also changing our example application from WinUI UWP to WinUI Desktop and will be supporting the latest stable Windows App SDK release. You can install the application from the Telerik UI for WinUI Examples web page and give it a spin!
The Telerik UI for WinUI suite is expanding with another new control—the Badge control! It will enable you to alert users and provide additional information about notifications, updates, changes, errors and anything else you might find useful. You can use the helper RadBadgeView control to attach Badge to any UI component of your application quickly. Choose from a predefined set of most popular badges or create your own to suit the application requirements.
In both cases, the control provides you with the full flexibility to adjust the appearance to your app’s overall look and feel. You can see below how the predefined badges look:
Here are some of the main features of the control:
For more details, please refer to the RadBadge documentation.
We recently added Telerik UI for WinUI VS extensions for Visual Studio 2019 and Visual Studio 2022. The extension will significantly increase your productivity and jumpstart the development process by allowing you to quickly create either desktop or UWP Telerik UI for WinUI projects. With the initial version, you can choose between two predefined templates:
For more details, you can check the Visual Studio Extension article from our documentation.
For more information on the Telerik UI for WinUI v0.6.0, visit our Release Notes.
The R3 2021 Service Pack is here and packed with new features, enhancements and goodies.
On the very bottom of the Suggested Actions for each Telerik UI for WPF control, now you will find the “View All Properties” link. When clicked, it opens the Properties window for the selected control, allowing you to browse to all other properties quickly. Note that this will be supported only in the Visual Studio 2022 version and above.
We are adding new option for sizing the TimeRuler that will automatically adjust the PixelLength of the control depending on the available space. This way the TimeRuler area would be stretched to fill the empty space with manually calculating the PixelLength. For more info check out the TimeRuler article from the GanttView help documentation.
The RadComboBox control got even more flexible with its new DropDownButtonIconContent and DropDownButtonIconTemplate properties. No more need to extract the default control template to change the dropdown icon.
Is it compatible with the RadGlyph? Yes, fully. Check out the following example, demonstrating how to set a RadGlyph as the combo box’s dropdown button icon of editable and noneditable ComboBox controls:
<telerik:RadComboBox IsEditable="True" Margin="0 10 0 0" DropDownButtonIconContent="" Width="200">
<telerik:RadComboBox.DropDownButtonIconTemplate>
<DataTemplate>
<telerik:RadGlyph Glyph="{Binding}" Foreground="#F7630C"/>
</DataTemplate>
</telerik:RadComboBox.DropDownButtonIconTemplate>
</telerik:RadComboBox>
<telerik:RadComboBox DropDownButtonIconContent="" Margin="0 10 0 0" Width="200">
<telerik:RadComboBox.DropDownButtonIconTemplate>
<DataTemplate>
<telerik:RadGlyph Glyph="{Binding}" Foreground="#F7630C"/>
</DataTemplate>
</telerik:RadComboBox.DropDownButtonIconTemplate>
</telerik:RadComboBox>
And here is the result:
Lovely, huh? For more details see the DropDown Button Icon article from the ComboBox documentation.
With the new ColorSettingsPanelWidth property of RadColorEditor, you will be able to easily customize the width of the color setting panel in the dropdown (on the right side). For example, check the images below. The first editor has narrow color settings area and the second one has a wider area:
For more info, check out the ColorEditor help documentation.
We have a lot more! To get an overview of all the latest features and improvements we’ve made, check out the release notes for the products below:
The Service Pack of the Telerik UI for WinForms suite comes just in time with the official launch of Visual Studio 2022 and .NET 6! This Service Pack brings full support for VS 2022 and .NET 6; rounded forms support in Windows 11; performance improvements in the file dialogs; memory optimizations in multiple controls; mentions (suggestions) functionality in RadRichTextEditor; and a set of new most-voted features. This year, we are the first to support design-time experience for .NET Core 3.1, .NET 5 and .NET 6 in Visual Studio 2022.
Let’s see in detail what is shipped with the R3 2021 Service Pack.
The newest Windows OS, v11, brings plenty of great features where the rounded corners are just a piece of the improved design. It will bring a more elegant experience to your forms in desktop applications:
The rounded corners are enabled by default which can be controlled by the Telerik.WinControls.WindowsSettings.EnableRoundedCornersDefaultValue property.
Make sure that Windows 10 version is defined in the app.manifest file:
This functionality enables you to show a predefined list of suggestions to be inserted into the document content when the users type a specific mention character, e.g., “@”. You can use a default provider for the mentions or define a custom one that suits your needs. Multiple providers are also supported while they have different mention characters.
The flexibility of the feature also provides you with the ability to control how the selected item is inserted, how it is visualized and how it is being matched inside the same collection.
RadSchedulerNavigator offers a date selector. Selecting a date inside the calendar will change the start date of the active view, preserving the same days count.
RadPropertyGrid supports individual item’s height. As the control does not expose the items directly, there is no Items collection. The data item can be accessed in the CreateItemElement or the ItemFormatting event. Then, specify the Item.ItemHeight property to the desired height.
RadVirtualKeyboard comes with a beep sound functionality after pressing a key and an improved API for finding a key row without the necessary of knowing the exact keyboard layout.
In R3 2021, RadTaskBoard (also known as Kanban Board) was released. The new powerful control enables users to track their tasks in a simple, agile-style manner. It provides a clean and user-friendly interface for a functional task management application.
With the Service Pack, we polished the user and tag management in the task cards and now you can fully benefit from the RadTaskBoard control.
You can also check our Release History page for a complete list of the included improvements.
Along with the latest .NET & VS support, we introduced some helpful improvements and addressed a lot of bugs. Let’s review the more impactful ones.
We made a very important improvement of the text measurement under Linux. We rely on a third-party text-handling library, and it has some significant flaws. This was bringing incorrect text wrapping and not on a rare occasion text that is clipped incorrectly. Using some smart algorithms, we now managed to make the rendered text layout almost identical to the one produced in Windows. We can safely consider this Linux user scenario covered.
The web-based report designer again received a substantial portion of our attention. Now the main menu displays a list of the recently opened reports for easily resuming report editing.
The “Open Report” functionality is further enhanced as you can now switch between Grid and List views in the “Open Report” dialog so that it better supports reports with a longer name. The list of the fixes in this designer is impressive.
We introduced the CommandTimeout property to the MSSQL Database Storage so that it can store resources of high volume. This is usually needed when huge reports get rendered and correspondingly cached. The property may be set as well using a newly added constructor overload or declaratively in the app configuration file.
We added a super handy endpoint “/api/reports/version” to the reports’ REST service implementations. As the address suggests, it returns the version of the server-side service assembly. Having this, if the server’s and viewer’s versions mismatch, you would get an informative message and upgrade the needed component. The handy part is that it can be also used to test if your service implementation is up and running or the programming gods have turned their backs on you today.
Back in February (R1 2021 SP1) we introduced functionality to skip the rendering of all pages not producing any significant content. This is especially useful for Report Books where some of the combined reports might not have data. We were sorry to hear this change in the behavior has caused some confusion for our users. Based on your feedback, we have improved this functionality and now if a page contains any error message, it is considered significant so that you as developers do not need to switch the SkipBlankPages property back and forth.
Again, an improvement based on user feedback: Some devs need to traverse all the data source components in the report definition. Now this is much easier using the dedicated GetDataSources method exposed on the Report level.
The other tool that got a lot of care for this release is the recently added WinUI report viewer. It now started to respect and display the interactive tooltips that are defined in the report model. We also further improved the UX in the high-contrast themes by using FontIcons instead of the original PathIcons. Next, the assemblies bringing the viewer itself may now be used in x86 apps (they were previously limited to x64 usage).
I would also mention a bug fix concerning the WinUI viewer when rendering reports from a Report Server (I know you knew that this scenario is supported). Now the Excel 97-2003, Web archive, and XPS renderings properly show the Export report dialog when selected. Again, the full list of fixes is available in the Release Notes article.
Lastly, let’s honor some important bug fixes. There was an annoying issue within the JSON serializer used on the server causing an error when an integer value got assigned to a multivalue float parameter. Well, it’s gone. Just to note that this serializer is used in the .NET Core 3.1/.NET 5/6 apps. And the second fix I will mention specifically is a security vulnerability bug fix in the legacy ASP.NET WebForms report viewer. Although this viewer is not being developed as it was effectively substituted with the HTML5 one (and all of its flavors), we are still committed to applying critical fixes, and the security ones are considered as such.
We hope that in this Service Pack release we managed to add valuable features and fix important bugs that will prove our product as a tool of choice for your apps, regardless of the platform or technology.
We will be extremely glad to hear from you about what we have missed or what can be done better, so please don’t hesitate and share your opinion below or drop a line in our Feedback Portal.
A client of ours contacted us for assistance in validating the expectations set for numerous mock objects. From the communication with him, we found out that we lack a mechanism that can tackle quickly and easily such a situation. That’s why we implemented the AssertAll method.
Here is an example of how this feature can be used:
[TestMethod]
public void TestMethod()
{
var foo = Mock.Create();
var bar = Mock.Create();
Mock.Arrange(() => foo.Post()).Occurs(2);
Mock.Arrange(() => bar.Get()).Occurs(2);
foo.Post();
bar.Get(); // just one call is made for the Get method
foo.Post();
Mock.AssertAll(); // assert all will fail the test as the expectation for the Get method is not met
}
Faster is always better when it comes to executing unit tests. With that in mind, we’ve managed to significantly improve the performance during the unit test discovery process inside the test explorer in Visual Studio.
Whew! No matter which product you’re interested in, that’s quite the update! If you’re looking to take advantage of any of these new features, all you have to do is update to the latest version that just recently was released. We will continue to provide updates along the way as we march toward R1 2022, so keep an eye out for more updates over the next couple of weeks!
]]>The Telerik teams at Progress have worked hard to ensure the massive update is available to you immediately after the official Microsoft releases, so you can take advantage of the latest and greatest in .NET 6 and VS 2022. In this blog post, we will take a closer look and see what’s new in Telerik UI components, libraries, tooling and Visual Studio extensions.
The official release of .NET 6, the next-generation platform that unites the .NET Framework and .NET Core, is now available! .NET 6 brings performance improvements and new capabilities to web, desktop, mobile and hybrid applications, and because it is an LTS (long-term supported) version, that means it will be officially supported until November 2024 (three years after its initial release).
Since the release of .NET 5 last year, we have continuously followed all preview releases of .NET 6 and ensured our product updates are compatible with them, meaning you could immediately plug in the latest version and try out the new .NET features even in its early days.
Now that .NET 6 is officially shipped, what does it mean for your current and new applications? With the instant support provided by Telerik, you can upgrade existing projects or start a new project using .NET 6 and Telerik right away. All you need to do is download the latest .NET SDK and the respective Telerik product version. If you are an active license holder, you can grab the November update from the “Your Account” page or update your NuGet package reference directly in your solutions.
Alternatively, everyone can download a free trial by head over to the respective product homes at:
If you prefer to stay on your current version of .NET, you can rest assured that we continue to support them as well.
Following the latest technology trends, we also provided early support for Telerik UI components, extensions and project templates for Visual Studio 2022 since June 2021 and now with the official release you can:
Below is a handy list of the available Visual Studio 2022 extensions, which you can download from Visual Studio Marketplace or as part of the product installers:
Telerik UI for WinUI Visual Studio 2022 Extension
Create New .NET 6 Project Wizard with Project Templates
Telerik UI for Xamarin Visual Studio 2022 Extension
Telerik Reporting Visual Studio 2022 Extension
While we dedicated special attention to the latest version of Visual Studio, we will continue to support previous widely used versions of the IDE: 2019, 2017 and beyond. Make sure to check the documentation of your product of interest to find out the details.
In addition to the overall excitement of the Telerik products support for .NET 6 and Visual Studio 2022, we wanted to spotlight a few attractive product-specific updates.
We are happy to announce that Telerik native Blazor UI components are compatible with the hybrid scenarios inside native MAUI, WPF and Windows Forms through Microsoft Blazor WebView. If you are keen on the topic like us, try out the sample how-to project Blazor in Hybrid Scenarios that we created or take a deep dive in the dedicated article “Blazor Hybrid Web Apps with .NET MAUI” by our awesome teammate Ed.
Just a couple of weeks ago, we announced the launch of two new cool browser-based playgrounds for creating, saving, running and sharing C# code snippets: Telerik REPL for ASP.NET Core and Telerik REPL for Blazor (REPL as Read–Eval–Print-Loop). Both REPLs also provide seamless integration with Telerik UI components and let you test and customize them effortlessly in the browser without any addition setup and configuration.
Today we are happy to announce that both code runners provide support for .NET 6 and Share to REPL feature from Visual Studio 2022, thus allowing you to take advantage of the latest Telerik UI for Blazor, Telerik UI for ASP.NET Core and .NET 6 packages!
Telerik REPL for Blazor
With the latest NuGet packages, you will also get our almighty .NET Core, .NET 5 and .NET 6 WinForms designers in Visual Studio. Last year, we were the first to release the WinForms Visual Studio designers for .NET Core and .NET 5! This year we are the first to support the .NET 6 in Visual Studio 2022.
Telerik WinForms Design Time Experience
Telerik UI for ASP.NET AJAX offers Day-Zero support for Visual Studio 2022 and Microsoft Web Live Preview (WLP). You can now configure your Telerik ASP.NET AJAX controls directly in the browser as well as in Visual Studio Designer using the powerful capabilities of WLP. The CSS Auto-Sync functionality allows you to customize the appearance of the Telerik controls and layout of the page without leaving Visual Studio.
Telerik UI for ASP.NET AJAX & Web Live Preview
As you can see, November is a month rich of .NET announcements, conferences and product releases, so why not just start calling it .NET-ember?
We encourage you to download and try out the latest bits and take a look at the detailed updates by Telerik and Kendo UI, because we shipped new UI components, features and improvements.
We would love to hear your feedback, so post any questions and/or comments below or in our dedicated Telerik Feedback Portal.
]]>