Quantcast
Channel: ASP.NET Blog
Viewing all 7144 articles
Browse latest View live

Make the most of your monthly Azure Credits

$
0
0

If you weren’t aware, Visual Studio subscribers have free monthly Azure credits, that are ideal for experimenting with and learning about Azure services. When you activate this benefit, it creates a separate Azure subscription with a monthly credit balance that renews each month while you remain an active Visual Studio subscriber. If the credits run out before the end of the month the subscription is suspended until more credits are available. No surprises, no cost, and no credit card required for any of it!

The table below shows you how many Azure credits you get based on your type of Visual Studio subscription:

Visual Studio subscription type Monthly Azure Credits Activate Credits
Visual Studio Professional (standard subscription) $50 activate
Visual Studio Test Professional $50 activate
MSDN Platforms $100 activate
Visual Studio Enterprise (standard subscription) $150 activate
Visual Studio Enterprise (BizSpark) $150 activate
Visual Studio Enterprise (MPN) $150 activate

Now that you know how many Azure Credits you get every month for free, you are probably wondering what you can spend it on! We have put together the following simple table to help you get going:

Azure Service Tier Estimated Monthly Cost
App Service Shared $9.49
Storage General Purpose V2 (1GB) $1.06
SQL Single DB (5DTUs, 2GB) $4.90
CosmosDB 1GB $23.61
Functions Dynamic First 1M executions free (up to 400K GB-s)
Monitor Application Insights First 1GB free
Key Vault Standard $0.03 (per 10k operations)
Service Bus Basic $0.05 (per 1M operations)
Redis Basic (C0: 250MB Cache) $16.06

Hopefully, you found this information helpful and you are on your way to make use of your Azure credits. If you are interested in the cost of an Azure service you didn’t see in the table above, try the Azure price calculator. If you have any questions or problems just leave us a comment below.


Blazor 0.8.0 experimental release now available

$
0
0

Blazor 0.8.0 is now available! This release updates Blazor to use Razor Components in .NET Core 3.0 and adds some critical bug fixes.

Get Blazor 0.8.0

To get started with Blazor 0.8.0 install the following:

  1. .NET Core 3.0 Preview 2 SDK (3.0.100-preview-010184)
  2. Visual Studio 2019 (Preview 2 or later) with the ASP.NET and web development workload selected.
  3. The latest Blazor extension from the Visual Studio Marketplace.
  4. The Blazor templates on the command-line:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates::0.8.0-preview-19104-04
    

You can find getting started instructions, docs, and tutorials for Blazor at https://blazor.net.

Upgrade to Blazor 0.8.0

To upgrade your existing Blazor apps to Blazor 0.8.0 first make sure you've installed the prerequisites listed above.

To upgrade a standalone Blazor 0.7.0 project to 0.8.0:

  • Update the Blazor packages and .NET CLI tool references to 0.8.0-preview-19104-04.
  • Replace any package reference to Microsoft.AspNetCore.Blazor.Browser with a reference to Microsoft.AspNetCore.Blazor.
  • Replace BlazorComponent with ComponentBase.
  • Update overrides of SetParameters on components to override SetParametersAsync instead.
  • Replace BlazorLayoutComponent with LayoutComponentBase
  • Replace IBlazorApplicationBuilder with IComponentsApplicationBuilder.
  • Replace any using statements for Microsoft.AspNetCore.Blazor.* with Microsoft.AspNetCore.Components.*, except leave Microsoft.AspNetCore.Blazor.Hosting in Program.cs
  • In index.html update the script reference to reference components.webassembly.js instead of blazor.webassembly.js

To upgrade an ASP.NET Core hosted Blazor app to 0.8.0:

  • Update the client-side Blazor project as described previously.
  • Update the ASP.NET Core app hosting the Blazor app to .NET Core 3.0 by following the migrations steps in the ASP.NET Core docs.
    • Update the target framework to be netcoreapp3.0
    • Remove any package reference to Microsoft.AspNetCore.App or Microsoft.AspNetCore.All
    • Upgrade any non-Blazor Microsoft.AspNetCore.* package references to version 3.0.0-preview-19075-0444
    • Remove any package reference to Microsoft.AspNetCore.Razor.Design
    • To enable JSON support, add a package reference to Microsoft.AspNetCore.Mvc.NewtonsoftJson and updateStartup.ConfigureServices to call services.AddMvc().AddNewtonsoftJson()
  • Upgrade the Microsoft.AspNetCore.Blazor.Server package reference to 0.8.0-preview-19104-04
  • Add a package reference to Microsoft.AspNetCore.Components.Server
  • In Startup.ConfigureServices simplify any call to app.AddResponseCompression to call the default overload without specifying WebAssembly or binary data as additional MIME types to compress.
  • In Startup.Configure add a call to app.UseBlazorDebugging() after the existing call to app.UseBlazor<App.Startup>()
  • Remove any unnecessary use of the Microsoft.AspNetCore.Blazor.Server namespace.

To upgrade a Blazor class library to 0.8.0:

  • Replace the package references to Microsoft.AspNetCore.Blazor.Browser and Microsoft.AspNetCore.Blazor.Build with references to Microsoft.AspNetCore.Components.Browser and Microsoft.AspNetCore.Components.Build and update the versions to 3.0.0-preview-19075-0444.
  • In the project file for the library change the project SDK from "Microsoft.NET.Sdk.Web" to "Microsoft.NET.Sdk.Razor".

Server-side Blazor is now ASP.NET Core Razor Components in .NET Core 3.0

As was recently announced, server-side Blazor is now shipping as ASP.NET Core Razor Components in .NET Core 3.0. We've integrated the Blazor component model into ASP.NET Core 3.0 and renamed it to Razor Components. Blazor 0.8.0 is now built on Razor Components and enables you to host Razor Components in the browser on WebAssembly.

Upgrade a server-side Blazor project to ASP.NET Core Razor Components in .NET Core 3.0

If you've been working with server-side Blazor, we recommend upgrading to use ASP.NET Core Razor Components in .NET Core 3.0.

To upgrade a server-side Blazor app to ASP.NET Core Razor Components:

  • Update the client-side Blazor project as described previously, except replace the script reference to blazor.server.js with components.server.js
  • Update the ASP.NET Core app hosting the Razor Components to .NET Core 3.0 as described previously.
  • In the server project:
    • Upgrade the Microsoft.AspNetCore.Blazor.Server package reference to 0.8.0-preview-19104-04
    • Add a package reference to Microsoft.AspNetCore.Components.Server version 3.0.0-preview-19075-0444
    • Replace the using statement for Microsoft.AspNetCore.Blazor.Server with Microsoft.AspNetCore.Components.Server
    • Replace services.AddServerSideBlazor with services.AddRazorComponents and app.UseServerSideBlazor with app.UseRazorComponents.
    • In the Startup.Configure method add app.UseStaticFiles() just prior to calling app.UseRazorComponents.
    • Move the wwwroot folder from the Blazor app project to the ASP.NET Core server project

Switching between ASP.NET Core Razor Components and client-side Blazor

Sometimes it's convenient to be able to switch between running your Razor Components on the server (ASP.NET Core Razor Components) and on the client (Blazor). For example, you might run on the server during development so that you can easily debug, but then publish your app to run on the client.

To update an ASP.NET Core hosted Blazor app so that it can be run as an ASP.NET Core Razor Components app:

  • Move the wwwroot folder from the client-side Blazor project to the ASP.NET Core server project.
  • In the server project:
    • Update the script tag in index.html to point to components.server.js instead of components.webassembly.js.
    • Add a call to services.AddRazorComponents<Client.Startup>() in the Startup.ConfigureServices method.
    • Add a call to app.UseStaticFiles() in the Startup.Configure method prior to the call to UseMvc.
    • Replace the call to UseBlazor with app.UseRazorComponents<Client.Startup>()
  • If you're using dependency injection to inject an HttpClient into your components, then you'll need to add an HttpClient as a service in your server's Startup.ConfigureServices method.

Tooling for Blazor projects is now included with Visual Studio 2019

Previously to get tooling support for Blazor projects you needed to install the Blazor extension for Visual Studio. Starting with Visual Studio 2019 Preview 2, tooling support for Razor Components (and hence Blazor apps) is already included without having to install anything else. The Blazor extension is now only needed to install the Blazor project templates in Visual Studio.

Runtime improvements

Blazor 0.8.0 includes some .NET runtime improvements like improved runtime performance on Chrome and an improved IL linker. In our performance benchmarks, Blazor 0.8.0 performance on Chrome is now about 25% faster. You can now also reference existing libraries like Json.NET from a Blazor app without any additional linker configuration:

@functions {
    WeatherForecast[] forecasts;

    protected override async Task OnInitAsync()
    {
        var json = await Http.GetStringAsync("api/SampleData/WeatherForecasts");
        forecasts = Newtonsoft.Json.JsonConvert.DeserializeObject<WeatherForecast[]>(json);
    }
}

Known issues

There are a couple of known issues with this release that you may run into:

  • "It was not possible to find any compatible framework version. The specified framework 'Microsoft.NETCore.App', version '2.0.0' was not found.": You may see this error when building a Blazor app because the IL linker currently requires .NET Core 2.x to run. To work around this issue, either install .NET Core 2.2 or disable IL linking by setting the <BlazorLinkOnBuild>false</BlazorLinkOnBuild> property in your project file.
  • "Unable to generate deps.json, it may have been already generated.": You may see this error when running a standalone Blazor app and you haven't yet restored packages for any .NET Core apps. To workaround this issue create any .NET Core app (ex dotnet new console) and then rerun the Blazor app.

These issues will be addressed in a future Blazor update.

Future updates

This release of Blazor was primarily focused on first integrating Razor Components into ASP.NET Core 3.0 and then rebuilding Blazor on top of that. Going forward, we plan to ship Blazor updates with each .NET Core 3.0 update.

Blazor, and support for running Razor Components on WebAssembly in the browser, won't ship with .NET Core 3.0, but we continue to work towards shipping Blazor some later date.

Give feedback

We hope you enjoy this latest preview release of Blazor. As with previous releases, your feedback is important to us. If you run into issues or have questions while trying out Blazor, file issues on GitHub. You can also chat with us and the Blazor community on Gitter if you get stuck or to share how Blazor is working for you. After you've tried out Blazor for a while please let us know what you think by taking our in-product survey. Click the survey link shown on the app home page when running one of the Blazor project templates:

Blazor survey

Thanks for trying out Blazor!

Changes to the web and JSON editor APIs in Visual Studio 2019

$
0
0

In Visual Studio 2019 Preview 2, The Web Tools team made some changes to improve extensibility features for extension developers. To standardize interfaces, the CSS, HTML, JSON and CSHTML editors renamed their assemblies as per the following table:

Old New
Microsoft.CSS.Core Microsoft.WebTools.Languages.Css
Microsoft.CSS.Editor Microsoft.WebTools.Languages.Css.Editor
Microsoft.Html.Core Microsoft.WebTools.Languages.Html
Microsoft.Html.Editor Microsoft.WebTools.Languages.Html.Editor
Microsoft.VisualStudio.Html.Package Microsoft.WebTools.Languages.Html.VS
Microsoft.JSON.Core Microsoft.WebTools.Languages.Json
Microsoft.JSON.Editor Microsoft.WebTools.Languages.Json.Editor
Microsoft.VisualStudio.JSON.Package Microsoft.WebTools.Languages.Json.VS
Microsoft.VisualStudio.Web.Extensions Microsoft.WebTools.Languages.Extensions
Microsoft.Web.Core Microsoft.WebTools.Languages.Shared
Microsoft.Web.Editor Microsoft.WebTools.Languages.Shared.Editor

To avoid potential parse issues, the JSON parse tree changed behavior. When you call JsonParserService.GetTreeAsync, you now get a snapshot of the JSON parse tree. As an extension developer, you can now request and maintain snapshots of the JSON parse tree.

Announcing an easier way to use latest certificates from Key Vault

$
0
0

Posting on behalf of Prashanth Yerramilli

When we launched Azure Key Vault a few years ago, it solved a major problem users had which was that storing sensitive and/or secret information in code or config files in plain text causes multiple problems including security exposure. Users stored their secrets in a safe store like Key Vault and used a URI to fetch the secret material. This service has been wildly popular and has become a standard for cloud applications. It is used by fledling startups to Fortune 500 companies world over.

Developers use Key Vault to store their adhoc secrets, certificates and keys used for encryption. And to follow best security practices they create secrets that are short lived. An example of typical flow in this case could be

  • Step 1: Developer creates a certificate in Key Vault
  • Step 2: Developer sets the lifetime of the secret to be 30 day. In other words developer asks Key Vault to re-create the certificate every 30 days. Developer also chooses to receive an email when a certificate is about to expire
  • Step 3: Developer writes a polling service to check if the certificate has indeed expired

In the above scenario there are few challenges for the customer. They would have to write a polling service that constantly checks if the certificate has expired and if so they wait for the new certificate and then bind it in Windows Certificate manager.
Now what if developer doesn’t have to poll. And also if the developer doesn’t have to bind the new certificate in Windows Certificate manager. To solve this exact problem we built a Key Vault Virtual Machine Extension.

Azure virtual machine (VM) extensions are small applications that provide post-deployment configuration and automation tasks on Azure VMs. For example, if a virtual machine requires software installation, anti-virus protection, or to run a script inside of it, a VM extension can be used. Azure VM extensions can be run with the Azure CLI, PowerShell, Azure Resource Manager templates, and the Azure portal. Extensions can be bundled with a new VM deployment, or run against any existing system.
To learn more about VM Extensions please click here

Key Vault VM Extension is supposed to do just that as explained in the steps below

  • Step 1: Create a Key Vault and create an Azure Windows Virtual Machine
  • Step 2: Install the Key Vault VM Extension on the VM
  • Step 3: Configure Key Vault VM Extension to monitor a specific vault by specifying how often it should fetch the certificate

By doing the above steps the latest certificate is bound correctly in Windows Certificate Manager. This feature enables auto-rotation of SSL certificates, without necessitating a re-deployment or binding.

In the lifecycle of secrets management fetching the latest version of the secret (for the purpose of this article a certificate) is just as important as storing it securely. To solve this problem, on an Azure Virtual Machine, we’ve created a VM Extension for Windows. A Linux version is coming soon.
Virtual Machine Extensions are small applications that provide post-deployment configuration and automation tasks on Azure VMs. In this case the Key Vault Virtual Machine extension once installed fetches the latest version of the certificate at a specified interval and automatically binds the latest version of the certificate in the certificate store on Windows. As you can see this feature enables auto-rotation of SSL certificates, without necessitating a re-deployment or binding.

Also before we begin going through the tutorial, we need to understand a concept called Managed Identities.
Your code needs credentials to authenticate to cloud services, but you want to limit the visibility of those credentials as much as possible. Ideally, they never appear on a developer’s workstation or get checked-in to source control. Azure Key Vault can store credentials securely so they aren’t in your code, but to retrieve them you need to authenticate to Azure Key Vault. To authenticate to Key Vault, you need a credential! A classic bootstrap problem. Through the magic of Azure and Azure AD, MI provides a “bootstrap identity” that makes it much simpler to get things started.

Here’s how it works: When you enable MI for an Azure resource such as a virtual machine, Azure creates a Service Principal (an identity) for that resource in Azure AD, and injects the credentials (of that identity) into the resource (in this case a virtual machine).

  1. Your code calls a local MI endpoint to get an access token
  2. MI uses the locally injected credentials to get an access token from Azure AD
  3. Your code uses this access token to authenticate to an Azure service

Managed Identities

Now within Managed Identities there are 2 types

  1. System Assigned managed identity is enabled directly on an Azure service instance. When the identity is enabled, Azure creates an identity for the instance in the Azure AD tenant that’s trusted by the subscription. The lifecycle of the identity is managed by Azure and is tied to the Azure service instance.
  2. User Assigned managed identity is created as a standalone Azure resource. Users first create an identity and then assign that identity to one or more Azure resources.

In this tutorial I will demonstrate how to create a Azure Virtual Machine with an ARM template which also includes creating a Key Vault VM Extension on the VM.

Prerequisites

Step 1

After the prerequisites are complete, create an System Assigned identity by following this tutorial

Step 2

Assign the newly created System Assigned identity to access to your Key Vault

  • Go to https://portal.azure.com and navigate to your Key Vault
  • Select Access Policies section and Add New by searching for the User Assigned identity
    AccessPolicies

Step 3

Create or Update a VM with the following ARM template
You can view full the ARM template here and the ARM Parameters file here.

The most minimal settings in the ARM template are shown below:

     {
            "secretsManagementSettings": {
                "observedCertificates": [
                    "<KeyVault URI of a secret to be monitored/retrieved, in versionless format: https://myVaultName.vault.azure.net/secrets/myCertName">,
                    "<more entries here>", 
                "pollingIntervalInS": "[parameters('kvvmextPollingInterval')]",
                ]
            }
        }

As you can see we only specify the observedCertificates parameter and polling Interval in seconds


Note: Your observedCertificates urls should be of the form:
https://myVaultName.vault.azure.net/secrets/myCertName 

and not:

https://myVaultName.vault.azure.net/certificates/myCertName 

Reason being the /secrets path returns the full certificate, inluding the private key, while the /certificates path does not.

By following this tutorial you can create a VM with the above specified template

The above tutorial assumes that you are storing your certificates on Windows Certificate Manager. And so the VM Extension pulls down the latest certificates at a specified interval and automatically binds those certificates in your certificate manager.

That’s all folks!

Linux Version: We’re actively working on a VM Extension for Linux and would love to hear any feedback you might have.

We are eager to hear from you about your use cases and how we can evolve the VM Extension to help you. So please reach out to us and add your feature requests to the Azure feedback forum. If you run into issues using the VM extension please reach out to us on StackOverflow.


Prashanth Yerramilli, Senior Program Manager, Azure Key Vault

Prashanth Yerramilli Profile Pic Prashanth Yerramilli is the Key Vault Program Manager on the Azure Security team. He has over 10 years of Software Engineering experience and brings to the team love for creating the ultimate development experience.

Prashanth can be reached at:
-Twitter @yvprashanth1
-GitHub https://github.com/yvprashanth

Microsoft’s Developer Blogs are Getting an Update

$
0
0

In the coming days, we’ll be moving our developer blogs to a new platform with a modern, clean design and powerful features that will make it easy for you to discover and share great content. This week, you’ll see the Visual Studio, IoTDev, and Premier Developer blogs move to a new URL  – while additional developer blogs will transition over the coming weeks. You’ll continue to receive all the information and news from our teams, including access to all past posts. Your RSS feeds will continue to seamlessly deliver posts and any of your bookmarked links will re-direct to the new URL location.

We’d love your feedback

Our most inspirational ideas have come from this community and we want to make sure our developer blogs are exactly what you need. Share your thoughts about the current blog design by taking our Microsoft Developer Blogs survey and tell us what you think! We would also love your suggestions for future topics that our authors could write about. Please use the survey to share what kinds of information, tutorials, or features you would like to see covered in future posts.

Frequently Asked Questions

For the most-asked questions, see the FAQ below. If you have any additional questions, ideas, or concerns that we have not addressed, please let us know by submitting feedback through the Developer Blogs FAQ page.

Will Saved/Bookmarked URLs Redirect?

Yes. All existing URLs will auto-redirect to the new site. If you discover any broken links, please report them through the FAQ feedback page.

Will My Feed Reader Still Send New Posts?

Yes, your RSS feed will continue to work through your current set-up. If you encounter any issues with your RSS feed, please report it with details about your feed reader.

Which Blogs Are Moving?

This migration involves the majority of our Microsoft developer blogs so expect to see changes to our Visual Studio, IoTDev, and Premier Developer blogs this week. The rest will be migrated in waves over the next few weeks.

We appreciate all of the feedback so far and look forward to showing you what we’ve been working on! For additional information about this blog migration, please refer to our Developer Blogs FAQ.

Migrating your existing on-prem SQL Server database to Azure SQL DB

$
0
0

If you are in the process of moving an existing .NET application to Azure, it’s likely you’ll have to migrate an existing, on-prem SQL database as well. There are a few different ways you can go about this, so let’s go through them.

Data Migration Assistant (downtime required)

The Data Migration Assistant (download | documentation) is free, easy to use, slick and extremely powerful! It can:

  • Evaluate if your database is ready to migrate and produce a readiness report (command line support included)
  • Provide recommendations for how to remediate migration blocking issues
  • Recommend the minimum Azure SQL Database SKU based on performance counter data of your existing database
  • Perform the actual migration of schema, data and objects (server roles, logins, etc.)

After a successful migration, applications will be able to connect to the target SQL server databases seamlessly. There are currently a couple of limitations, but the majority of databases shouldn’t be impacted. If this sounds interesting, check out the full tutorials on how to migrate to Azure SQL DB and how to migrate to Azure SQL DB Managed Instance.

Azure Data Migration Service (no downtime required)

The Azure Data Migration Service allows you to move your on-prem database to Azure without taking it offline during the migration. Applications can keep on running while the migration is taking place. Once the database in Azure is ready you can switch your applications over immediately.

If this sounds interesting, check out the full tutorials on how to migrate to Azure SQL DB and how to migrate to Azure SQL DB Managed Instance without downtime.

SQL Server Management Studio (downtime required)

You are probably already familiar with SQL Server Management Studio (download | documentation), but if you are not it’s basically an IDE for SQL Server built on top of the Visual Studio shell and it’s free! Unlike the Data Migration Assistant, it cannot produce readiness reports nor can it suggest remediating actions, but it can perform the actual migration two different ways.

The first way is by selecting the command “Deploy Database to Microsoft Azure SQL Database…” which will bring up the migration wizard to take you through the process step by step:

The second way is by exporting the existing, on-prem database as a .bacpac file (docs to help with that) and then importing the .backpac file into Azure:

 

Resolving database migration compatibility issues

There are a wide variety of compatibility issues that you might encounter, depending both on the version of SQL Server in the source database and the complexity of the database you are migrating. Use the following resources, in addition to a targeted Internet search using your search engine of choices:

In addition to searching the Internet and using these resources, use the MSDN SQL Server community forums or StackOverflow. If you have any questions or problems just leave us a comment below.

 

What’s new in Azure SignalR 1.1.0 Preview 1

$
0
0

We just shipped 1.1.0 Preview 1 of Azure SignalR Service SDK to support some new features in ASP.NET Core 3.0, including endpoint routing and server-side Blazor. Let’s take a look how you can use them in your Azure SignalR application.

Here is the list of what’s new in this release:

  • Endpoint routing support for ASP.NET Core 3
  • Use SignalR service in server-side Blazor apps
  • Server stickiness

Endpoint routing support for ASP.NET Core 3

For those who are using Azure SignalR, you should be familiar with AddAzureSignalR() and UseAzureSignalR(). These two methods are required if you want to switch your app server from self-hosted SignalR to use Azure SignalR.

A typical Azure SignalR application usually looks like this in Startup.cs (note where AddAzureSignalR() and UseAzureSignalR() are used):

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSignalR()
            .AddAzureSignalR();
    ...
}

public void Configure(IApplicationBuilder app)
{
    ...
    app.UseAzureSignalR(routes => 
    { 
        routes.MapHub<Chat>("/chat"); 
    });
    ...
}

ASP.NET Core 3.0 introduced a new endpoint routing support which allows routable things like MVC and SignalR to be mixed together in a unified UseEndpoints() interface.

For example, you can call MapGet() and MapHub() in a single UseEndpoints() call, like this:

app.UseEndpoints(routes =>
{
    routes.MapGet("/foo", async context => {
        await context.Response.WriteAsync("bar");
    });
    routes.MapHub<Chat>("/chat");
});

This new syntax is also supported in the latest Azure SignalR SDK so you don’t need to use a separate UseAzureSignalR() to map hubs.

Now your Azure SignalR application looks like this:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSignalR()
            .AddAzureSignalR();
    ...
}

public void Configure(IApplicationBuilder app)
{
    ...
    app.UseRouting();
    app.UseEndpoints(routes =>
    {
        routes.MapHub<Chat>("/chat");
    });
    ...
}

The only change you need to make is to call AddAzureSignalR() after AddSignalR().

This will be very useful in the case that SignalR is deeply integrated in your code base or the library you’re using. For example, when you’re using server-side Blazor.

Use SignalR service in server-side Blazor apps

Server-side Blazor is a new way to build interactive client-side web UI in ASP.NET Core 3. In server-side Blazor, UI updates are rendered at server side, then sent to browser through a SignalR connection. Since it uses SignalR, there is a natural need to use Azure SignalR service to handle the SignalR traffic so your application can easily scale.

blazor

If you look at some server-side Blazor code samples, you’ll see they have a call to MapBlazorHub() to setup the communication channel between client and server.

app.UseEndpoints(endpoints =>
{
    ...
    endpoints.MapBlazorHub();
    ...
});

The implementation of this method calls MapHub() to create a SignalR hub at server side. Before this release there is no way to change the implementation of MapBlazorHub() to use SignalR service. Now if you call AddAzureSignalR(), MapBlazorHub() will also use SignalR service to host the hub instead of hosting it on the server.

Please follow these steps to change your server-side Blazor app to use SignalR service:

  1. Open your Startup.cs, add services.AddSignalR().AddAzureSignalR() in ConfigureServices().
  2. Create a new SignalR service instance.
  3. Get connection string and set it to environment variable Azure:SignalR:ConnectionString.

Then run your app you’ll see the WebSocket connection is going through SignalR service.

Check out this repo for a complete code sample.

Server stickiness

The typical connection flow when using SignalR service is that client first negotiates with app server to get the url of SignalR service, then service routes client to app server.

When you have multiple app servers, there is no guarantee that two servers (the one who does negotiation and the one who gets the hub invocation) will be the same one.

We hear a lot of customers asking about whether it’s possible to make the two servers the same one so they can share some states between negotiation and hub invocation. In this release we have added a new “server sticky mode” to support this scenario.

To enable this, you just need to set ServerStickyMode to Required in AddAzureSignalR():

services.AddSignalR().AddAzureSignalR(options => {
    options.ServerStickyMode = ServerStickyMode.Required;
});

Now for any connection, SignalR service will guarantee negotiation and hub invocation go to the same app server (called “server sticky”).

This feature is very useful when you have client state information maintained locally on the app server. For example, when using server-side Blazor, UI state is maintained at server side so you want all client requests go to the same server including the SignalR connection. So you need to set server sticky mode to Required when using server-side Blazor together with SignalR service.

Please note in this mode, there may be additional cost for the service to route connection to the right app server. So there may be some negative impact in message latency. If you don’t want the performance penalty, there is another Preferred mode you can use. In this mode stickiness is not always guaranteed (only when there is no additional cost to do the routing). But you can still gain some performance benefits as message delivery is more efficient if sender and receiver are on the same app server. Also when sticky mode is enabled, service won’t balance connections between app servers (by default SignalR service balances the traffic by routing to a server with least connections). So we recommend to set sticky mode to Disabled (this is also the default value) and only enable it when there is a need.

You can refer to this doc for more details about server sticky mode.

The post What’s new in Azure SignalR 1.1.0 Preview 1 appeared first on ASP.NET Blog.

ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 6

$
0
0

.NET Core 3.0 Preview 6 is now available and it includes a bunch of new updates to ASP.NET Core and Blazor.

Here’s the list of what’s new in this preview:

  • New Razor features: @attribute, @code, @key, @namespace, markup in @functions
  • Blazor directive attributes
  • Authentication & authorization support for Blazor apps
  • Static assets in Razor class libraries
  • Json.NET no longer referenced in project templates
  • Certificate and Kerberos Authentication
  • SignalR Auto-reconnect
  • Managed gRPC Client
  • gRPC Client Factory
  • gRPC Interceptors

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 6 install the .NET Core 3.0 Preview 6 SDK

If you’re on Windows using Visual Studio, you also need to install the latest preview of Visual Studio 2019.

For the latest client-side Blazor templates also install the latest Blazor extension from the Visual Studio Marketplace.

Upgrade an existing project

To upgrade an existing an ASP.NET Core app to .NET Core 3.0 Preview 6, follow the migrations steps in the ASP.NET Core docs.

Please also see the full list of breaking changes in ASP.NET Core 3.0.

To upgrade an existing ASP.NET Core 3.0 Preview 5 project to Preview 6:

  • Update Microsoft.AspNetCore.* package references to 3.0.0-preview6.19307.2
  • In Blazor apps:
    • Rename @functions to @code
    • Update Blazor specific attributes and event handlers to use the new directive attribute syntax (see below)
    • Remove any call to app.UseBlazor<TStartup>() and instead add a call to app.UseClientSideBlazorFiles<TStartup>() before the call to app.UseRouting(). Also add a call to endpoints.MapFallbackToClientSideBlazor<TStartup>("index.html") in the call to app.UseEndpoints().

Before

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
});

app.UseBlazor<Client.Startup>();

After

app.UseClientSideBlazorFiles<Client.Startup>();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapDefaultControllerRoute();
    endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
});

New Razor features

We’ve added support for the following new Razor language features in this release.

@attribute

The new @attribute directive adds the specified attribute to the generated class.

@attribute [Authorize]

@code

The new @code directive is used in .razor files (not supported in .cshtml files) to specify a code block to add to the generated class as additional members. It’s equivalent to @functions, but now with a better name.

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

@key

The new @key directive attribute is used in .razor files to specify a value (any object or unique identifier) that the Blazor diffing algorithm can use to preserve elements or components in a list.

<div>
    @foreach (var flight in Flights)
    {
        <DetailsCard @key="flight" Flight="@flight" />
    }
</div>

To understand why this feature is needed, consider rendering a list of cards with flight details without this feature:

<div>
    @foreach (var flight in Flights)
    {
        <DetailsCard Flight="@flight" />
    }
</div>

If you add a new flight into the middle of the Flights list the existing DetailsCard instances should remain unaffected and one new DetailsCard should be inserted into the rendered output.

To visualize this, if Flights previously contained [F0, F1, F2], then this is the before state:

  • DetailsCard0, with Flight=F0
  • DetailsCard1, with Flight=F1
  • DetailsCard2, with Flight=F2

… and this is the desired after state, given we insert a new item FNew at index 1:

  • DetailsCard0, with Flight=F0
  • DetailsCardNew, with Flight=FNew
  • DetailsCard1, with Flight=F1
  • DetailsCard2, with Flight=F2

However, the actual after state this:

  • DetailsCard0, with Flight=F0
  • DetailsCard1, with Flight=FNew
  • DetailsCard2, with Flight=F1
  • DetailsCardNew, with Flight=F2

The system has no way to know that DetailsCard2 or DetailsCard3 should preserve their associations with their older Flight instances, so it just re-associates them with whatever Flight matches their position in the list. As a result, DetailsCard1 and DetailsCard2 rebuild themselves completely using new data, which is wasteful and sometimes even leads to user-visible problems (e.g., input focus is unexpectedly lost).

By adding keys using @key the diffing algorithm can associate the old and new elements or components.

@namespace

Specifies the namespace for the generated class or the namespace prefix when used in an _Imports.razor file. The @namespace directive works today in pages and views (.cshtml) apps, but is now it is also supported with components (.razor).

@namespace MyNamespace

Markup in @functions and local functions

In views and pages (.cshtml files) you can now add markup inside of methods in the @functions block and in local functions.

@{ GreetPerson(person); }

@functions {
    void GreetPerson(Person person)
    {
        <p>Hello, <em>@person.Name!</em></p>
    }
}

Blazor directive attributes

Blazor uses a variety of attributes for influencing how components get compiled (e.g. ref, bind, event handlers, etc.). These attributes have been added organically to Blazor over time and use different syntaxes. In this Blazor release we’ve standardized on a common syntax for directive attributes. This makes the Razor syntax used by Blazor more consistent and predictable. It also paves the way for future extensibility.

Directive attributes all follow the following syntax where the values in parenthesis are optional:

@directive(-suffix(:name))(="value")

Some valid examples:

<!-- directive -->
<div @directive>...</div>
<div @directive="value"></div>

<!-- directive with key/value arg-->
<div @directive:key>...</div>
<div @directive:key="value"></div>

<!-- directive with suffix -->
<div @directive-suffix></div>
<div @directive-suffix="value"></div>

<!-- directive with suffix and key/value arg-->
<div @directive-suffix:key></div>
<div @directive-suffix:key="value"></div>

All of the Blazor built-in directive attributes have been updated to use this new syntax as described below.

Event handlers

Specifying event handlers in Blazor now uses the new directive attribute syntax instead of the normal HTML syntax. The syntax is similar to the HTML syntax, but now with a leading @ character. This makes C# event handlers distinct from JS event handlers.

<button @onclick="@Clicked">Click me!</button>

When specifying a delegate for C# event handler the @ prefix is currently still required on the attribute value, but we expect to remove this requirement in a future update.

In the future we also expect to use the directive attribute syntax to support additional features for event handlers. For example, stopping event propagation will likely look something like this (not implemented yet, but it gives you an idea of scenarios now enabled by directive attributes):

<button @onclick="Clicked" @onclick:stopPropagation>Click me!</button>

Bind

<input @bind="myValue">...</input>
<input @bind="myValue" @bind:format="mm/dd">...</input>
<MyButton @bind-Value="myValue">...</MyButton>

Key

<div @key="id">...</div>

Ref

<button @ref="myButton">...</button>

Authentication & authorization support for Blazor apps

Blazor now has built-in support for handling authentication and authorization. The server-side Blazor template now supports options for enabling all of the standard authentication configurations using ASP.NET Core Identity, Azure AD, and Azure AD B2C. We haven’t updated the Blazor WebAssembly templates to support these options yet, but we plan to do so after .NET Core 3.0 has shipped.

To create a new Blazor app with authentication enabled:

  1. Create a new Blazor (server-side) project and select the link to change the authentication configuration. For example, select “Individual User Accounts” and “Store user accounts in-app” to use Blazor with ASP.NET Core Identity:

    Blazor authentication

  2. Run the app. The app includes links in the top row for registering as a new user and logging in.

    Blazor authentication running

  3. Select the Register link to register a new user.

    Blazor authentication register

  4. Select “Apply Migrations” to apply the ASP.NET Core Identity migrations to the database.

    Blazor authentication apply migrations

  5. You should now be logged in.

    Blazor authentication logged in

  6. Select your user name to edit your user profile.

    Blazor authentication edit profile

In the Blazor app, authentication and authorization are configured in the Startup class using the standard ASP.NET Core middleware.

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapBlazorHub();
    endpoints.MapFallbackToPage("/_Host");
});

When using ASP.NET Core Identity all of the identity related UI concerns are handled by the framework provided default identity UI.

services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

The authentication related links in top row of the app are rendered using the new built-in AuthorizeView component, which displays different content depending on the authentication state.

LoginDisplay.razor

<AuthorizeView>
    <Authorized>
        <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
        <a href="Identity/Account/LogOut">Log out</a>
    </Authorized>
    <NotAuthorized>
        <a href="Identity/Account/Register">Register</a>
        <a href="Identity/Account/Login">Log in</a>
    </NotAuthorized>
</AuthorizeView>

The AuthorizeView component will only display its child content when the user is authorized. Alternatively, the AuthorizeView takes parameters for specifying different templates when the user is Authorized, NotAuthorized, or Authorizing. The current authentication state is passed to these templates through the implicit context parameter. You can also specify specific roles or an authorization policy on the AuthorizeView that the user must satisfy to see the authorized view.

To authorize access to specific pages in a Blazor app, use the normal [Authorize] attribute. You can apply the [Authorize] attribute to a component using the new @attribute directive.

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@page "/fetchdata"

To specify what content to display on a page that requires authorization when the user isn’t authorized or is still in the processing of authorizing, use the NotAuthorizedContent and AuthorizingContent parameters on the Router component. These Router parameters are only support in client-side Blazor for this release, but they will be enabled for server-side Blazor in a future update.

The new AuthenticationStateProvider service make the authentication state available to Blazor apps in a uniform way whether they run on the server or client-side in the browser. In server-side Blazor apps the AuthenticationStateProvider surfaces the user from the HttpContext that established the connection to the server. Client-side Blazor apps can configure a custom AuthenticationStateProvider as appropriate for that application. For example, it might retrieve the current user information by querying an endpoint on the server.

The authentication state is made available to the app as a cascading value (Task<AuthenticationState>) using the CascadingAuthenticationState component. This cascading value is then used by the AuthorizeView and Router components to authorize access to specific parts of the UI.

App.razor

<CascadingAuthenticationState>
    <Router AppAssembly="typeof(Startup).Assembly">
        <NotFoundContent>
            <p>Sorry, there's nothing at this address.</p>
        </NotFoundContent>
    </Router>
</CascadingAuthenticationState>

Static assets in Razor class libraries

Razor class libraries can now include static assets like JavaScript, CSS, and images. These static assets can then be included in ASP.NET Core apps by referencing the Razor class library project or via a package reference.

To include static assets in a Razor class library add a wwwroot folder to the Razor class library and include any required files in that folder.

When a Razor class library with static assets is referenced either as a project reference or as a package, the static assets from the library are made available to the app under the path prefix _content/{LIBRARY NAME}/. The static assets stay in their original folders and any changes to the content of static assets in the Razor class libraries are reflected in the app without rebuilding.

When the app is published, the companion assets from all referenced Razor class libraries are copied into the wwwroot folder of the published app under the same prefix.

To try out using static assets from a Razor class library:

  1. Create a default ASP.NET Core Web App.

    dotnet new webapp -o WebApp1
    
  2. Create a Razor class library and reference it from the web app.

    dotnet new razorclasslib -o RazorLib1
    dotnet add WebApp1 reference RazorLib1
    
  3. Add a wwwroot folder to the Razor class library and include a JavaScript file that logs a simple message to the console.

    cd RazorLib1
    mkdir wwwroot
    

    hello.js

    console.log("Hello from RazorLib1!");
    
  4. Reference the script file from Index.cshtml in the web app.

    <script src="_content/RazorLib1/hello.js"></script>
    
  5. Run the app and look for the output in the browser console.

    Hello from RazorLib1!
    

Projects now use System.Text.Json by default

New ASP.NET Core projects will now use System.Text.Json for JSON handling by default. In this release we removed Json.NET (Newtonsoft.Json) from the project templates. To enable support for using Json.NET, add the Microsoft.AspNetCore.Mvc.NewtonsoftJson package to your project and add a call to AddNewtonsoftJson() following code in your Startup.ConfigureServices method. For example:

services.AddMvc()
    .AddNewtonsoftJson();

Certificate and Kerberos authentication

Preview 6 brings Certificate and Kerberos authentication to ASP.NET Core.

Certificate authentication requires you to configure your server to accept certificates, and then add the authentication middleware in Startup.Configure and the certificate authentication service in Startup.ConfigureServices.

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(
        CertificateAuthenticationDefaults.AuthenticationScheme)
            .AddCertificate();
    // All the other service configuration.
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    // All the other app configuration.
}

Options for certificate authentication include the ability to accept self-signed certificates, check for certificate revocation, and check that the proffered certificate has the right usage flags in it. A default user principal is constructed from the certificate properties, with an event that enables you to supplement or replace the principal. All the options, and instructions on how to configure common hosts for certificate authentication can be found in the documentation.

We’ve also extended “Windows Authentication” onto Linux and macOS. Previously this authentication type was limited to IIS and HttpSys, but now Kestrel has the ability to use Negotiate, Kerberos, and NTLM on Windows, Linux, and macOS for Windows domain joined hosts by using the Microsoft.AspNetCore.Authentication.Negotiate nuget package. As with the other authentication services you configure authentication app wide, then configure the service:

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
        .AddNegotiate();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();
    // All the other app configuration.
}

Your host must be configured correctly. Windows hosts must have SPNs added to the user account hosting the application. Linux and macOS machines must be joined to the domain, then SPNs must be created for the web process, as well as keytab files generated and configured on the host machine. Full instructions are given in the documentation.

SignalR Auto-reconnect

This preview release, available now via npm install @aspnet/signalr@next and in the .NET Core SignalR Client, includes a new automatic reconnection feature. With this release we’ve added the withAutomaticReconnect() method to the HubConnectionBuilder. By default, the client will try to reconnect immediately and after 2, 10, and 30 seconds. Enlisting in automatic reconnect is opt-in, but simple via this new method.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chatHub")
    .withAutomaticReconnect()
    .build();

By passing an array of millisecond-based durations to the method, you can be very granular about how your reconnection attempts occur over time.

.withAutomaticReconnect([0, 3000, 5000, 10000, 15000, 30000])
//.withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

Or you can pass in an implementation of a custom reconnect policy that gives you full control.

If the reconnection fails after the 30-second point (or whatever you’ve set as your maximum), the client presumes the connection is offline and stops trying to reconnect. During these reconnection attempts you’ll want to update your application UI to provide cues to the user that the reconnection is being attempted.

Reconnection Event Handlers

To make this easier, we’ve expanded the SignalR client API to include onreconnecting and onreconnected event handlers. The first of these handlers, onreconnecting, gives developers a good opportunity to disable UI or to let users know the app is offline.

connection.onreconnecting((error) => {
    const status = `Connection lost due to error "${error}". Reconnecting.`;
    document.getElementById("messageInput").disabled = true;
    document.getElementById("sendButton").disabled = true;
    document.getElementById("connectionStatus").innerText = status;
});

Likewise, the onreconnected handler gives developers an opportunity to update the UI once the connection is reestablished.

connection.onreconnected((connectionId) => {
    const status = `Connection reestablished. Connected.`;
    document.getElementById("messageInput").disabled = false;
    document.getElementById("sendButton").disabled = false;
    document.getElementById("connectionStatus").innerText = status;
});

Learn more about customizing and handling reconnection

Automatic reconnect has been partially documented already in the preview release. Check out the deeper docs on the topic, with more examples and details on usage, at https://aka.ms/signalr/auto-reconnect.

Managed gRPC Client

In prior previews, we relied on the Grpc.Core library for client support. The addition of HTTP/2 support in HttpClient in this preview has allowed us to introduce a fully managed gRPC client.

To begin using the new client, add a package reference to Grpc.Net.Client and then you can create a new client.

var httpClient = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };
var client = GrpcClient.Create<GreeterClient>(httpClient);

gRPC Client Factory

Building on the opinionated pattern we introduced in HttpClientFactory, we’ve added a gRPC client factory for creating gRPC client instances in your project. There are two flavors of the factory that we’ve added: Grpc.Net.ClientFactory and Grpc.AspNetCore.Server.ClientFactory.

The Grpc.Net.ClientFactory is designed for use in non-ASP.NET app models (such as Worker Services) that still use the Microsoft.Extensions.* primitives without a dependency on ASP.NET Core.

In applications that perform service-to-service communication, we often observe that most servers are also clients that consume other services. In these scenarios, we recommend the use of Grpc.AspNetCore.Server.ClientFactory which features automatic propagation of gRPC deadlines and cancellation tokens.

To use the client factory, add the appropriate package reference to your project (Grpc.AspNetCore.Server.Factory or Grpc.Net.ClientFactory) before adding the following code to ConfigureServices().

services
    .AddGrpcClient<GreeterClient>(options =>
    {
        options.BaseAddress = new Uri("https://localhost:5001");
    });

gRPC Interceptors

gRPC exposes a mechanism to intercept RPC invocations on both the client and the server. Interceptors can be used in conjunction with existing HTTP middleware. Unlike HTTP middleware, interceptors give you access to actual request/response objects before serialization (on the client) and after deserialization (on the server) and vice versa for the response. All middlewares run before interceptors on the request side and vice versa on the response side.

Client interceptors

When used in conjunction with the client factory, you can add a client interceptor as shown below.

services
    .AddGrpcClient<GreeterClient>(options =>
    {
        options.BaseAddress = new Uri("https://localhost:5001");
    })
    .AddInterceptor<CallbackInterceptor>();

Server interceptors

Server interceptors can be registered in ConfigureServices() as shown below.

services
    .AddGrpc(options =>
    {
        // This registers a global interceptor
        options.Interceptors.Add<MaxStreamingRequestTimeoutInterceptor>(TimeSpan.FromSeconds(30));
    })
    .AddServiceOptions<GreeterService>(options =>
    {
        // This registers an interceptor for the Greeter service
        options.Interceptors.Add<UnaryCachingInterceptor>();
    });

For examples on how to author an interceptors, take a look at these examples in the grpc-dotnet repo.

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core and Blazor! Please let us know what you think by filing issues on GitHub.

Thanks for trying out ASP.NET Core and Blazor!

The post ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 6 appeared first on ASP.NET Blog.


Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6

$
0
0

With the ASP.NET Core 2.1 release, we included UseHsts and UseHttpRedirection by default. These methods put a site into an infinite loop if deployed to an Azure Linux App Service, Azure Linux virtual machine (VM), or behind any other reverse proxy besides IIS. TLS is terminated by the reverse proxy, and Kestrel isn’t made aware of the correct request scheme.

OAuth and OIDC also fail in this configuration because they generate incorrect redirects. Calls to UseIISIntegration add and configure forwarded headers middleware when running behind IIS, but there’s no matching automatic configuration for Linux (Apache or Nginx integration). The fix for this issue is discussed in more detail in the doc article Forward the scheme for Linux and non-IIS reverse proxies.

Configuration-only Wire-up in Preview 6

With the updates in .NET Core 3 preview 6, you no longer need to call the middleware explicitly, as the host logic has been pre-wired to enable the Forwarded Headers Middleware by default as long as the ASPNETCORE_FORWARDEDHEADERS_ENABLED environment variable has been set to true. Turning on the Forwarded Headers Middleware is as simple as setting the ASPNETCORE_FORWARDEDHEADERS_ENABLED setting in the Azure Portal’s configuration blade for any App Service running on Linux or in a container.

Enabling the Forwarded Headers Middleware via config

Once this setting is set to true, the middleware starts working, and features dependent on Request.IsHttps resulting to true begin to function as expected.

Resolving the issue with ASP.NET Core 2.x Apps Today

If you’re currently building an ASP.NET Core 2.x app and want to run it on App Service for Linux now, there’s a workaround that will be future-proof when the updates come out for 3.0.

To forward the scheme from the proxy in non-IIS scenarios, add and configure Forwarded Headers Middleware. In Startup.cs, use the following code:

// using Microsoft.AspNetCore.HttpOverrides;

public void ConfigureServices(IServiceCollection services)
{
    if (string.Equals(
        Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"), 
        "true", StringComparison.OrdinalIgnoreCase))
    {
        services.Configure<ForwardedHeadersOptions>(options =>
        {
            options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | 
                ForwardedHeaders.XForwardedProto;
            // Only loopback proxies are allowed by default.
            // Clear that restriction because forwarders are enabled by explicit 
            // configuration.
            options.KnownNetworks.Clear();
            options.KnownProxies.Clear();
        });
    }
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseForwardedHeaders();
}

If you enable your ASP.NET Core 2.x apps with this workaround today, when you’re ready to upgrade to 3.0, you’ll already have the right configuration setting in place.

Base Image Update

The base images used by the App Service team to streamline the creation of ASP.NET Core apps will soon be updated so that the ASPNETCORE_FORWARDEDHEADERS_ENABLED environment variable will be set to true. Once they’re updated, you won’t even need to explicitly set the environment variable; it’ll be enabled by default.

Try it Out

If you’re new to building ASP.NET Core apps using containers, the App Service options for Linux and Container-based hosting offer a great place to get started. The docs are loaded with guidance and examples, from how to Run a .NET Core app in App Service on Linux to accessing a SQL Server Database from an ASP.NET Core app running in App Service Linux.

The post Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6 appeared first on ASP.NET Blog.

Configuring a Server-side Blazor app with Azure App Configuration

$
0
0

With .NET Core 3.0 Preview 6, we added authentication & authorization support to server-side Blazor apps. It only takes a matter of seconds to wire up an app to Azure Active Directory with support for single or multiple organizations. Once the project is created, it contains all the configuration elements in its appsettings.json to function. This is great, but in a team environment – or in a distributed topology – configuration files lead to all sorts of problems. In this post, we’ll take a look at how we can extract those configuration values out of JSON files and into an Azure App Configuration instance, where they can be used by other teammates or apps.

Setting up Multi-org Authentication

In the .NET Core 3.0 Preview 6 blog post we explored how to use the Individual User Accounts option in the authentication dialog to set up a Blazor app with ASP.NET Identity, so we won’t go into too much detail. Essentially, you click the Change link during project creation.

Click Change Auth during project creation

In this example I’ll be using an Azure Active Directory application to allow anyone with a Microsoft account to log into the app, so I’ll select Work or School Accounts and then select Cloud – Multiple Organizations in the Change Authentication dialog.

The Visual Studio add authentication dialog.

Once the project is created, my AzureAD configuration node contains the 3 key pieces of information my app’s code will need to authenticate against Azure Active Directory; my tenant URL, the client ID for the AAD app Visual Studio created for me during the project’s creation, and the callback URI so users can get back to my app once they’ve authenticated.

The appsettings.json inclusive of the settings.

Whilst this is conveniently placed here in my appsettings.json file, it’d be more convenient if I didn’t need any local configuration files. Having a centralized configuration-management solution would be easier to manage, as well as give me the ability to keep my config out of source control, should there come a point when things like connection strings need to be shared amongst developers.

Azure App Configuration

Azure App Configuration is a cloud-based solution for managing all of your configuration values. Once I have an Azure App Configuration instance set up in my subscription, adding the configuration settings is simple. By default, they’re hidden from view, but I can click Show Values or select an individual setting for editing or viewing.

The config values in Azure App Configuration

Convenient .NET Core IConfiguration Integration

The Azure App Configuration team has shipped a NuGet package containing extensions to ASP.NET and .NET Core that enable developers the ability of using the service, but without needing to change all your code that already makes use of IConfiguration. To start with, install the Microsoft.Extensions.Configuration.AzureAppConfiguration NuGet package.

Adding the NuGet Package for Azure App Configuration

You’ll need to copy the connection string from the Azure Portal to enable connectivity between your app and Azure App Configuration.

Copying the Azure App Configuration connection string

Once that value has been copied, you can use it with either dotnet user-secrets to configure your app, or using a debug-time environment variable. Though it seems like we’ve created yet one more configuration value to track, think about it this way: this is the only value you’ll have to set using an environment variable; all your other configuration can be set via Azure App Configuration in the portal.

Setting up the Azure App Configuration connection string in an environment variable

Using the Azure App Configuration Provider for .NET Core

Once the NuGet package is installed, the code to instruct my .NET Core code to use Azure App Configuration whenever it reads any configuration values from IConfiguration is simple. In Program.cs I’ll call the ConfigureAppConfiguration middleware method, then use the AddAzureAppConfiguration extension method to get the connection string from my ASPNETCORE_AzureAppConfigConnectionString environment variable. If the environment variable isn’t set, the call will noop and the other configuration providers will do the work.

This is great, because I won’t even need to change existing – or in this case, template-generated code – I just tell my app to use Azure App Configuration and I’m off to the races. The full update to Program.cs is shown below.

// using Microsoft.Extensions.Configuration.AzureAppConfiguration;

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddAzureAppConfiguration(options =>
            {
                var azureAppConfigConnectionString = 
                    hostingContext.Configuration["AzureAppConfigConnectionString"];
                options.Connect(azureAppConfigConnectionString);
            });
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

When I run the app, it first reaches out to Azure App Configuration to get all the settings it needs to run and then works as if it were configured locally using appsettings.json. As long as my teammates or other services needing these values have the connection string to the Azure App Configuration instance holding the settings for the app, they’re good.

Running the authenticated app

Now, I can remove the configuration values entirely from the appsettings.json file. If I want to control the logging behavior using Azure App Configuration, I could move these left-over settings out, too. Even though I’ll be using Azure App Configuration as, the other providers are still there.

The appsettings.json with the settings removed.

Dynamic Re-loading

Log levels are a good example of how the Azure App Configuration service can enable dynamic reloading of configuration settings you might need to tweak frequently. By moving my logging configuration into Azure App Configuration, I can change the log level right in the portal. In Program.cs, I can use the Watch method to specify which configuration settings I’ll want to reload when they change.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddAzureAppConfiguration(options =>
            {
                var azureAppConfigConnectionString = 
                    hostingContext.Configuration["AzureAppConfigConnectionString"];
                options.Connect(azureAppConfigConnectionString)
                    .Watch("Logging:LogLevel:Default")
                    .Watch("Logging:LogLevel:Microsoft")
                    .Watch("Logging:LogLevel:Microsoft.Hosting.Lifetime");
            });
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

The default load-time is 30 seconds, but now, should I need to turn up the volume on my logs to get a better view of what’s happening in my site, I don’t need to re-deploy or even stop my site. Simply changing the values in the portal will be enough – 30 seconds later the values will be re-loaded from Azure App Configuration and my logging will be more verbose.

Changing configuration values in the portal

Configuration Source Ordering

The JsonConfigurationSource configuration sources – those which load settings from appsettings.json and appsettings.{Environment}.json – are loaded during the call to CreateDefaultBuilder. So, by the time I call AddAzureAppConfiguration to load in the AzureAppConfigurationSource, the JSON file providers are already in the configuration sources list.

The importance of ordering is evident here; should I want to override the configuration values coming from Azure App Configuration with my local appsettings.json or appsettings.Development.json files, I’d need to re-order the providers in the call to ConfigureAppConfiguration. Otherwise, the JSON file values will be loaded first, then the last source (the one that will “win”) will be the Azure App Configuration source.

Try it Out

Any multi-node or microservice-based application topology benefits from centralized configuration, and teams benefit from it by not having to keep track of so many configuration settings, environment variables, and so on. Take a look over the Azure App Configuration documentation. You’ll see that there are a multitude of other features, like Feature Flags and dark deployment support. Then, create an instance and try wiring your existing ASP.NET Code up to read configuration values from the cloud.

The post Configuring a Server-side Blazor app with Azure App Configuration appeared first on ASP.NET Blog.

ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 7

$
0
0

.NET Core 3.0 Preview 7 is now available and it includes a bunch of new updates to ASP.NET Core and Blazor.

Here’s the list of what’s new in this preview:

  • Latest Visual Studio preview includes .NET Core 3.0 as the default runtime
  • Top level ASP.NET Core templates in Visual Studio
  • Simplified web templates
  • Attribute splatting for components
  • Data binding support for TypeConverters and generics
  • Clarified which directive attributes expect HTML vs C#
  • EventCounters
  • HTTPS in gRPC templates
  • gRPC Client Improvements
  • gRPC Metapackage
  • CLI tool for managing gRPC code generation

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 7 install the .NET Core 3.0 Preview 7 SDK

If you’re on Windows using Visual Studio, install the latest preview of Visual Studio 2019.

Note: .NET Core 3.0 Preview 7 requires Visual Studio 2019 16.3 Preview 1, which is now available!

To install the latest client-side Blazor templates also run the following command:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview7.19365.7

Installing the Blazor Visual Studio extension is no longer required and it can be uninstalled if you’ve installed a previous version. Installing the Blazor WebAssembly templates from the command-line is now all you need to do to get them to show up in Visual Studio.

Upgrade an existing project

To upgrade an existing an ASP.NET Core app to .NET Core 3.0 Preview 7, follow the migrations steps in the ASP.NET Core docs.

Please also see the full list of breaking changes in ASP.NET Core 3.0.

To upgrade an existing ASP.NET Core 3.0 Preview 6 project to Preview 7:

  • Update Microsoft.AspNetCore.* package references to 3.0.0-preview7.19365.7.

That’s it! You should be ready to go.

Latest Visual Studio preview includes .NET Core 3.0 as the default runtime

The latest preview update for Visual Studio (16.3) includes .NET Core 3.0 as the default .NET Core runtime version. This means that if you install the latest preview of Visual Studio then you already have .NET Core 3.0. New project by default will target .NET Core 3.0

Top level ASP.NET Core templates in Visual Studio

The ASP.NET Core templates now show up as top level templates in Visual Studio in the “Create a new project” dialog.

ASP.NET Core templates

This means you can now search for the various ASP.NET Core templates and filter by project type (web, service, library, etc.) to find the one you want to use.

Simplified web templates

We’ve taken some steps to further simplify the web app templates to reduce the amount of code that is frequently just removed.

Specifically:

  • The cookie consent UI is no longer included in the web app templates by default.
  • Scripts and related static assets are now referenced as local files instead of using CDNs based on the current environment.

We will provide samples and documentation for adding these features to new apps as needed.

Attribute splatting for components

Components can now capture and render additional attributes in addition to the component’s declared parameters. Additional attributes can be captured in a dictionary and then “splatted” onto an element as part of the component’s rendering using the new @attributes Razor directive. This feature is especially valuable when defining a component that produces a markup element that supports a variety of customizations. For instance if you were defining a component that produces an <input> element, it would be tedious to define all of the attributes <input> supports like maxlength or placeholder as component parameters.

Accepting arbitrary parameters

To define a component that accepts arbitrary attributes define a component parameter using the [Parameter] attribute with the CaptureUnmatchedValues property set to true. The type of the parameter must be assignable from Dictionary<string, object>. This means that IEnumerable<KeyValuePair<string, object>> or IReadOnlyDictionary<string, object> are also options.

@code {
    [Parameter(CaptureUnmatchedValues= true)]
    Dictionary<string, object> Attributes { get; set; }
}

The CaptureUnmatchedValues property on [Parameter] allows that parameter to match all attributes that do not match any other parameter. A component can only define a single parameter with CaptureUnmatchedValues.

Using @attributes to render arbitrary attributes

A component can pass arbitrary attributes to another component or markup element using the @attributes directive attribute. The @attributes directive allows you to specify a collection of attributes to pass to a markup element or component. This is valuable because the set of key-value-pairs specified as attributes can come from a .NET collection and do not need to be specified in the source code of the component.

<input class="form-field" @attributes="Attributes" type="text" />

@code {
    [Parameter(CaptureUnmatchedValues = true)]
    Dictionary<string, object> Attributes { get; set; }
}

Using the @attributes directive the contents of the Attribute property get “splatted” onto the input element. If this results in duplicate attributes, then evaluation of attributes occurs from left to right. In the above example if Attributes also contained a value for class it would supersede class="form-field". If Attributes contained a value for type then that would be superseded by type="text".

Data binding support for TypeConverters and generics

Blazor now supports data binding to types that have a string TypeConverter. Many built-in framework types, like Guid and TimeSpan have a string TypeConverter, or you can define custom types with a string TypeConverter yourself. These types now work seamlessly with data binding:

<input @bind="guid" />

<p>@guid</p>

@code {
    Guid guid;
}

Data binding also now works great with generics. In generic components you can now bind to types specified using generic type parameters.

@typeparam T

<input @bind="value" />

<p>@value</p>

@code {
    T value;
}

Clarified which directive attributes expect HTML vs C#

In Preview 6 we introduced directive attributes as a common syntax for Razor compiler related features like specifying event handlers (@onclick) and data binding (@bind). In this update we’ve cleaned up which of the built-in directive attributes expect C# and HTML. Specifically, event handlers now expect C# values so a leading @ character is no longer required when specifying the event handler value:

@* Before *@
<button @onclick="@OnClick">Click me</button>

@* After *@
<button @onclick="OnClick">Click me</button>

EventCounters

In place of Windows perf counters, .NET Core introduced a new way of emitting metrics via EventCounters. In preview7, we now emit EventCounters ASP.NET Core. You can use the dotnet counters global tool to view the metrics we emit.

Install the latest preview of dotnet counters by running the following command:

dotnet tool install --global dotnet-counters --version 3.0.0-preview7.19365.2

Hosting

The Hosting EventSourceProvider (Microsoft.AspNetCore.Hosting) now emits the following request counters:

  • requests-per-second
  • total-requests
  • current-requests
  • failed-requests

SignalR

In addition to hosting, SignalR (Microsoft.AspNetCore.Http.Connections) also emits the following connection counters:

  • connections-started
  • connections-stopped
  • connections-timed-out
  • connections-duration

To view all the counters emitted by ASP.NET Core, you can start dotnet counters and specify the desired provider. The example below shows the output when subscribing to events emitted by the Microsoft.AspNetCore.Hosting and System.Runtime providers.

dotnet counters monitor -p <PID> Microsoft.AspNetCore.Hosting System.Runtime

D8GX-5oV4AASKwM

New Package ID for SignalR’s JavaScript Client in NPM

The Azure SignalR Service made it easier for non-.NET developers to make use of SignalR’s real-time capabilities. A frequent question we would get from potential customers who wanted to enable their applications with SignalR via the Azure SignalR Service was “does it only work with ASP.NET?” The former identity of the ASP.NET Core SignalR – which included the @aspnet organization on NPM, only further confused new SignalR users.

To mitigate this confusion, beginning with 3.0.0-preview7, the SignalR JavaScript client will change from being @aspnet/signalr to @microsoft/signalr. To react to this change, you will need to change your references in package.json files, require statements, and ECMAScript import statements. If you’re interested in providing feedback on this move or to learn the thought process the team went through to make the change, read and/or contribute to this GitHub issue where the team engaged in an open discussion with the community.

New Customizable SignalR Hub Method Authorization

With Preview 7, SignalR now provides a custom resource to authorization handlers when a hub method requires authorization. The resource is an instance of HubInvocationContext. The HubInvocationContext includes the HubCallerContext, the name of the hub method being invoked, and the arguments to the hub method.

Consider the example of a chat room allowing multiple organization sign-in via Azure Active Directory. Anyone with a Microsoft account can sign in to chat, but only members of the owning organization should be able to ban users or view users’ chat histories. Furthermore, we might want to restrict certain functionality from certain users. Using the updated features in Preview 7, this is entirely possible. Note how the DomainRestrictedRequirement serves as a custom IAuthorizationRequirement. Now that the HubInvocationContext resource parameter is being passed in, the internal logic can inspect the context in which the Hub is being called and make decisions on allowing the user to execute individual Hub methods.

public class DomainRestrictedRequirement :
    AuthorizationHandler<DomainRestrictedRequirement, HubInvocationContext>,
    IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
        DomainRestrictedRequirement requirement,
        HubInvocationContext resource)
    {
        if (IsUserAllowedToDoThis(resource.HubMethodName, context.User.Identity.Name) &&
            context.User != null &&
            context.User.Identity != null &&
            context.User.Identity.Name.EndsWith("@jabbr.net", StringComparison.OrdinalIgnoreCase))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }

    private bool IsUserAllowedToDoThis(string hubMethodName,
        string currentUsername)
    {
        return !(currentUsername.Equals("bob42@jabbr.net", StringComparison.OrdinalIgnoreCase) &&
            hubMethodName.Equals("banUser", StringComparison.OrdinalIgnoreCase));
    }
}

Now, individual Hub methods can be decorated with the name of the policy the code will need to check at run-time. As clients attempt to call individual Hub methods, the DomainRestrictedRequirement handler will run and control access to the methods. Based on the way the DomainRestrictedRequirement controls access, all logged-in users should be able to call the SendMessage method, only users who’ve logged in with a @jabbr.net email address will be able to view users’ histories, and – with the exception of bob42@jabbr.net – will be able to ban users from the chat room.

[Authorize]
public class ChatHub : Hub
{
    public void SendMessage(string message)
    {
    }

    [Authorize("DomainRestricted")]
    public void BanUser(string username)
    {
    }

    [Authorize("DomainRestricted")]
    public void ViewUserHistory(string username)
    {
    }
}

Creating the DomainRestricted policy is as simple as wiring it up using the authorization middleware. In Startup.cs, add the new policy, providing the custom DomainRestrictedRequirement requirement as a parameter.

services
    .AddAuthorization(options =>
    {
        options.AddPolicy("DomainRestricted", policy =>
        {
            policy.Requirements.Add(new DomainRestrictedRequirement());
        });
    });

It must be noted that in this example, the DomainRestrictedRequirement class is not only a IAuthorizationRequirement but also it’s own AuthorizationHandler for that requirement. It is fine to split these into separate classes to separate concerns. Yet, in this way, there’s no need to inject the AuthorizationHandler during Startup, since the requirement and the handler are the same thing, there’s no need to inject the handler separately.

HTTPS in gRPC templates

The gRPC templates have been now been updated to use HTTPS by default. At development time, we continue the same certificate generated by the dotnet dev-certs tool and during production, you will still need to supply your own certificate.

gRPC Client Improvements

The managed gRPC client (Grpc.Net.Client) has been updated to target .NET Standard 2.1 and no longer depends on types present only in .NET Core 3.0. This potentially gives us the ability to run on other platforms in the future.

gRPC Metapackage

In 3.0.0-preview7, we’ve introduced a new package Grpc.AspNetCore that transitively references all other runtime and tooling dependencies required for building gRPC projects. Reasoning about a single package version for the metapackage should make it easier for developers to deal with as opposed multiple dependencies that version independently.

CLI tool for managing gRPC code generation

The new dotnet-grpc global tool makes it easier to manage protobuf files and their code generation settings. The global tool manages adding and removing protobuf files as well adding the required package references required to build and run gRPC applications.

Install the latest preview of dotnet-grpc by running the following command:

dotnet tool install --global dotnet-grpc --version 0.1.22-pre2

As an example, you can run following commands to generate a protobuf file and add it to your project for code generation. If you attempt this on a non-web project, we will default to generating a client and add the required package dependencies.

dotnet new proto -o .\Protos\mailbox.proto
dotnet grpc add-file .\Protos\mailbox.proto

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core and Blazor! Please let us know what you think by filing issues on GitHub.

Thanks for trying out ASP.NET Core and Blazor!

The post ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 7 appeared first on ASP.NET Blog.

HttpRepl: A command-line tool for interacting with RESTful HTTP services

$
0
0

The ASP.NET team has built a command-line tool called HttpRepl. It lets you browse and invoke HTTP services in a similar way to working with files and folders. You give it a starting point (a base URL) and then you can execute commands like “dir” and “cd” to navigate your way around the API:

C:\> dotnet httprepl http://localhost:65369/
(Disconnected)~ set base http://localhost:65369
Using swagger metadata from http://localhost:65369/swagger/v1/swagger.json

http://localhost:65369/~ dir
.        []
Fruits   [get|post]
People   [get|post]

http://localhost:65369/~ cd People
/People    [get|post]

http://localhost:65369/People~ dir
.      [get|post]
..     []
{id}   [get]

Once you have identified the API you are interested in, you can use all the typical HTTP verbs against it. Here is an example of calling GET on http://localhost:65369/People as a continuation from before:

http://localhost:65369/People~ get
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Wed, 24 Jul 2019 20:33:07 GMT
Server: Microsoft-IIS/10.0
Transfer-Encoding: chunked
X-Powered-By: ASP.NET

[
  {
    "id": 1,
    "name": "Scott Hunter"
  },
  {
    "id": 0,
    "name": "Scott Hanselman"
  },
  {
    "id": 2,
    "name": "Scott Guthrie"
  }
]

Right now HttpRepl is being shipped as a .NET Core Global Tool, which means all you have to do to get it is run the following command on a machine with the .NET Core SDK installed:

C:\> dotnet tool install -g Microsoft.dotnet-httprepl --version “3.0.0-*”

The ASP.NET team built HttpRepl for the purpose of exploring and testing APIs. The idea was to make the experience of exploring and testing APIs through a command-line more convenient. What do you think about HttpRepl and what other uses do you envision for it? We would love to hear your opinion, please leave us a comment below or visit the project on GitHub. And for those wondering, HttpRepl’s official ship date is expected to align with .NET Core 3.0 GA.

Configure Visual Studio Code to launch HttpRepl on debug

You can configure Visual Studio to launch HttpRepl when debugging (along with your web app) by creating a new launch configuration as follows:

"version": "0.2.0",
  "compounds": [
    {
      "name": ".NET Core REPL",
      "configurations": [
        ".NET Core Launch (web)",
        "httprepl"
      ]
    }
  ],
  "configurations": [
    {
      "name": "httprepl",
      "type": "coreclr",
      "request": "launch",
      "program": "dotnet",
      "args": ["httprepl", "http://localhost:5000"],
      "cwd": "${workspaceFolder}",
      "stopAtEntry": false,
      "console": "integratedTerminal"
    },
    {
      "name": ".NET Core Launch (web)",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build",
      // If you have changed target frameworks, make sure to update the program path.
      "program": "${workspaceFolder}/bin/Debug/netcoreapp3.0/api.dll",
      "args": [],
      "cwd": "${workspaceFolder}",
      "stopAtEntry": false,
      // Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
      "serverReadyAction": {
        "action": "openExternally",
        "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"

      },
      "env": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "sourceFileMap": {
        "/Views": "${workspaceFolder}/Views"
      }
    }

Configure Visual Studio for Windows to launch HttpRepl on F5

You can configure Visual Studio to automatically launch HttpRepl when you F5 a project with the following simple steps:

The .exe for HttpRepl on Windows can be found in the following location:

%USERPROFILE%\.dotnet\tools\dotnet-httprepl.exe

Don’t forget to select it from the menu after adding it:

Next time you F5 your project, Visual Studio will automatically launch HttpRepl with the appropriate base URL (same URL that would have been passed to a browser, controlled through launchsettings):

Note: We are currently working on integrating HttpRepl into Visual Studio, which will give you an out-of-the box and more refined experience.

Configure Visual Studio for Mac to launch HttpRepl as a Custom Tool

In Visual Studio for Mac, you can configure a Custom Tool to open a new Terminal window and start httprepl. To configure this, go to Tools>Edit Custom Tools…

This will bring you to the External Tools dialog where you can add a new tool. To get started click the Add button to add a new tool. Here you will configure a new tool to launch a new Terminal instance and start the httprepl tool. Fill in the dialog with the following values.

  • Title: dotnet httprepl
  • Command: osascript
  • Arguments: -e ‘tell application “Terminal” to activate’ -e ‘tell application “Terminal”
    to do script “dotnet-httprepl”‘
  • Working directory: ${ProjectDir}

See the image below showing this new tool:

After clicking OK a new tool will appear in the Tools menu. To test your application with httprepl, start your application with Run>Start Debugging (or Run>Start without Debugging) and then start the httprepl with the new tool in the Tools menu:

When you invoke the tool a new Terminal window should appear in the foreground. From here you can set the base url to that of the api that you would like to test with set base. For example, see the image below that shows set base was executed and a get request will be executed next:

Give us feedback

It’s not HTTPie, it’s not Curl, but it’s also not PostMan. It’s something that you run and stays running and its aware of its current context. We find this experience valuable, but ultimately what matters the most is what you think. Please let us know your opinion by leaving comments below or on GitHub.

The post HttpRepl: A command-line tool for interacting with RESTful HTTP services appeared first on ASP.NET Blog.

Azure SignalR Service now supports Event Grid!

$
0
0

Azure SignalR Service now supports Event Grid!

Since we GA’ed Azure SignalR Service in last September, serverless has become a very popular use case in Azure SignalR Service and is used by many customers. Unlike the traditional SignalR application which requires a server to host the hub, in serverless scenario no server is needed, instead you can directly send messages to clients through REST APIs or our management SDK which can easily be used in serverless code like Azure Functions.

Though there is a huge benefit which saves you the cost of maintaining the app server, the feature set in serverless scenario is limited. Since there is no real hub, it’s not possible to respond to client activities like client invocations or connection events. Without client events serverless use cases will be limited and we hear a lot of customers asking about this support. Today we’re excited to announce a new feature that enables Azure SignalR Service to publish client events to Azure Event Grid so that you can subscribe and respond to them.

How does it work?

Let’s first revisit how serverless scenario in Azure SignalR Service works.

  1. In serverless scenario, even you don’t have an app server, you still need to have a negotiate API so SignalR client can do the negotiation to get the url to SignalR service and a corresponding access token. Usually this can be done using an Azure Function.

  2. Client will then use the url and access token to connect to SignalR service.

  3. After clients are connected, you can send message to clients using REST APIs or service management SDK. If you are using Azure Functions, our SignalR Service binding does the work for you so you only need to return the messages as an output binding.

This flow is illustrated as step 1-3 in the diagram below:

Serverless workflow

What’s missing here is that there is no equivalent of OnConnected() and OnDisconnected() in serverless APIs so there is no way for the Azure function to know whether a client is connected or disconnected.

Now with Event Grid you’ll be able to get such events through an Event Grid subscription (as step 4 and 5 in the above diagram):

  1. When a client is connected/disconnected to SignalR service, service will publish this event to Event Grid.

  2. In Azure function you can have an Event Grid trigger and subscribe to such events, then Event Grid will send those events to the function (through a webhook).

How to use it?

It’s very simple to make your serverless application subscribe to SignalR connection events. Let’s use Azure function as an example.

  1. First you need to make sure your SignalR Service instance is in serverless mode. (Create a SignalR Service instance if you haven’t done so.)

    Enable serverless mode

  2. Create an Event Grid trigger in your function app.

    Create Event Grid trigger

  3. In the Event Grid trigger, add an Event Grid subscription.

    Add Event Grid Subscription

    Then select your SignalR Service instance.

    Select SignalR Service instance

Now you’re all set! Your function app is now able to get connection events from SignalR Service.

To test it, you just need to open a SignalR connection to the service. You can use the SignalR client in our sample repo, which contains a simple negotiate API implementation.

  1. Clone AzureSignalR-samples repo.

  2. Start the sample negotiation server.

    cd samples\Management\NegotiationServer
    set Azure__SignalR__ConnectionString=<connection_string>
    dotnet run
    
  3. Run SignalR client.

    cd samples\Management\SignalRClient
    dotnet run
    

    Open the function logs in Azure portal and you’ll see a connected event is sent to the function:

    Azure Function output

    If you stop the client you’ll also see a disconnected event is received.

Try it now!

This feature is now in public preview so feel free to try it out and let us know your feedback by filing issues on Github.

For more information about how to use Event Grid with SignalR Service, you can read this article or try this sample.

The post Azure SignalR Service now supports Event Grid! appeared first on ASP.NET Blog.

ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 8

$
0
0

.NET Core 3.0 Preview 8 is now available and it includes a bunch of new updates to ASP.NET Core and Blazor.

Here’s the list of what’s new in this preview:

  • Project template updates
    • Cleaned up top-level templates in Visual Studio
    • Angular template updated to Angular 8
    • Blazor templates renamed and simplified
    • Razor Class Library template replaces the Blazor Class Library template
  • Case-sensitive component binding
  • Improved reconnection logic for Blazor Server apps
  • NavLink component updated to handle additional attributes
  • Culture aware data binding
  • Razor Pages support for @attribute
  • New networking primitives for non-HTTP Servers
  • Unix domain socket support for the Kestrel Sockets transport
  • gRPC support for CallCredentials
  • ServiceReference tooling in Visual Studio
  • Diagnostics improvements for gRPC

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 8 install the .NET Core 3.0 Preview 8 SDK

If you’re on Windows using Visual Studio, install the latest preview of Visual Studio 2019.

.NET Core 3.0 Preview 8 requires Visual Studio 2019 16.3 Preview 2 or later

To install the latest Blazor WebAssembly template also run the following command:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview8.19405.7

Upgrade an existing project

To upgrade an existing an ASP.NET Core app to .NET Core 3.0 Preview 8, follow the migrations steps in the ASP.NET Core docs.

Please also see the full list of breaking changes in ASP.NET Core 3.0.

To upgrade an existing ASP.NET Core 3.0 Preview 7 project to Preview 8:

  • Update Microsoft.AspNetCore.* package references to 3.0.0-preview8.19405.7.
  • Update package references to Microsoft.AspNetCore.Components.Browser to instead reference Microsoft.AspNetCore.Components.Web.
  • In Razor components rename OnInit to OnInitialized and OnInitAsync to OnInitializedAsync.
  • In Blazor apps, update Razor component parameters to be public, as non-public component parameters now result in an error.
  • In Blazor WebAssembly apps that make use of the HttpClient JSON helpers, add a package reference to Microsoft.AspNetCore.Blazor.HttpClient.
  • On Blazor form components remove use of Id and Class parameters and instead use the HTML id and class attributes.
  • Rename ElementRef to ElementReference.
  • Remove backing field declarations when using @ref or specify the @ref:suppressField parameter to suppress automatic backing field generation.
  • Update calls to ComponentBase.Invoke to call ComponentBase.InvokeAsync.
  • Update uses of ParameterCollection to use ParameterView.
  • Update uses of IComponent.Configure to use IComponent.Attach.
  • Remove use of namespace Microsoft.AspNetCore.Components.Layouts.

You should hopefully now be all set to use .NET Core 3.0 Preview 8.

Project template updates

Cleaned up top-level templates in Visual Studio

Top level ASP.NET Core project templates in the “Create a new project” dialog in Visual Studio no longer appear duplicated in the “Create a new ASP.NET Core web application” dialog. The following ASP.NET Core templates now only appear in the “Create a new project” dialog:

  • Razor Class Library
  • Blazor App
  • Worker Service
  • gRPC Service

Angular template updated to Angular 8

The Angular template for ASP.NET Core 3.0 has now been updated to use Angular 8.

Blazor templates renamed and simplified

We’ve updated the Blazor templates to use a consistent naming style and to simplify the number of templates:

  • The “Blazor (server-side)” template is now called “Blazor Server App”. Use blazorserver to create a Blazor Server app from the command-line.
  • The “Blazor” template is now called “Blazor WebAssembly App”. Use blazorwasm to create a Blazor WebAssembly app from the command-line.
  • To create an ASP.NET Core hosted Blazor WebAssembly app, select the “ASP.NET Core hosted” option in Visual Studio, or pass the --hosted on the command-line

Create a new Blazor app

dotnet new blazorwasm --hosted

Razor Class Library template replaces the Blazor Class Library template

The Razor Class Library template is now setup for Razor component development by default and the Blazor Class Library template has been removed. New Razor Class Library projects target .NET Standard so they can be used from both Blazor Server and Blazor WebAssembly apps. To create a new Razor Class Library template that targets .NET Core and supports Pages and Views instead, select the “Support pages and views” option in Visual Studio, or pass the --support-pages-and-views option on the command-line.

Razor Class Library for Pages and Views

dotnet new razorclasslib --support-pages-and-views

Case-sensitive component binding

Components in .razor files are now case-sensitive. This enables some useful new scenarios and improves diagnostics from the Razor compiler.

For example, the Counter has a button for incrementing the count that is styled as a primary button. What if we wanted a Button component that is styled as a primary button by default? Creating a component named Button in previous Blazor releases was problematic because it clashed with the button HTML element, but now that component matching is case-sensitive we can create our Button component and use it in Counter without issue.

Button.razor

<button class="btn btn-primary" @attributes="AdditionalAttributes" @onclick="OnClick">@ChildContent</button>

@code {
    [Parameter]
    public EventCallback<UIMouseEventArgs> OnClick { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    [Parameter(CaptureUnmatchedValues = true)]
    public IDictionary<string, object> AdditionalAttributes { get; set; }
}

Counter.razor

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<Button OnClick="IncrementCount">Click me</Button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

Notice that the Button component is pascal cased, which is the typical style for .NET types. If we instead try to name our component button we get a warning that components cannot start with a lowercase letter due to the potential conflicts with HTML elements.

Lowercase component warning

We can move the Button component into a Razor Class Library so that it can be reused in other projects. We can then reference the Razor Class Library from our web app. The Button component will now have the default namespace of the Razor Class Library. The Razor compiler will resolve components based on the in scope namespaces. If we try to use our Button component without adding a using statement for the requisite namespace, we now get a useful error message at build time.

Unrecognized component error

NavLink component updated to handle additional attributes

The built-in NavLink component now supports passing through additional attributes to the rendered anchor tag. Previously NavLink had specific support for the href and class attributes, but now you can specify any additional attribute you’d like. For example, you can specify the anchor target like this:

<NavLink href="my-page" target="_blank">My page</NavLink>

which would render:

<a href="my-page" target="_blank" rel="noopener noreferrer">My page</a>

Improved reconnection logic for Blazor Server apps

Blazor Server apps require a live connection to the server in order to function. If the connection or the server-side state associated with it is lost, then the the client will be unable to function. Blazor Server apps will attempt to reconnect to the server in the event of an intermittent connection loss and this logic has been made more robust in this release. If the reconnection attempts fail before the network connection can be reestablished, then the user can still attempt to retry the connection manually by clicking the provided “Retry” button.

However, if the server-side state associated with the connect was also lost (e.g. the server was restarted) then clients will still be unable to connect. A common situation where this occurs is during development in Visual Studio. Visual Studio will watch the project for file changes and then rebuild and restart the app as changes occur. When this happens the server-side state associated with any connected clients is lost, so any attempt to reconnect with that state will fail. The only option is to reload the app and establish a new connection.

New in this release, the app will now also suggest that the user reload the browser when the connection is lost and reconnection fails.

Reload prompt

Culture aware data binding

Data-binding support (@bind) for <input> elements is now culture-aware. Data bound values will be formatted for display and parsed using the current culture as specified by the System.Globalization.CultureInfo.CurrentCulture property. This means that @bind will work correctly when the user’s desired culture has been set as the current culture, which is typically done using the ASP.NET Core localization middleware (see Localization).

You can also manually specify the culture to use for data binding using the new @bind:culture parameter, where the value of the parameter is a CultureInfo instance. For example, to bind using the invariant culture:

<input @bind="amount" @bind:culture="CultureInfo.InvariantCulture" />

The <input type="number" /> and <input type="date" /> field types will by default use CultureInfo.InvariantCulture and the formatting rules appropriate for these field types in the browser. These field types cannot contain free-form text and have a look and feel that is controller by the browser.

Other field types with specific formatting requirements include datetime-local, month, and week. These field types are not supported by Blazor at the time of writing because they are not supported by all major browsers.

Data binding now also includes support for binding to DateTime?, DateTimeOffset, and DateTimeOffset?.

Razor Pages support for @attribute

Razor Pages now support the new @attribute directive for adding attributes to the generate page class.

For example, you can now specify that a page requires authorization like this:

@page
@attribute [Microsoft.AspNetCore.Authorization.Authorize]

<h1>Authorized users only!<h1>

<p>Hello @User.Identity.Name. You are authorized!</p>

New networking primitives for non-HTTP Servers

As part of the effort to decouple the components of Kestrel, we are introducing new networking primitives allowing you to add support for non-HTTP protocols.

You can bind to an endpoint (System.Net.EndPoint) by calling Bind on an IConnectionListenerFactory. This returns a IConnectionListener which can be used to accept new connections. Calling AcceptAsync returns a ConnectionContext with details on the connection. A ConnectionContext is similar to HttpContext except it represents a connection instead of an HTTP request and response.

The example below show a simple TCP Echo server hosted in a BackgroundService built using these new primitives.

public class TcpEchoServer : BackgroundService
{
    private readonly ILogger<TcpEchoServer> _logger;
    private readonly IConnectionListenerFactory _factory;
    private IConnectionListener _listener;

    public TcpEchoServer(ILogger<TcpEchoServer> logger, IConnectionListenerFactory factory)
    {
        _logger = logger;
        _factory = factory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _listener = await _factory.BindAsync(new IPEndPoint(IPAddress.Loopback, 6000), stoppingToken);

        while (true)
        {
            var connection = await _listener.AcceptAsync(stoppingToken);
            // AcceptAsync will return null upon disposing the listener
            if (connection == null)
            {
                break;
            }
            // In an actual server, ensure all accepted connections are disposed prior to completing
            _ = Echo(connection, stoppingToken);
        }

    }

    public override async Task StopAsync(CancellationToken cancellationToken)
    {
        await _listener.DisposeAsync();
    }

    private async Task Echo(ConnectionContext connection, CancellationToken stoppingToken)
    {
        try
        {
            var input = connection.Transport.Input;
            var output = connection.Transport.Output;

            await input.CopyToAsync(output, stoppingToken);
        }
        catch (OperationCanceledException)
        {
            _logger.LogInformation("Connection {ConnectionId} cancelled due to server shutdown", connection.ConnectionId);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "Connection {ConnectionId} threw an exception", connection.ConnectionId);
        }
        finally
        {
            await connection.DisposeAsync();
            _logger.LogInformation("Connection {ConnectionId} disconnected", connection.ConnectionId);
        }
    }
}

Unix domain socket support for the Kestrel Sockets transport

We’ve updated the default sockets transport in Kestrel to add support Unix domain sockets (on Linux, macOS, and Windows 10, version 1803 and newer). To bind to a Unix socket, you can call the ListenUnixSocket() method on KestrelServerOptions.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder
                .ConfigureKestrel(o =>
                {
                    o.ListenUnixSocket("/var/listen.sock");
                })
                .UseStartup<Startup>();
        });

gRPC support for CallCredentials

In preview8, we’ve added support for CallCredentials allowing for interoperability with existing libraries like Grpc.Auth that rely on CallCredentials.

Diagnostics improvements for gRPC

Support for Activity

The gRPC client and server use Activities to annotate inbound/outbound requests with baggage containing information about the current RPC operation. This information can be accessed by telemetry frameworks for distributed tracing and by logging frameworks.

EventCounters

The newly introduced Grpc.AspNetCore.Server and Grpc.Net.Client providers now emit the following event counters:

  • total-calls
  • current-calls
  • calls-failed
  • calls-deadline-exceeded
  • messages-sent
  • messages-received
  • calls-unimplemented

You can use the dotnet counters global tool to view the metrics emitted.

dotnet counters monitor -p <PID> Grpc.AspNetCore.Server

ServiceReference tooling in Visual Studio

We’ve added support in Visual Studio that makes it easier to manage references to other Protocol Buffers documents and Open API documents.

ServiceReference

When pointed at OpenAPI documents, the ServiceReference experience in Visual Studio can generated typed C#/TypeScript clients using NSwag.

When pointed at Protocol Buffer (.proto) files, the ServiceReference experience will Visual Studio can generate gRPC service stubs, gRPC clients, or message types using the Grpc.Tools package.

SignalR User Survey

We’re interested in how you use SignalR and the Azure SignalR Service, and your opinions on SignalR features. To that end, we’ve created a survey we’d like to invite any SignalR customer to complete. If you’re interested in talking to one of the engineers from the SignalR team about your ideas or feedback, we’ve provided an opportunity to enter your contact information in the survey, but that information is not required. Help us plan the next wave of SignalR features by providing your feedback in the survey.

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core and Blazor! Please let us know what you think by filing issues on GitHub.

Thanks for trying out ASP.NET Core and Blazor!

Correction: 8/14/2019

An earlier version of this blog post referenced a productivity feature in Blazor to automatically generate backing fields for elements that utilized the @ref attribute. Unfortunately, we missed a critical design flaw which prevents this from working end-to-end. For more information check out this announcement.

The post ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 8 appeared first on ASP.NET Blog.

Redesigning Configuration Refresh for Azure App Configuration

$
0
0

Overview

Since its inception, the .NET Core configuration provider for Azure App Configuration has provided the capability to monitor changes and sync them to the configuration within a running application. We recently redesigned this functionality to allow for on-demand refresh of the configuration. The new design paves the way for smarter applications that only refresh the configuration when necessary. As a result, inactive applications no longer have to monitor for configuration changes unnecessarily.
 

Initial design : Timer-based watch

In the initial design, configuration was kept in sync with Azure App Configuration using a watch mechanism which ran on a timer. At the time of initialization of the Azure App Configuration provider, users could specify the configuration settings to be updated and an optional polling interval. In case the polling interval was not specified, a default value of 30 seconds was used.

public static IWebHost BuildWebHost(string[] args)
{
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            // Load settings from Azure App Configuration
            // Set up the provider to listen for changes triggered by a sentinel value
            var settings = config.Build();
            string appConfigurationEndpoint = settings["AzureAppConfigurationEndpoint"];

            config.AddAzureAppConfiguration(options =>
            {
                options.ConnectWithManagedIdentity(appConfigurationEndpoint)
                        .Use(keyFilter: "WebDemo:*")
                        .WatchAndReloadAll(key: "WebDemo:Sentinel", label: LabelFilter.Null);
            });

            settings = config.Build();
        })
        .UseStartup<Startup>()
        .Build();
}

For example, in the above code snippet, Azure App Configuration would be pinged every 30 seconds for changes. These calls would be made irrespective of whether the application was active or not. As a result, there would be unnecessary usage of network and CPU resources within inactive applications. Applications needed a way to trigger a refresh of the configuration on demand in order to be able to limit the refreshes to active applications. Then unnecessary checks for changes could be avoided.

This timer-based watch mechanism had the following fundamental design flaws.

  1. It could not be invoked on-demand.
  2. It continued to run in the background even in applications that could be considered inactive.
  3. It promoted constant polling of configuration rather than a more intelligent approach of updating configuration when applications are active or need to ensure freshness.
     

New design : Activity-based refresh

The new refresh mechanism allows users to keep their configuration updated using a middleware to determine activity. As long as the ASP.NET Core web application continues to receive requests, the configuration settings continue to get updated with the configuration store.

The application can be configured to trigger refresh for each request by adding the Azure App Configuration middleware from package Microsoft.Azure.AppConfiguration.AspNetCore in your application’s startup code.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAzureAppConfiguration();
    app.UseMvc();
}

At the time of initialization of the configuration provider, the user can use the ConfigureRefresh method to register the configuration settings to be updated with an optional cache expiration time. In case the cache expiration time is not specified, a default value of 30 seconds is used.

public static IWebHost BuildWebHost(string[] args)
{
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            // Load settings from Azure App Configuration
            // Set up the provider to listen for changes triggered by a sentinel value
            var settings = config.Build();
            string appConfigurationEndpoint = settings["AzureAppConfigurationEndpoint"];

            config.AddAzureAppConfiguration(options =>
            {
                options.ConnectWithManagedIdentity(appConfigurationEndpoint)
                        .Use(keyFilter: "WebDemo:*")
                        .ConfigureRefresh((refreshOptions) =>
                        {
                            // Indicates that all settings should be refreshed when the given key has changed
                            refreshOptions.Register(key: "WebDemo:Sentinel", label: LabelFilter.Null, refreshAll: true);
                        });
            });

            settings = config.Build();
        })
        .UseStartup<Startup>()
        .Build();
}

In order to keep the settings updated and avoid unnecessary calls to the configuration store, an internal cache is used for each setting. Until the cached value of a setting has expired, the refresh operation does not update the value. This happens even when the value has changed in the configuration store.  

Try it now!

For more information about Azure App Configuration, check out the following resources. You can find step-by-step tutorials that would help you get started with dynamic configuration using the new refresh mechanism within minutes. Please let us know what you think by filing issues on GitHub.

Overview: Azure App configuration
Tutorial: Use dynamic configuration in an ASP.NET Core app
Tutorial: Use dynamic configuration in a .NET Core app
Related Blog: Configuring a Server-side Blazor app with Azure App Configuration

The post Redesigning Configuration Refresh for Azure App Configuration appeared first on ASP.NET Blog.


ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 9

$
0
0

.NET Core 3.0 Preview 9 is now available and it contains a number of improvements and updates to ASP.NET Core and Blazor.

Here’s the list of what’s new in this preview:

  • Blazor event handlers and data binding attributes moved to Microsoft.AspNetCore.Components.Web
  • Blazor routing improvements
    • Render content using a specific layout
    • Routing decoupled from authorization
    • Route to components from multiple assemblies
  • Render multiple Blazor components from MVC views or pages
  • Smarter reconnection for Blazor Server apps
  • Utility base component classes for managing a dependency injection scope
  • Razor component unit test framework prototype
  • Helper methods for returning Problem Details from controllers
  • New client API for gRPC
  • Support for async streams in streaming gRPC responses

Please see the release notes for additional details and known issues.

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 9 install the .NET Core 3.0 Preview 9 SDK.

If you’re on Windows using Visual Studio, install the latest preview of Visual Studio 2019.

.NET Core 3.0 Preview 9 requires Visual Studio 2019 16.3 Preview 3 or later.

To install the latest Blazor WebAssembly template also run the following command:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview9.19424.4

Upgrade an existing project

To upgrade an existing ASP.NET Core app to .NET Core 3.0 Preview 9, follow the migrations steps in the ASP.NET Core docs.

Please also see the full list of breaking changes in ASP.NET Core 3.0.

To upgrade an existing ASP.NET Core 3.0 Preview 8 project to Preview 9:

  • Update all Microsoft.AspNetCore.* package references to 3.0.0-preview9.19424.4
  • In Blazor apps and libraries:
    • Add a using statement for Microsoft.AspNetCore.Components.Web in your top level _Imports.razor file (see Blazor event handlers and data binding attributes moved to Microsoft.AspNetCore.Components.Web below for details)
    • Add a using statement for Microsoft.AspNetCore.Components.Authorization in your top level _Imports.razor file. In Blazor WebAssembly apps also add a package reference to Microsoft.AspNetCore.Components.Authorization.
    • Update all Blazor component parameters to be public.
    • Update implementations of IJSRuntime to return ValueTask<T>.
    • Replace calls to MapBlazorHub<TComponent> with a single call to MapBlazorHub.
    • Update calls to RenderComponentAsync and RenderStaticComponentAsync to use the new overloads to RenderComponentAsync that take a RenderMode parameter (see Render multiple Blazor components from MVC views or pages below for details).
    • Update App.razor to use the updated Router component (see Blazor routing improvements below for details).
    • (Optional) Remove page specific _Imports.razor file with the @layout directive to use the default layout specified through the router instead.
    • Remove any use of the PageDisplay component and replace with LayoutView, RouteView, or AuthorizeRouteView as appropriate (see Blazor routing improvements below for details).
    • Replace uses of IUriHelper with NavigationManager.
    • Remove any use of @ref:suppressField.
    • Replace the previous RevalidatingAuthenticationStateProvider code with the new RevalidatingIdentityAuthenticationStateProvider code from the project template.
    • Replace Microsoft.AspNetCore.Components.UIEventArgs with System.EventArgs and remove the “UI” prefix from all EventArgs derived types (UIChangeEventArgs -> ChangeEventArgs, etc.).
    • Replace DotNetObjectRef with DotNetObjectReference.
    • Replace OnAfterRender() and OnAfterRenderAsync() implementations with OnAfterRender(bool firstRender) or OnAfterRenderAsync(bool firstRender).
    • Remove any usage of IComponentContext and move any logic that should not run during prerendering into OnAfterRender or OnAfterRenderAsync.
  • In gRPC projects:
    • Update calls to GrpcClient.Create with a call GrpcChannel.ForAddress to create a new gRPC channel and new up your typed gRPC clients using this channel.
    • Rebuild any project or project dependency that uses gRPC code generation for an ABI change in which all clients inherit from ClientBase instead of LiteClientBase. There are no code changes required for this change.
    • Please also see the grpc-dotnet announcement for all changes.

You should now be all set to use .NET Core 3.0 Preview 9!

Blazor event handlers and data binding attributes moved to Microsoft.AspNetCore.Components.Web

In this release we moved the set of bindings and event handlers available for HTML elements into the Microsoft.AspNetCore.Components.Web.dll assembly and into the Microsoft.AspNetCore.Components.Web namespace. This change was made to isolate the web specific aspects of the Blazor programming from the core programming model. This section provides additional details on how to upgrade your existing projects to react to this change.

Blazor apps

Open the application’s root _Imports.razor and add @using Microsoft.AspNetCore.Components.Web. Blazor apps get a reference to the Microsoft.AspNetCore.Components.Web package implicitly without any additional package references, so adding a reference to this package isn’t necessary.

Blazor libraries

Add a package reference to the Microsoft.AspNetCore.Components.Web package package if you don’t already have one. Then open the root _Imports.razor file for the project (create the file if you don’t already have it) and add @using Microsoft.AspNetCore.Components.Web.

Troubleshooting guidance

With the correct references and using statement for Microsoft.AspNetCore.Components.Web, event handlers like @onclick and @bind should be bold font and colorized as shown below when using Visual Studio.

Events and binding working in Visual Studio

If @bind or @onclick are colorized as a normal HTML attribute, then the @using statement is missing.

Events and binding not recognized

If you’re missing a using statement for the Microsoft.AspNetCore.Components.Web namespace, you may see build failures. For example, the following build error for the code shown above indicates that the @bind attribute wasn’t recognized:

CS0169  The field 'Index.text' is never used
CS0428  Cannot convert method group 'Submit' to non-delegate type 'object'. Did you intend to invoke the method?

In other cases you may get a runtime exception and the app fails to render. For example, the following runtime exception seen in the browser console indicates that the @onclick attribute wasn’t recognized:

Error: There was an error applying batch 2.
DOMException: Failed to execute 'setAttribute' on 'Element': '@onclick' is not a valid attribute name.

Add a using statement for the Microsoft.AspNetCore.Components.Web namespace to address these issues. If adding the using statement fixed the problem, consider moving to the using statement app’s root _Imports.razor so it will apply to all files.

If you add the Microsoft.AspNetCore.Components.Web namespace but get the following build error, then you’re missing a package reference to the Microsoft.AspNetCore.Components.Web package:

CS0234  The type or namespace name 'Web' does not exist in the namespace 'Microsoft.AspNetCore.Components' (are you missing an assembly reference?)

Add a package reference to the Microsoft.AspNetCore.Components.Web package to address the issue.

Blazor routing improvements

In this release we’ve revised the Blazor Router component to make it more flexible and to enable new scenarios. The Router component in Blazor handles rendering the correct component that matches the current address. Routable components are marked with the @page directive, which adds the RouteAttribute to the generated component classes. If the current address matches a route, then the Router renders the contents of its Found parameter. If no route matches, then the Router component renders the contents of its NotFound parameter.

To render the component with the matched route, use the new RouteView component passing in the supplied RouteData from the Router along with any desired parameters. The RouteView component will render the matched component with its layout if it has one. You can also optionally specify a default layout to use if the matched component doesn’t have one.

<Router AppAssembly="typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
    </Found>
    <NotFound>
        <h1>Page not found</h1>
        <p>Sorry, but there's nothing here!</p>
    </NotFound>
</Router>

Render content using a specific layout

To render a component using a particular layout, use the new LayoutView component. This is useful when specifying content for not found pages that you still want to use the app’s layout.

<Router AppAssembly="typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="typeof(MainLayout)">
            <h1>Page not found</h1>
            <p>Sorry, but there's nothing here!</p>
        </LayoutView>
    </NotFound>
</Router>

Routing decoupled from authorization

Authorization is no longer handled directly by the Router. Instead, you use the AuthorizeRouteView component. The AuthorizeRouteView component is a RouteView that will only render the matched component if the user is authorized. Authorization rules for specific components are specified using the AuthorizeAttribute. The AuthorizeRouteView component also sets up the AuthenticationState as a cascading value if there isn’t one already. Otherwise, you can still manually setup the AuthenticationState as a cascading value using the CascadingAuthenticationState component.

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <CascadingAuthenticationState>
            <LayoutView Layout="@typeof(MainLayout)">
                <p>Sorry, there's nothing at this address.</p>
            </LayoutView>
        </CascadingAuthenticationState>
    </NotFound>
</Router>

You can optionally set the NotAuthorized and Authorizing parameters of the AuthorizedRouteView component to specify content to display if the user is not authorized or authorization is still in progress.

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
            <NotAuthorized>
                <p>Nope, nope!</p>
            </NotAuthorized>
        </AuthorizeRouteView>
    </Found>
</Router>

Route to components from multiple assemblies

You can now specify additional assemblies for the Router component to consider when searching for routable components. These assemblies will be considered in addition to the specified AppAssembly. You specify these assemblies using the AdditionalAssemblies parameter. For example, if Component1 is a routable component defined in a referenced class library, then you can support routing to this component like this:

<Router
    AppAssembly="typeof(Program).Assembly"
    AdditionalAssemblies="new[] { typeof(Component1).Assembly }>
    ...
</Router>

Render multiple Blazor components from MVC views or pages

We’ve reenabled support for rendering multiple components from a view or page in a Blazor Server app. To render a component from a .cshtml file, use the Html.RenderComponentAsync<TComponent>(RenderMode renderMode, object parameters) HTML helper method with the desired RenderMode.

RenderMode Description Supports parameters?
Static Statically render the component with the specified parameters. Yes
Server Render a marker where the component should be rendered interactively by the Blazor Server app. No
ServerPrerendered Statically prerender the component along with a marker to indicate the component should later be rendered interactively by the Blazor Server app. No

Support for stateful prerendering has been removed in this release due to security concerns. You can no longer prerender components and then connect back to the same component state when the app loads. We may reenable this feature in a future release post .NET Core 3.0.

Blazor Server apps also no longer require that the entry point components be registered in the app’s Configure method. Only a single call to MapBlazorHub() is required.

Smarter reconnection for Blazor Server apps

Blazor Server apps are stateful and require an active connection to the server in order to function. If the network connection is lost, the app will try to reconnect to the server. If the connection can be reestablished but the server state is lost, then reconnection will fail. Blazor Server apps will now detect this condition and recommend the user to refresh the browser instead of retrying to connect.

Blazor Server reconnect rejected

Utility base component classes for managing a dependency injection scope

In ASP.NET Core apps, scoped services are typically scoped to the current request. After the request completes, any scoped or transient services are disposed by the dependency injection (DI) system. In Blazor Server apps, the request scope lasts for the duration of the client connection, which can result in transient and scoped services living much longer than expected.

To scope services to the lifetime of a component you can use the new OwningComponentBase and OwningComponentBase<TService> base classes. These base classes expose a ScopedServices property of type IServiceProvider that can be used to resolve services that are scoped to the lifetime of the component. To author a component that inherits from a base class in Razor use the @inherits directive.

@page "/users"
@attribute [Authorize]
@inherits OwningComponentBase<Data.ApplicationDbContext>

<h1>Users (@Service.Users.Count())</h1>
<ul>
    @foreach (var user in Service.Users)
    {
        <li>@user.UserName</li>
    }
</ul>

Note: Services injected into the component using @inject or the InjectAttribute are not created in the component’s scope and will still be tied to the request scope.

Razor component unit test framework prototype

We’ve started experimenting with building a unit test framework for Razor components. You can read about the prototype in Steve Sanderson’s Unit testing Blazor components – a prototype blog post. While this work won’t ship with .NET Core 3.0, we’d still love to get your feedback early in the design process. Take a look at the code on GitHub and let us know what you think!

Helper methods for returning Problem Details from controllers

Problem Details is a standardized format for returning error information from an HTTP endpoint. We’ve added new Problem and ValidationProblem method overloads to controllers that use optional parameters to simplify returning Problem Detail responses.

[Route("/error")]
public ActionResult<ProblemDetails> HandleError()
{
    return Problem(title: "An error occurred while processing your request", statusCode: 500);
}

New client API for gRPC

To improve compatibility with the existing Grpc.Core implementation, we’ve changed our client API to use gRPC channels. The channel is where gRPC configuration is set and it is used to create strongly typed clients. The new API provides a more consistent client experience with Grpc.Core, making it easier to switch between using the two libraries.

// Old
using var httpClient = new HttpClient() { BaseAddress = new Uri("https://localhost:5001") };
var client = GrpcClient.Create<GreeterClient>(httpClient);

// New
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new GreeterClient(channel);

var reply = await client.GreetAsync(new HelloRequest { Name = "Santa" });

Support for async streams in streaming gRPC responses

gRPC streaming responses return a custom IAsyncStreamReader type that can be iterated on to receive all response messages in a streaming response. With the addition of async streams in C# 8, we’ve added a new extension method that makes for a more ergonomic API while consuming streaming responses.

// Old
while (await requestStream.MoveNext(CancellationToken.None))
{
  var message = requestStream.Current;
  // …
}

// New and improved
await foreach (var message in requestStream.ReadAllAsync())
{
  // …
}

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core and Blazor! Please let us know what you think by filing issues on GitHub.

Thanks for trying out ASP.NET Core and Blazor!

The post ASP.NET Core and Blazor updates in .NET Core 3.0 Preview 9 appeared first on ASP.NET Blog.

Blazor 0.7.0 experimental release now available

$
0
0

Blazor 0.7.0 is now available! This release focuses on enabling component coordination across ancestor-descendent relationships. We've also added some improvements to the debugging experience.

Here's what's new in the Blazor 0.7.0 release:

  • Cascading values and parameters
  • Debugging improvements

A full list of the changes in this release can be found in the Blazor 0.7.0 release notes.

Get Blazor 0.7.0

Install the following:

  1. .NET Core 2.1 SDK (2.1.500 or later).
  2. Visual Studio 2017 (15.9 or later) with the ASP.NET and web development workload selected.
  3. The latest Blazor Language Services extension from the Visual Studio Marketplace.
  4. The Blazor templates on the command-line:

    dotnet new -i Microsoft.AspNetCore.Blazor.Templates
    

You can find getting started instructions, docs, and tutorials for Blazor at https://blazor.net.

Upgrade an existing project to Blazor 0.7.0

To upgrade a Blazor 0.6.0 project to 0.7.0:

  • Install the prerequisites listed above.
  • Update the Blazor packages and .NET CLI tool references to 0.7.0. The upgraded Blazor project file should look like this:

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
    <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <RunCommand>dotnet</RunCommand>
        <RunArguments>blazor serve</RunArguments>
        <LangVersion>7.3</LangVersion>
    </PropertyGroup>
    
    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.7.0" />
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.7.0" />
        <DotNetCliToolReference Include="Microsoft.AspNetCore.Blazor.Cli" Version="0.7.0" />
    </ItemGroup>
    
    </Project>
    

That's it! You're now ready to try out the latest Blazor features.

Cascading values and parameters

Blazor components can accept parameters that can be used to flow data into a component and impact the component's rendering. Parameter values are provided from parent component to child component. Sometimes, however, it's inconvenient to flow data from an ancestor component to a descendent component, especially when there are many layers in between. Cascading values and parameters solve this problem by providing a convenient way for an ancestor component to provide a value that is then available to all descendent components. They also provide a great way for components to coordinate.

For example, if you wanted to provide some theme information for a specific part of your app you could flow the relevant styles and classes from component to component, but this would be tedious and cumbersome. Instead, a common ancestor component can provide the theme information as a cascading value that descendents can accept as a cascading parameter and then consume as needed.

Let's say the following ThemeInfo class specifies all of the theme information that you want to flow down the component hierarchy so that all of the buttons within that part of your app share the same look and feel:

public class ThemeInfo 
{
    public string ButtonClass { get; set; }
}

An ancestor component can provide a cascading value using the CascadingValue component. The CascadingValue component wraps a subtree of the component hierarchy and specifies a single value that will be available to all components within that subtree. For example, we could specify the theme info in our application layout as a cascading parameter for all components that make up the layout body like this:

@inherits BlazorLayoutComponent

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">
    <div class="top-row px-4">
        <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
    </div>

    <CascadingValue Value="@theme">
        <div class="content px-4">
            @Body
        </div>
    </CascadingValue>
</div>

@functions {
    ThemeInfo theme = new ThemeInfo { ButtonClass = "btn-success" };
}

To make use of cascading values, components can declare cascading parameters using the [CascadingParameter] attribute. Cascading values are bound to cascading parameters by type. In the following example the Counter component is modified to have a cascading parameter that binds to the ThemeInfo cascading value, which is then used to set the class for the button.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn @ThemeInfo.ButtonClass" onclick="@IncrementCount">Click me</button>

@functions {
    int currentCount = 0;

    [CascadingParameter] protected ThemeInfo ThemeInfo { get; set; }

    void IncrementCount()
    {
        currentCount++;
    }
}

When we run the app we can see that the new style is applied:

Counter with cascading parameter

Cascading parameters also enable components to collaborate across the component hierarchy. For example, let's say you have a TabSet component that contains a number of Tab components, like this:

<TabSet>
    <Tab Title="First tab">
        <h4>First tab</h4>
        This is the first tab.
    </Tab>

    @if (showSecondTab)
    {
        <Tab Title="Second">
            <h4>Second tab</h4>
            You can toggle me.
        </Tab>
    }

    <Tab Title="Third">
        <h4>Third tab</h4>

        <label>
            <input type="checkbox" bind=@showSecondTab />
            Toggle second tab
        </label>
    </Tab>
</TabSet>

In this example the child Tab components are not explicitly passed as parameters to the TabSet. Instead they are simply part of the child content of the TabSet. But the TabSet still needs to know about each Tab so that it can render the headers and the active tab. To enable this coordination without requiring any specific wire up from the user, the TabSet component can provide itself as a cascading value that can then be picked up by the descendent Tab components:

In TabSet.cshtml

<!-- Display the tab headers -->
<CascadingValue Value=this>
    <ul class="nav nav-tabs">
        @ChildContent
    </ul>
</CascadingValue>

This allows the descendent Tab components to capture the containing TabSet as a cascading parameter, so they can add themselves to the TabSet and coordinate on which Tab is active:

In Tab.cshtml

[CascadingParameter] TabSet ContainerTabSet { get; set; }

Check out the full TabSet sample here.

Debugging improvements

In Blazor 0.5.0 we added some very preliminary support for debugging client-side Blazor apps in the browser. While this initial debugging support demonstrated that debugging .NET apps in the browser was possible, it was still a pretty rough experience. Blazor 0.7.0 picks up the latest runtime updates, which includes some fixes that makes the debugging experience more reliable. You can now more reliably set and remove breakpoints, and the reliability of step debugging has been improved.

Improved Blazor debugging

Give feedback

We hope you enjoy this latest preview release of Blazor. As with previous releases, your feedback is important to us. If you run into issues or have questions while trying out Blazor, file issues on GitHub. You can also chat with us and the Blazor community on Gitter if you get stuck or to share how Blazor is working for you. After you've tried out Blazor for a while please let us know what you think by taking our in-product survey. Click the survey link shown on the app home page when running one of the Blazor project templates:

Blazor survey

Thanks for trying out Blazor!

Razor support in Visual Studio Code now in Preview

$
0
0

Earlier this week we released a preview of support for working with Razor files (.cshtml) in the C# extension for Visual Studio Code (1.17.1). This initial release introduces C# completions, directive completions, and basic diagnostics (red squiggles for errors) for ASP.NET Core projects.

Prerequisites

To use this preview of Razor support in Visual Studio Code install the following:

If you already installed VS Code and the C# extension in the past, make sure you have updated to the latest versions of both.

Get started

To try out the new Razor tooling, create a new ASP.NET Core web app and then edit any Razor (.cshtml) file.

  1. Open Visual Studio Code
  2. Select Terminal > New Terminal
  3. In the new terminal run:

    dotnet new webapp -o WebApp1`
    code -r WebApp1
    
  4. Open About.cshtml

  5. Try out HTML completions

    HTML completions

  6. And Razor directive completions

    Directive completions

  7. And C# completions

    C# completions

  8. You also get diagnostics (red squiggles)

    C# diagnostics

Limitations and known issues

This is the first alpha release of the Razor tooling for Visual Studio Code, so there are a number of limitations and known issues:

  • Razor editing is currently only supported in ASP.NET Core projects (no support for ASP.NET projects or Blazor projects yet)
  • Support for tag helpers and formatting is not yet implemented
  • Limited support for colorization
  • Loss of HTML completions following C# less than (<) operator
  • Error squiggles misaligned for expressions near the start of a new line
  • Incorrect errors in Blazor projects for event bindings
  • Emmet based abbreviation expansion is not yet supported

Note that if you need to disable the Razor tooling for any reason:

  • Open the Visual Studio Code User Settings: File -> Preferences -> Settings
  • Search for "razor"
  • Check the "Razor: Disabled" checkbox

Feedback

Even though the functionality of Razor tooling is currently pretty limited, we are shipping this preview now so that we can start collecting feedback. Any issues or suggestions for the Razor tooling in Visual Studio Code should be reported on the https://github.com/aspnet/Razor.VSCode repo.

To help us diagnose any reported issues please provide the following information in the GitHub issue:

  1. Razor (cshtml) file content
  2. Generated C# code from the Razor CSharp output
    • Right-click inside your .cshtml file and select "Command Palette"
    • Search for and select "Razor: Show Razor CSharp"
  3. Verbose Razor log output
    • See instructions for capturing the Razor log output here
  4. OmniSharp log output
    • Open VS Code's "Output" pane
    • In the dropdown choose "OmniSharp Log"

What's next?

Next up we are working on tag helper support. This will include support for tag helper completions and IntelliSense. Once we have tag helper tooling support in place we can then start work on enabling Blazor tooling support as well. Follow our progress and join in the conversation on the https://github.com/aspnet/Razor.VSCode repo.

Thanks for trying out this early preview!

Announcing ASP.NET Core 2.2, available today!

$
0
0

I’m happy to announce that ASP.NET Core 2.2 is available as part of .NET Core 2.2 today!

How to get it

You can download the new .NET Core SDK (2.2.100) for your dev machine and build servers from the .NET Core 2.2 download page. New Windows Server hosting, runtime installers and binary archives are also available from this page for updating servers.

This release updates .NET Core, ASP.NET Core, and Entity Framework Core to version 2.2.0. The new SDK version is 2.2.100. Visual Studio requirements are as follows:

Visual Studio 2019 16.0 Preview 1, also available today, includes the .NET Core SDK 2.2.100 as an optional component.

What’s new?

The main theme for this ASP.NET Core release was to improve developer productivity and platform functionality with regard to building Web/HTTP APIs. As usual, we made some performance improvements as well. We’ve posted about these features as part of the preview releases and you as such you can read about them by following the links below:

Health Checks integration with BeatPulse

We’re happy to announce that the BeatPulse project now supports the new Health Checks API, which means you can easily add checks for dozens of popular systems and dependencies using their great support. Here’s a message from the BeatPulse team about their support for our new Health Checks API:

BeatPulse is a community driven project that was created to provide health checking mechanisms for systems, networking and a wide variety of services that are common within the enterprise, e.g. SqlServer, MySql,Postgress, Redis, Kafka and many more . When Microsoft announced ASP.NET Core Health Checks for the 2.2 roadmap, the BeatPulse team ported all the existing liveness packages and features to work with the new Microsoft Health Checks abstractions at the repository AspNetCore.Diagnostics.HealthChecks. Apart from all the health checking packages, the BeatPulse team also incorporates other features like pulse tracking (Application Insights and Prometheus), failure notifications and a UI interface were we can configure different monitored systems and have a global view of health status. This UI is available as a Docker image published in Docker Hub.

More coming soon

When we announced planning for ASP.NET Core 2.2, we mentioned a number of features that aren’t detailed above, including API Authorization with IdentityServer4, Open API (Swagger) driven client code generation, and the HTTP REPL command line tool. These features are still being worked on and aren’t quite ready for release, however we expect to make them available as add-ons in the coming months. Thanks for your patience while we complete these experiences and get them ready for you all to try out.

Migrating a project to ASP.NET Core 2.2

To migrate an ASP.NET Core project from 2.1 to 2.2, open the project’s .csproj file and change the value of the TargetFramework element to netcoreapp2.2. You do not need to do this if you’re targeting .NET Framework 4.x.

Finish by updating your NuGet package references to the latest stable versions. Note that projects targeting .NET Core (rather than .NET Framework) should not have a package version specified for the Microsoft.AspNetCore.App package reference as this will be managed automatically by the SDK. Doing so will now result in a build warning.

For more information on upgrading to ASP.NET Core 2.2 see here.

Support life cycle

ASP.NET Core 2.2 is the latest release in the “Current” .NET Core train. This represents the first release since the declaration of 2.1 LTS that reestablishes a separate LTS and Current train. The Current train is where new features, enhancements, and regular bug fixes are applied and is recommended for most customers. Note that both LTS and Current releases receive servicing updates for security and critical stability fixes. It is currently expected that 2.2 will the last non-servicing release in the 2.x life cycle, and as such customers not using an LTS release will need to migrate to 3.0 GA, within 3 months of its release in the second half of 2019 in order to remain supported.

Read more about the .NET Core support policy here.

Availability in Azure App Service

The .NET Core 2.2 SDK, runtime, and updated ASP.NET Core IIS Module are in the process of being deployed to Azure App Service regions around the world. We expect this to be completed before the end of December 2018.

Some regions may receive the updated runtime before the updated ASP.NET Core IIS Module (ANCM), which is required by default for projects targeting ASP.NET Core 2.2. It’s also a requirement for the new in-process hosting feature. If you receive startup errors after deploying to Azure App Service, try configuring your project to use the existing version of ANCM by setting the AspNetCoreModule property to the value “AspNetCoreModule”, e.g.:

<PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>
    <AspNetCoreModuleName>AspNetCoreModule</AspNetCoreModuleName>
    <AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
</PropertyGroup>

Once the target region has been updated with the latest ANCM version, you can remove that property altogether and redeploy the application to have it switch to using the new ANCM.

This release also adds better 64-bit support for .NET Core in Azure App Service. If you’re running your ASP.NET Core application on .NET Core 2.2 with in-process hosting, you can simply enable the 64-bit option in the Azure Portal and the site will now run in a 64-bit process. For other information on how to run your ASP.NET Core application in a 64-bit process in Azure App Service with other configurations, see this article.

Giving feedback

As always, please provide us feedback by logging issues at https://github.com/aspnet/AspNetCore. We look forward to hearing from you!

ASP.NET Core updates in .NET Core 3.0 Preview 2

$
0
0

.NET Core 3.0 Preview 2 is now available and it includes a bunch of new updates to ASP.NET Core.

Here's the list of what's new in this preview:

  • Razor Components
  • SignalR client-to-server streaming
  • Pipes on HttpContext
  • Generic host in templates
  • Endpoint routing updates

Get started

To get started with ASP.NET Core in .NET Core 3.0 Preview 2 install the .NET Core 3.0 Preview 2 SDK

If you're on Windows using Visual Studio, you'll also want to install the latest preview of Visual Studio 2019.

Upgrade an existing project

To upgrade an existing an ASP.NET Core app to .NET Core 3.0 Preview 2, follow the migrations steps in the ASP.NET Core docs.

Add package for Json.NET

As part of the work to tidy up the ASP.NET Core shared framework, Json.NET is being removed from the shared framework and now needs to be added as a package.

To add back Json.NET support to an ASP.NET Core 3.0 project:

Runtime compilation removed

As a consequence of cleaning up the ASP.NET Core shared framework to not depend on Roslyn, support for runtime compilation of pages and views has also been removed in this preview release. Instead compilation of pages and views is performed at build time. In a future preview update we will provide a NuGet packages for optionally enabling runtime compilation support in an app.

Other breaking changes and announcements

For a full list of other breaking changes and announcements for this release please see the ASP.NET Core Announcements repo.

Build modern web UI with Razor Components

Razor Components are a new way to build interactive client-side web UI with ASP.NET Core. This release of .NET Core 3.0 Preview 2 adds support for Razor Components to ASP.NET Core and for hosting Razor Components on the server. For those of you who have been following along with the experimental Blazor project, Razor Components represent the integration of the Blazor component model into ASP.NET Core along with the server-side Blazor hosting model. ASP.NET Core Razor Components is a new capability in ASP.NET Core to host Razor Components on the server over a real-time connection.

Working with Razor Components

Razor Components are self-contained chunks of user interface (UI), such as a page, dialog, or form. Razor Components are normal .NET classes that define UI rendering logic and client-side event handlers, so you can write rich interactive web apps without having to write any JavaScript. Razor components are typically authored using Razor syntax, a natural blend of HTML and C#. Razor Components are similar to Razor Pages and MVC Views in that they both use Razor. But unlike pages and views, which are built around a request/reply model, components are used specifically for handling UI composition.

To create, build, and run your first ASP.NET Core app with Razor Components run the following from the command line:

dotnet new razorcomponents -o WebApplication1
cd WebApplication1
dotnet run

Or create an ASP.NET Core Razor Components in Visual Studio 2019:

Razor Components template

The generated solution has two projects: a server project (WebApplication1.Server), and a project with client-side web UI logic written using Razor Components (WebApplication1.App). The server project is an ASP.NET Core project setup to host the Razor Components.

Razor Components solution

Why two projects? In part it's to separate the UI logic from the rest of the application. There is also a technical limitation in this preview that we are using the same Razor file extension (.cshtml) for Razor Components that we also use for Razor Pages and Views, but they have different compilation models, so they need to kept separate. In a future preview we plan to introduce a new file extension for Razor Components (.razor) so that you can easily host your components, pages, and views all in the same project.

When you run the app you should see multiple pages (Home, Counter, and Fetch data) on different tabs. On the Counter page you can click a button to increment a counter without any page refresh. Normally this would require writing JavaScript, but here everything is written using Razor Components in C#!

Razor Components app

Here's what the Counter component code looks like:

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount+=1;
    }
}

Making a request to /counter, as specified by the @page directive at the top, causes the component to render its content. Components render into an in-memory representation of the render tree that can then be used to update the UI in a very flexible and efficient way. Each time the "Click me" button is clicked the onclick event is fired and the IncrementCount method is called. The currentCount gets incremented and the component is rendered again. The runtime compares the newly rendered content with what was rendered previously and only the changes are then applied to the DOM (i.e. the updated count).

You can use components from other components using an HTML-like syntax where component parameters are specified using attributes or child content. For example, you can add a Counter component to the app's home page like this:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter />

To add a parameter to the Counter component update the @functions block to add a property decorated with the [Parameter] attribute:

@functions {
    int currentCount = 0;

    [Parameter] int IncrementAmount { get; set; } = 1;

    void IncrementCount()
    {
        currentCount+=IncrementAmount;
    }
}

Now you can specify IncrementAmount parameter value using an attribute like this:

<Counter IncrementAmount="10" />

The Home page then has it's own counter that increments by tens:

Count by tens

This is just an intro to what Razor Components are capable of. Razor Components are based on the Blazor component model and they support all of the same features (parameters, child content, templates, lifecycle events, component references, etc.). To learn more about Razor Components check out the component model docs and try out building your first Razor Components app yourself.

Hosting Razor Components

Because Razor Components decouple a component's rendering logic from how the UI updates get applied, there is a lot of flexibility in how Razor Components can be hosted. ASP.NET Core Razor Components in .NET Core 3.0 adds support for hosting Razor Components on the server in an ASP.NET Core app where all UI updates are handled over a SignalR connection. The runtime handles sending UI events from the browser to the server and then applies UI updates sent by the server back to the browser after running the components. The same connection is also used to handle JavaScript interop calls.

ASP.NET Core Razor Components

Alternatively, Blazor is an experimental single page app framework that runs Razor Components directly in the browser using a WebAssembly based .NET runtime. In Blazor apps the UI updates from the Razor Components are all applied in process directly to the DOM.

Blazor

Support for the client-side Blazor hosting model using WebAssembly won't ship with ASP.NET Core 3.0, but we are working towards shipping it with a later release.

Regardless of which hosting model you use for your Razor Components, the component model is the same. The same Razor Components can be used with either hosting model. You can even switch your app back and forth from being a client-side Blazor app or Razor Components running in ASP.NET Core using the same components as long as your components haven't taken any server specific dependencies.

JavaScript interop

Razor Components can also use client-side JavaScript if needed. From a Razor Component you can call into any browser API or into an existing JavaScript library running in the browser. .NET library authors can use JavaScript interop to provide .NET wrappers for JavaScript APIs, so that they can be conveniently called from Razor Components.

public class ExampleJsInterop
{
    public static Task<string> Prompt(this IJSRuntime js, string text)
    {
        // showPrompt is implemented in wwwroot/exampleJsInterop.js
        return js.InvokeAsync<string>("exampleJsFunctions.showPrompt", text);
    }
}
@inject IJSRuntime JS

<button onclick="@OnClick">Show prompt</button>

@functions {
    string name;

    async Task OnClick() {
        name = await JS.Prompt("Hi! What's you're name?");
    }
}

Both Razor Components and Blazor share the same JavaScript interop abstraction, so .NET libraries relying on JavaScript interop are usable by both types of apps. Check out the JavaScript interop docs for more details on using JavaScript interop and the Blazor community page for existing JavaScript interop libraries.

Sharing component libraries

Components can be easily shared and reused just like you would normal .NET classes. Razor Components can be built into component libraries and then shared as NuGet packages. You can find existing component libraries on the Blazor community page.

The .NET Core 3.0 Preview 2 SDK doesn't include a project template for Razor Component Class Libraries yet, but we expect to add one in a future preview. In meantime, you can use Blazor Component Class Library template.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::0.8.0-preview-19104-04 
dotnet new blazorlib

In this preview release ASP.NET Core Razor Components don't yet support using static assets in component libraries, so the support for component class libraries is pretty limited. However, in a future preview we expect to add this support for using static assets from a library just like you can in Blazor today.

Integration with MVC Views and Razor Pages

Razor Components can be used with your existing Razor Pages and MVC apps. There is no need to rewrite existing views or pages to use Razor Components. Components can be used from within a view or page. When the page or view is rendered, any components used will be prerendered at the same time.

To render a component from a Razor Page or MVC View in this release, use the RenderComponentAsync<TComponent> HTML helper method:

<div id="Counter">
    @(await Html.RenderComponentAsync<Counter>(new { IncrementAmount = 10 }))
</div>

Components rendered from pages and views will be prerendered, but are not yet interactive (i.e. clicking the Counter button doesn't do anything in this release). This will get addressed in a future preview, along with adding support for rendering components from pages and views using the normal element and attribute syntax.

While views and pages can use components the converse is not true: components can't use views and pages specific features, like partial views and sections. If you want to use a logic from partial view in a component you'll need to factor that logic out first as a component.

Cross platform tooling

Visual Studio 2019 comes with built-in editor support for Razor Components including completions and diagnostics in the editor. You don't need to install any additional extensions.

Razor Components tooling

Razor Component tooling isn't available yet in Visual Studio for Mac or Visual Studio Code, but it's something we are actively working on.

A bright future for Blazor

In parallel with the ASP.NET Core 3.0 work, we will continue ship updated experimental releases of Blazor to support hosting Razor Components client-side in the browser (we'll have more to share on the latest Blazor update shortly!). While in ASP.NET Core 3.0 we will only support hosting Razor Components in ASP.NET Core, we are also working towards shipping Blazor and support for running Razor Components in the browser on WebAssembly in a future release.

SignalR client-to-server streaming

With ASP.NET Core SignalR we added Streaming support, which enables streaming return values from server-side methods. This is useful for when fragments of data will come in over a period of time.

With .NET Core 3.0 Preview 2 we've added client-to-server streaming. With client-to-server streaming, your server-side methods can take instances of a ChannelReader<T>. In the C# code sample below, the StartStream method on the Hub will receive a stream of strings from the client.

public async Task StartStream(string streamName, ChannelReader<string> streamContent)
{
    // read from and process stream items
    while (await streamContent.WaitToReadAsync(Context.ConnectionAborted))
    {
        while (streamContent.TryRead(out var content))
        {
            // process content
        }
    }
}

Clients would use the SignalR Subject (or an RxJS Subject) as an argument to the streamContent parameter of the Hub method above.

let subject = new signalR.Subject();
await connection.send("StartStream", "MyAsciiArtStream", subject);

The JavaScript code would then use the subject.next method to handle strings as they are captured and ready to be sent to the server.

subject.next("example");
subject.complete();

Using code like the two snippets above, you can create real-time streaming experiences. For a preview of what you can do with client-side streaming with SignalR, take a look at the demo site, streamr.azurewebsites.net. If you create your own stream, you can stream ASCII art representations of image data being captured by your local web cam to the server, where it will be bounced out to other clients who are watching your stream.

Client-to-server Streaming with SignalR

System.IO.Pipelines on HttpContext

In ASP.NET Core 3.0, we're working on consuming the System.IO.Pipelines API and exposing it in ASP.NET Core to allow you to write more performant applications.

In Preview 2, we're exposing the request body pipe and response body pipe on the HttpContext that you can directly read from and write to respectively in addition to maintaining the existing Stream-based APIs.
While these pipes are currently just wrappers over the existing streams, we will directly expose the underlying pipes in a future preview.

Here's an example that demonstrates using both the request body and response body pipes directly.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting(routes =>
    {
        routes.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello World");
        });

        routes.MapPost("/", async context =>
        {
            while (true)
            {
                var result = await context.Request.BodyPipe.ReadAsync();
                var buffer = result.Buffer;

                if (result.IsCompleted)
                {
                    break;
                }

                context.Request.BodyPipe.AdvanceTo(buffer.End);
            }
        });
    });
}

Generic host in templates

The templates have been updated to use the Generic Host instead of WebHostBuilder as they have in the past:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

This is part of the ongoing plan started in 2.0 to better integrate ASP.NET Core with other server scenarios that are not web specific.

What about IWebHostBuilder?

The IWebHostBuilder interface that is used with WebHostBuilder today will be kept, and is the type of the webBuilder used in the sample code above. We intend to deprecate and eventually remove WebHostBuilder itself as its functionality will be replaced by HostBuilder, though the interface will remain.

The biggest difference between WebHostBuilder and HostBuilder is that you can no longer inject arbitrary services into your Startup.cs. Instead you will be limited to the IHostingEnvironment and IConfiguration interfaces. This removes a behavior quirk related to injecting services into Startup.cs before the ConfigureServices method is called. We will publish more details on the differences between WebHostBuilder and HostBuilder in a future deep-dive post.

Endpoint routing updates

We're excited to start introducing more of the Endpoint Routing story that began in 2.2. Endpoint routing allows frameworks like MVC as well as other routable things to mix with middleware in a way that hasn't been possible before. This is now present in the project templates in 3.0.0-preview-2, we'll continue to add more richness as we move closer to a final release.

Here's an example:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseStaticFiles();

    app.UseRouting(routes =>
    {
        routes.MapApplication();

        routes.MapGet("/hello", context =>
        {
            return context.Response.WriteAsync("Hi there!");    
        });

        routes.MapHealthChecks("/healthz");
    });

    app.UseAuthentication();
    app.UseAuthorization();
}

There's a few things to unpack here.

First, the UseRouting(...) call adds a new Endpoint Routing middleware. UseRouting is at the core of many of the templates in 3.0 and replaces many of the features that were implemented inside UseMvc(...) in the past.

Also notice that inside UseRouting(...) we're setting up a few things. MapApplication() brings in MVC controllers and pages for routing. MapGet(...) shows how to wire up a request delegate to routing. MapHealthChecks(...) hooks up the health check middleware, but by plugging it into routing.

What might be surprising to see is that some middleware now come after UseRouting. Let's tweak this example to demonstrate why that is valuable.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseStaticFiles();

    app.UseRouting(routes =>
    {
        routes.MapApplication();

        routes.MapGet("/hello", context =>
        {
            return context.Response.WriteAsync("Hi there! Here's your secret message");    
        })
        .RequireAuthorization(new AuthorizeAttribute(){ Roles = "secret-messages", });

        routes.MapHealthChecks("/healthz").RequireAuthorization("admin");
    });

    app.UseAuthentication();
    app.UseAuthorization();
}

Now I've added an AuthorizeAttribute to my request delegate. This is just like placing [Authorize(Roles = "secret-messages")] on an action method in a controller. We've also given the health checks middleware an authorization policy as well (by policy name).

This works because the following steps happen in order (ignoring what happens before routing):

  1. UseRouting(...) makes a routing decision – selecting an Endpoint
  2. UseAuthorization() looks at the Endpoint that was selected and runs the corresponding authorization policy
  3. hidden… At the end of the middleware pipeline the Endpoint is executed (if no endpoint was matched then a 404 response is returned)

So think of UseRouting(...) as making a deferred routing decision – where middleware that appear after it run in the middle. Any middleware that run after routing can see the results and read or modify the route data and chosen endpoint. When processing reaches the end of the pipeline, then the endpoint is invoked.

What is an Endpoint and why did we add this?

An Endpoint is a new primitive to help frameworks (like MVC) be friends with middleware. Fundamentally an Endpoint is a request delegate (something that can execute) plus a bag of metadata (policies).

Here's an example middleware – you can use this to examine endpoints in the debugger or by printing to the console:

app.Use(next => (context) =>
{
    var endpoint = context.GetEndpoint();
    if (endpoint != null)
    {
        Console.WriteLine("Name: " + endpoint.DisplayName);
        Console.WriteLine("Route: " + (endpoint as RouteEndpoint)?.RoutePattern);
        Console.WriteLine("Metadata: " + string.Join(", ", endpoint.Metadata));
    }

    return next(context);
});

In the past we haven't had a good solution when we've wanted to implement a policy like CORS or Authorization in both middleware and MVC. Putting a middleware in the pipeline feels very good because you get to configure the order. Putting filters and attributes on methods in controllers feels really good when you need to apply policies to different parts of the application. Endpoints bring togther all of these advantages.

As an addition problem – what do you do if you're writing the health checks middleware? You might want to secure your middleware in a way that developers can customize. Being able to leverage the ASP.NET Core features for this directly avoids the need to build in support for cross-cutting concerns in every component that serves HTTP.

In addition to removing code duplication from MVC, the Endpoint + Middleware solution can be used by any other ASP.NET Core-based technologies. You don't even need to use UseRouting(...) – all that is required to leverage the enhancements to middleware is to set an Endpoint on the HttpContext.

What's integrated with this?

We added the new authorize middleware so that you can start doing more powerful security things with just middleware. The authorize middleware can accept a default policy that applies when there's no endpoint, or the endpoint doesn't specify a policy.

CORS is also now endpoint routing aware and will use the CORS policy specified on an endpoint.

MVC also plugs in to endpoint routing and will create endpoints for all of your controllers and pages. MVC can now be used with the CORS and authorize features and will largely work the same. We've long had confusion about whether to use the CORS middleware or CORS filters in MVC, the updated guidance is to use both. This allows you to provide CORS support to other middleware or static files, while still applying more granular CORS policies with the existing attributes.

Health checks also provide methods to register the health checks middleware as a router-ware (as shown above). This allows you to specify other kinds of policies for health checks.

Finally, new in ASP.NET Core 3.0 preview 2 is host matching for routes. Placing the HostAttribute on an MVC controller or action will prompt the routing system to require the specified domain or port. Or you can use RequireHost in your Startup.cs:

app.UseRouting(routes =>
{
    routes.MapGet("/", context => context.Response.WriteAsync("Hi Contoso!"))
        .RequireHost("contoso.com");

    routes.MapGet("/", context => context.Response.WriteAsync("Hi AdventureWorks!"))
        .RequireHost("adventure-works.com");

    routes.MapHealthChecks("/healthz").RequireHost("*:8080");
});

Do you think that there are things that are missing from the endpoint story? Are there more things we should make smarter or more integrated? Please let us know what you'd like to see.

Give feedback

We hope you enjoy the new features in this preview release of ASP.NET Core! Please let us know what you think by filing issues on Github.

Viewing all 7144 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>