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

Exploring Azure App Service – Web Apps and SQL Azure

$
0
0

There is a good chance that your web app uses a database. In my previous post introducing Azure App Service, I showed some of the benefits of hosting apps in Azure App Service, and how easy it is to get a basic site running in a few clicks. In this post I’ll show how to set up a SQL Azure database along with an App Service Web App from Visual Studio, and apply Entity Framework automatically as part of publish.

Let’s get going

To get started, you’ll first need:

  • Visual Studio 2017 with the ASP.NET and web development workload installed (download now)
  • An Azure account:
  • Any ASP.NET or ASP.NET Core app that uses a SQL Database. For the purposes of this post, I’ll create a new ASP.NET Core app with Individual Authentication:
    • On the “New ASP.NET Core Web Application” dialog, click the “Change Authentication” button.
      clip_image002
  • Then select the “Individual User Accounts” radio button and click “OK”.
  • Click OK.

I can now run my project locally (F5) and create user accounts which will be stored in a SQL Server Express Local DB on my machine.

Publishing to App Service with a Database

Let’s publish our application to Azure. To do this, I’ll right click my project in Solution Explorer and choose “Publish”

clip_image003

This brings up the Visual Studio publish target dialog, which will default to the Azure App Service pane with the “Create new” radio button selected. To continue click “Publish”.

This brings up the “Create App Service” dialog (see the “Key App Service Concepts” section of my previous post for an explanation of the fields). To create a SQL Database for our app to use, click the “Create a SQL Database” link in the top right section of the dialog.

clip_image005

This will bring up the “Configure SQL Database” dialog.

  • Note: If you are using a Visual Studio Enterprise subscription, many regions will not let you create a SQL Azure database so I recommend choosing “East US” or “West US 2” depending on where you are located (we are adding logic in in the Visual Studio 2017 15.8 update to remove those regions if that’s the case, but for now you’ll need to choose an appropriate region). To do this, click the “New…” button next to your “Hosting Plan Dropdown” and pick the appropriate region (“East US” or “West US 2”).
  • Since I don’t have an existing SQL Server, the first thing I need to do is create a server to host the database, so I’ll click the “New…” button next to the “SQL Server” dropdown,
  • Choose a location for the database.
  • Provide an administrator user name and password for the server
  • Click “OK”
    clip_image007
  • Make sure the connection string name field matches the name of the connection string your application uses to access the database (if using a new project, it is “DefaultConnection” which will be prepopulated for you).
    clip_image009
  • Click OK
  • Then click the “Create” button on the “Create App Service” dialog

It should take ~2-3 minutes to create all of the resources in Azure, then your application will publish and a browser will open to your home page.

Configuring EF Migrations

At this point there is a database for your app to use in the cloud, but EF migrations have not been applied, so any functionality that relies on the database (e.g. Registering for a user account) will result in an error.

To apply EF migrations to the database:

  • Click the “Configure…” button on the publish summary page
    clip_image011
  • Navigate to the “Settings” tab
  • When it finishes discovering data contexts, expand the “Entity Framework Migrations” section, and check the “Apply this migration on publish” for all of the contexts it finds
    clip_image013
  • Click “Save”
  • Click Publish again, in the output window you should see “Generating Entity framework SQL Scripts” and then “Generating Entity framework SQL Scripts completed successfully”
    clip_image015

That’s it, your web app and SQL Azure database are both configured and running in the cloud.

Conclusion

Hopefully, this post showed you how easy it is to try App Service and SQL Azure. We believe that for most people, App Service is the easiest place to get started with cloud development, even if you need to move to other services in the future for further capabilities (compare hosting options). As always, let us know if you run into any issues, or have any questions below or via Twitter.


A Penny Saved is a Ton of Serverless Compute Earned

$
0
0

Scott Guthrie recently shared one of my favorite anecdotes on his Azure Red Shirt Tour. A Microsoft customer regularly invokes 1 billion (yes, that’s with a “B”) Azure Functions per day. The customer reached out to support after the first month thinking there was a bug in the billing system, only to find out that the $72 was in fact correct. How is that possible? Azure Functions is a serverless compute platform that allows you to focus on code that only executes when triggered by events, and you only pay for CPU time and memory used during execution (versus a traditional web server where you are paying a fee even if your app is idle). This is called micro-billing, and is one key reason serverless computing is so powerful.

Curious about Azure Functions? Follow the link https://aka.ms/go-funcs to get up and running with your first function in minutes.

Scott Guthrie Red Shirt

Scott Guthrie on the Azure Red Shirt Tour

In fact, micro-billing is so important, it’s one of three rules I use to verify if a service is serverless. There is not an official set of rules and there is no standard for serverless. The closest thing to a standard is the whitepaper published by the Cloud Native Computing Foundation titled CNCF WG-Serverless Whitepaper v1.0 (PDF). The paper describes serverless computing as “building and running applications that do not require server management.” The paper continues to state they are “executed, scaled, and billed in response to the exact demand needed at the moment.”

It’s easy to label almost everything serverless, but there is a difference between managed and serverless. A managed service takes care of responsibilities for you, such as standing up a website or hosting a Docker container. Serverless is a managed service but requires a bit more. Here is Jeremy’s Serverless Rules.

  1. The service should be capable of running entirely in the cloud. Running locally is fine and often preferred for developing, testing, and debugging, but ultimately it should end up in the cloud.
  2. You don’t have to configure a virtual machine or cluster. Docker is great, but containers require a Docker host to run. That host typically means setting up a VM and, for resiliency and scale, using an orchestrator like Kubernetes to scale the solution. There are also services like Azure Web Apps that provide a fully managed experience for running web apps and containers, but I don’t consider them serverless because they break the next rule.
  3. You only pay for active invocations and never for idle time. This rule is important, and the essence of micro-billing. ACI is a great way to run a container, but I pay for it even when it’s not being used. A function, on the other hand, only bills when it’s called.

These rules are why I stopped calling managed databases “serverless.” So, what, then, does qualify as serverless?

The Azure serverless platform includes Azure Functions, Logic Apps, and Event Grid. In this post, we’ll take a closer look at Azure Functions.

Azure Functions

Azure Functions allows you to write code that is executed based on an event, or trigger. Triggers may include an HTTP request, a timer, a message in a queue, or any other number of important events. The code is passed details of the trigger but can also access bindings that make it easier to connect to resources like databases and storage. The serverless Azure Functions model is based on two parameters: invocations and gigabyte seconds.

Invocations are the number of times the function is invoked based on its trigger. Gigabyte seconds is a function of memory usage. Image a graph that shows time on the x-axis and memory consumption on the y-axis. Plot the memory usage of your function over time. Gigabyte seconds represent the area under the curve.

Let’s assume you have a microservice that is called every minute and takes one second to scan and aggregate data. It uses a steady 128 megabytes of memory during the run. Using the Azure Pricing Calculator, you’ll find that the cost is free. That’s because the first 400,000 Gigabyte seconds and 1 million invocations are free every month. Running every second (there are 2,628,000 seconds in a month) with double memory (256 megabytes), the entire monthly cost is estimated at $4.51.

Azure Functions pricing

Pricing calculator for Azure Functions

Recently I tweeted about my own experience with serverless cost (or lack thereof). I wrote a link-shortening tool. It uses a function to take long URLs and turn them into a shorter code I can easily share. I also have a function that takes the short code and performs the redirect, then stores the data in a queue. Another microservice processes items in the queue and stores metadata that I can analyze for later. I have tens of thousands of invocations per month and my total cost is less than a dollar.

Link shortener stats

A tweet about cost of running serverless code in Azure

Do I have your attention?

In future posts I will explore the cost model for Logic Apps and Event Grid. In the meantime…

Learn about and get started with your first Azure Function by following this link: https://aka.ms/go-funcs

Announcing ASP.NET Providers Connected Service Visual Studio Extension

$
0
0

Provider pattern was introduced in ASP.NET 2.0 and it gives the developers the flexibility of where to store the state of ASP.NET features (e.g. Session State, Membership, Output Cache etc.). In ASP.NET 4.6.2, we added async support for Session State Provider and Output Cache Provider.  These providers provide much better scalability, and enables the web application to adapt to the cloud environment.  Furthermore, , we also released SqlSessionStateProviderAsync, CosmosDBSessionStateProviderAsync, RedisSessionStateProvider and SQLAsyncOutputCacheProvider.  Through these providers the web applications can store the Session State in Azure resources like, SQL Azure, CosmosDB, and Redis Cache, and Output Cache in SQL Azure.  With these options, it may be not very straightforward to pick one and configure it right in the application.  Today we are releasing ASP.NET Providers Connected Service Visual Studio Extension to help you pick the right provider and configure it properly to work with Azure resources.  This extension will be your one-stop shop where you can install and configure all the ASP.NET providers that are Azure ready.

How to install the extension

The ASP.NET Providers Connected Service Extension can be installed on Visual Studio 2017. You can install it through Extensions and Updates in Visual Studio and type “ASP.NET Providers Connected Service” in the search box. Or you can download the extension from Visual Studio MarketPlace.

How to use the extension

To use the Extension, you need to make sure that your web application targets to .NET Framework 4.6.2 or higher.  You can open the extension through right clicking on the project, selecting Add and clicking on Connected Service. You will see all the Connected Services installed on your VS which apply to your project.

After clicking on Microsoft ASP.NET Providers extension. You will see the following wizard window, you can choose the provider you want to install and configure for your ASP.NET web application. Currently we have two sets of providers, Session State providers and Output Cache provider.

Select a provider and click on the Next button. You will see a list of providers that apply to your application, which connects with Azure resources. Currently we have SQL SessionState provider, CosmosDB SessionState provider, RedisCache Sessionstate provider and SQL OutputCache provider.

After the provider is chosen, the wizard window will lead you to select an Azure instance which will be used by the provider selected.  In order to fetch the Azure instances that apply to the selected provider, you will need to sign in with your account in Visual Studio.   Then Select an Azure instance and click on the Finish button, the extension will install the relevant Nuget packages and update the web.config file to connect the provider with that selected Azure instance.

Things to be aware of

  1. If the application is already configured with a provider and you want to install a same type of provider, you need to remove that provider first. E.g. your application is using SQL SessionState provider and you want to switch to CosmosDB SessionState provider. In this case, you need to remove the SessionState Provider settings in the web.config, then you can use ASP.NET Providers Connected Services to install and configure the CosmosDB SessionState provider.
  2. If you are installing Async SQL SessionState provider or Async SQL OutputCache provider, you need to replace the user name and password in the connection string in web.config added by ASP.NET Providers Connected Services. As you may have multiple accounts in your Azure SQL Database instance.

Summary

ASP.NET Providers Connected Services helps you install and configure ASP.NET providers for your web application to consume Azure services. Our goal of this Visual Studio extension is to make it easier and provide a central place to help you configure different providers for the ASP.NET web applications and connect your web applications with Azure. Please install the extension from Visual Studio Marketplace today and let us know your feedback.

ASP.NET Core Performance Improvements

$
0
0
This is a guest post by Mike Rousos

I recently had an opportunity to help a developer with an ASP.NET Core app that was functionally correct but slow when under a heavy user load. We found a few different factors contributing to the app’s slowdown while investigating, but the majority of the issues were some variation of blocking threads that could have run in a non-blocking way. It was a good reminder for me just how crucial it is to use non-blocking patterns in multi-threaded scenarios like a web app.

Beware of Locks

One of the first problems we noticed (through CPU analysis with PerfView) was that a lot of time was spent in logging code paths. This was confirmed with ad hoc exploration of call stacks in the debugger which showed many threads blocked waiting to acquire a lock. It turns out some common logging code paths in the application were incorrectly flushing Application Insights telemetry. Flushing App Insights requires a global lock and should generally not be done manually during the course of an app’s execution. In this case, though, Application Insights was being flushed at least once per HTTP request and, under load, this became a large bottleneck!

You can see this sort of pattern in the images below from a small repro I made. In this sample, I have an ASP.NET Core 2.0 web API that enables common CRUD operations against an Azure SQL database with Entity Framework Core. Load testing the service running on my laptop (not the best test environment), requests were processed in an average of about 0.27 seconds. After adding a custom ILoggerProvider calling Console.WriteLine inside of a lock, though, the average response time rose to 1.85 seconds – a very noticeable difference for end users. Using PerfView and a debugger, we can see that a lot of time (66% of PerfView’s samples) is spent in the custom logging method and that a lot of worker threads are stuck there (delaying responses) while waiting for their turn with the lock.

Something's up with this logging call

Something’s up with this logging call

 

Threads waiting on lock acquisition

Threads waiting on lock acquisition

ASP.NET Core’s Console logger used to have some locking like this in versions 1.0 and 1.1, causing it to be slow in high-traffic scenarios, but these issues have been addressed in ASP.NET Core 2.0. It is still a best practice to be mindful of logging in production, though.

For very performance-sensitive scenarios, you can use LoggerMessage to optimize logging even further. LoggerMessage allows defining log messages ahead-of-time so that message templates don’t need to be parsed every time a particular message is logged. More details are available in ourdocumentation, but the basic pattern is that log messages are defined as strongly-typed delegates:

// This delegate logs a particular predefined message
private static readonly Action<ILogger, int, Exception> _retrievedWidgets =
    LoggerMessage.Define<int>(
        LogLevel.Information,
        new EventId(1, nameof(RetrievedWidgets)),
        "Retrieved {Count} widgets");

// A helper extension method to make it easy to call the 
// LoggerMessage-produced delegate from an ILogger
public static void RetrievedWidgets(this ILogger logger, int count) =>
    _retrievedWidgets(logger, count, null);

Then, that delegate is invoked as needed for high-performance logging:

var widgets = await _dbContext.Widgets.AsNoTracking().ToListAsync();
_logger.RetrievedWidgets(widgets.Length);

Keep Asynchronous Calls Asynchronous

Another issue our investigation uncovered in the slow ASP.NET Core app was similar: calling Task.Wait() or Task.Result on asynchronous calls made from the app’s controllers instead of using await. By making controller actions async and awaiting these sorts of calls, the executing thread is freed to go serve other requests while waiting for the invoked task to complete.

I reproduced this issue in my sample application by replacing async calls in the action methods with synchronous alternatives. At first, this only caused a small slowdown (0.32 second average response instead of 0.27 seconds) because the async methods I was calling in the sample were all pretty quick. To simulate longer async tasks, I updated both the async and synchronous versions of my sample to have a Task.Delay(200) in each controller action (which, of course, I used await with when async and .Wait() with when synchronous). In the async case, average response time went from 0.27s to 0.46s which is more or less what we would expect if each request has an extra pause or 200ms. In the synchronous case, though, the average time went from 0.32 seconds to 1.47 seconds!

The charts below demonstrate where a lot of this slowdown comes from. The green lines in the charts represent requests served per second and the red lines represent user load. In the first chart (which was taken while running the async version of my sample), you can see that as users increase, more requests are being served. In the second chart (corresponding to theTask.Wait() case), on the other hand, there’s a strange pattern of requests per second remaining flat for several minutes after user load increases and only then increasing to keep up. This is because the existing pool of threads serving requests couldn’t keep up with more users (since they were all blocked on Task.Wait() calls) and throughput didn’t improve until more threads were created.

Threads Keeping Up

Asynchronous RPS compared to user load

 

Sync Thread Growth Lag

Synchronous RPS compared to user load

 

Attaching a debugger to both scenarios, I found that 75 managed threads were being used in the async test but 232 were in use in the synchronous test. Even though the synchronous test did eventually add enough threads to handle the incoming requests, calling Task.Result and Task.Wait can cause slowdowns when user load changes. Analyzers (like AsyncFixer) can help to find places where asynchronous alternatives can be used and there are EventSource events that can be used to find blocking calls at runtime, if needed.

Wrap-Up

There were some other perf issues in the application I helped investigate (server GC wasn’t enabled in ASP.NET Core 1.1 templates, for example, something that has been corrected in ASP.NET Core 2.0), but one common theme of the problems we found was around blocking threads unnecessarily. Whether it’s from lock contention or waiting on tasks to finish, it’s important to keep threads unblocked for good performance in ASP.NET Core apps.

If you’d like to dig into your own apps to look for perf trouble areas, check out the Channel9 PerfView tutorials for an overview of how PerfView can help uncover CPU and memory-related perf issues in .NET applications.

ASP.NET Core 2.1.0 now available

$
0
0

Today we're thrilled to announce the release of ASP.NET Core 2.1.0! This is the latest release of our open-source and cross-platform web framework for .NET and it's now ready for production use. Get started with ASP.NET Core 2.1 today!

New features in this release include:

Check out What's New in ASP.NET Core 2.1 in the ASP.NET Core docs to learn more about these features. For a complete list of all the changes in this release, see the release notes.

ASP.NET Core 2.1.0 is available with .NET Core 2.1.0 along with Entity Framework Core 2.1.0, which you can read about in the corresponding blog posts.

Get started

You can Get started with ASP.NET Core 2.1 in 10 minutes by installing the latest .NET Core SDK and latest Visual Studio release. Then follow the tutorial instructions to create your first ASP.NET Core app.

Migrating an ASP.NET Core 2.0.x project to 2.1.0

For instructions on migrating to ASP.NET Core 2.1 see Migrating from ASP.NET Core 2.0.x project to 2.1.0 in ASP.NET Core documentation.

Deploy to Azure

ASP.NET Core 2.1 is available to be used on Azure App Service today. Publish your ASP.NET Core 2.1 app to Azure App Service.

For apps that use ASP.NET Core SignalR, configure your app to use the new Azure SignalR Service (public preview) to scale the real-time capabilities of your app.

Give feedback

We hope you enjoy using the new features and improvements in ASP.NET Core 2.1.0. If you have any questions or find any issues with this release let us know by filing issues on GitHub.

Thanks for using ASP.NET Core!

Use Dependency Injection In WebForms Application

$
0
0

Dependency Injection design pattern is widely used in modern applications.  It decouples objects to the extent that no client code needs to be changed simply because an object it depends changes to a different one.  It brings you a lot of benefits, like reduced dependency, more reusable code, more testable code, etc.  in the past, it was very difficult to use Dependency Injection in WebForms application before.  Starting from .NET 4.7.2, it is now easy for developers to use Dependency Injection in WebForms applications.  With the UnityAdapter, you can add it to your existing WebForms application in 4 simple steps.

How to enable Dependency Injection in your existing WebForms application

Suppose you have a movie website which lists most popular movies in history.  You use repository pattern to separate the logic that retrieves the data and maps it to the business entity.  Currently you are creating business logic object and repository object in default.aspx page.  The code looks like bellow.

Now simply follow 4 steps below, you will be able to adopt Dependency Injection to decouple the MovieManager from default.aspx page. The sample web application is on this Github repo.  And you can use tag to retrieve the code change in each step.

1. Retarget the project to .NET Framework 4.7.2. (Git Tag: step-1)

Open project property and change the targetFramework of the project to .NET Framework 4.7.2. You would also need to change targetFramework in httpRuntime section in web.config file as illustrated below.

2. Install AspNet.WebFormsDependencyInjection.Unity NuGet package. (Git Tag: step-2)

3. Register types in Global.asax. (Git Tag: step-3)

4. Refactor Default.aspx.cs. (Git Tag: step-4)

Areas that Dependency Injection can be used

There are many areas you can use Dependency Injection in WebForms applications now. Here is a complete list.

  • Pages and controls
    • WebForms page
    • User control
    • Custom control
  • IHttpHandler and IHttpHandlerFactory
  • IHttpModule
  • Providers
    • BuildProvider
    • ResourceProviderFactory
    • Health monitoring provider
    • Any ProviderBase based provider created by System.Web.Configuration.ProvidersHelper.InstantiateProvider. e.g. custom sessionstate provider

 

Summary

Using Microsoft.AspNet.WebFormsDependencyInjection.Unity NuGet package on .net framework 4.7.2, Dependency Injection can be easily added into your existing WebForms application. Please give it a try and let us know your feedback.

Blazor 0.4.0 experimental release now available

$
0
0

Blazor 0.4.0 is now available! This release includes important bug fixes and several new feature enhancements.

New features in Blazor 0.4.0 (details below):

  • Add event payloads for common event types
  • Use camelCase for JSON handling
  • Automatic import of core Blazor namespaces in Razor
  • Send and receive binary HTTP content using HttpClient
  • Templates run on IIS Express by default with autobuild enabled
  • Bind to numeric types
  • JavaScript interop improvements

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

Get Blazor 0.4.0

To get setup with Blazor 0.4.0:

  1. Install the .NET Core 2.1 SDK (2.1.300 or later).
  2. Install Visual Studio 2017 (15.7) with the ASP.NET and web development workload selected.
    • Note: The Blazor tooling is not currently compatible with the VS2017 preview channel (15.8). This will be addressed in a future Blazor release
  3. Install the latest Blazor Language Services extension from the Visual Studio Marketplace.

To install 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.4.0

To upgrade an existing Blazor project from 0.3.0 to 0.4.0:

  • Install all of the required bits listed above.
  • Update your Blazor package and .NET CLI tool references to 0.4.0.

Your upgraded Blazor project file should look like this:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netstandard2.1</TargetFramework>
    <RunCommand>dotnet</RunCommand>
    <RunArguments>blazor serve</RunArguments>
    <LangVersion>7.3</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.4.0" />
    <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.4.0" />
    <DotNetCliToolReference Include="Microsoft.AspNetCore.Blazor.Cli" Version="0.4.0" />
  </ItemGroup>

</Project>

Event payloads for common event types

This release adds payloads for the following event types:

Event arguments Events
UIMouseEventArgs onmouseover, onmouseout, onmousemove, onmousedown, onmouseup, oncontextmenu
UIDragEventArgs ondrag, ondragend, ondragenter, ondragleave, ondragover, ondragstart, ondrop
UIPointerEventArgs gotpointercapture, lostpointercapture, pointercancel, pointerdown, pointerenter, pointerleave, pointermove, pointerout, pointerover, pointerup
UITouchEventArgs ontouchcancel, ontouchend, ontouchmove, ontouchstart, ontouchenter, ontouchleave
UIWheelEventArgs onwheel, onmousewheel
UIKeyboardEventArgs onkeydown, onkeyup
UIKeyboardEventArgs onkeydown, onkeyup, onkeypress
UIProgressEventArgs onloadstart, ontimeout, onabort, onload, onloadend, onprogress, onerror

Thank you to Gutemberg Ribeiro (galvesribeiro) for this contribution! If you haven't checked out Gutemberg's handy collection of Blazor extensions they are definitely worth a look.

Use camelCase for JSON handling

The Blazor JSON helpers and utilities now use camelCase by default. .NET objects serialized to JSON are serialized using camelCase for the member names. On deserialization a case-insensitive match is used. The casing of dictionary keys is preserved.

Automatic import of core for Blazor namespaces in Razor

Blazor now automatically imports the Microsoft.AspNetCore.Blazor and Microsoft.AspNetCore.Blazor.Components namespaces in Razor files, so you don't need to add @using statements for them. One less thing for you to do!

Send and receive binary HTTP content using HttpClient

You can now use HttpClient to send and receive binary data from a Blazor app (previously you could only handle text content). Thank you Robin Sue (Suchiman) for this contribution!

Bind to numeric types

Binding now works with numeric types: long, float, double, decimal. Thanks again to Robin Sue (Suchiman) for this contribution!

Templates run on IIS Express by default with autobuild enabled

The Blazor project templates are now setup to run on IIS Express by default, while still preserving autobuild support.

JavaScript interop improvements

Call async JavaScript functions from .NET

With Blazor 0.4.0 you can now call and await registered JavaScript async functions like you would an async .NET method using the new RegisteredFunction.InvokeAsync method. For example, you can register an async JavaScript function so it can be invoked from your Blazor app like this:

Blazor.registerFunction('BlazorLib1.DelayedText', function (text) {
    // Wait 1 sec and then return the specified text
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(text);
        }, 1000);
    });
});

You then invoke this async JavaScript function using InvokeAsync like this:

public static class ExampleJSInterop
{
    public static Task<string> DelayedText(string text)
    {
        return RegisteredFunction.InvokeAsync<string>("BlazorLib1.DelayedText", text);
    }
}

Now you can await the async JavaScript function like you would any normal C# async method:

var text = await ExampleJSInterop.DelayedText("See ya in 1 sec!");

Call .NET methods from JavaScript

Blazor 0.4.0 makes it easy to call sync and async .NET methods from JavaScript. For example, you might call back into .NET when a JavaScript callback is triggered. While calling into .NET from JavaScript was possible with earlier Blazor releases the pattern was low-level and difficult to use. Blazor 0.4.0 provides simpler pattern with the new Blazor.invokeDotNetMethod and Blazor.invokeDotNetMethodAsync functions.

To invoke a .NET method from JavaScript the target .NET method must meet the following criteria:

  • Static
  • Non-generic
  • No overloads
  • Concrete JSON serializable parameter types

For example, let's say you wanted to invoke the following .NET method when a timeout is triggered:

namespace Alerts
{
    public class Timeout
    {
        public static void TimeoutCallback()
        {
            Console.WriteLine('Timeout triggered!');
        }
    }
}

You can call this .NET method from JavaScript using Blazor.invokeDotNetMethod like this:

Blazor.invokeDotNetMethod({
    type: {
        assembly: 'MyTimeoutAssembly',
        name: 'Alerts.Timeout'
    },
    method: {
        name: 'TimeoutCallback'
    }
})

When invoking an async .NET method from JavaScript if the .NET method returns a task, then the JavaScript invokeDotNetMethodAsync function will return a Promise that completes with the task result (so JavaScript/TypeScript can also use await on it).

Summary

We hope you enjoy this latest preview of Blazor. Your feedback is especially important to us during this experimental phase for Blazor. If you run into issues or have questions while trying out Blazor please 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 also let us know what you think by taking our in-product survey. Just 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 script debugging in Visual Studio 15.7

$
0
0

We’re always looking for ways to make developing with Visual Studio faster.  One of the tasks developers do many times a day is launching debugging sessions.  We identified that script debugging added about 1.5s per F5, but only about 15.5% of people actively debugged script using Visual Studio.

Based on the above, in Visual Studio 15.7 we made the decision to turn off script debugging by default to improve the overall experience for most users. If you want to turn the capability back on, you can do it from Tools | Options | Debugging | and check “Enable JavaScript debugging for ASP.NET (Chrome, Edge, and IE):

We also added the following dialog when you attempt to set a breakpoint with script debugging disabled:

When script debugging is ON, Visual Studio automatically stops debugging when the browser window is closed. It will also close the browser window if you stop debugging in Visual Studio. We added the same capability to Visual Studio when script debugging is OFF under Tools | Options | Project and Solutions | Web Projects:

With this option enabled:

  • Visual Studio will open a new browser window when debugging starts
  • Visual Studio will stop debugging when the browser window is closed

The following matrix shows you all the available options and the expected behavior for each combination:

Enable JavaScript debugging for ASP.NET (Chrome, Edge and IE) Stop debugger when browser window is closed What happens when you start debugging What happens when you stop debugging What happens when you close the browser window
TRUE TRUE New browser window always pops up New browser window always goes away, with all open tabs Debugging stops
TRUE FALSE New browser window always pops up New browser window always goes away, with all open tabs Debugging stops
FALSE TRUE New browser window always pops up New browser window always goes away, with all open tabs Debugging stops
FALSE FALSE Opens new tab if browser window already exists Browser tab/window stays open Debugging continues

 

If you want Visual Studio to return to its default pre-15.7 behavior, all you have to do is enable script debugging in Tools | Options | Debugging | and check “Enable JavaScript debugging for ASP.NET (Chrome, Edge, and IE). If you notice any unexpected behavior with these options please use report a problem in Visual Studio to let us know. If you have any feedback or suggestions regarding this change please let us know on uservoice or simply post a reply to this post.


Workaround for Bower Version Deprecation

$
0
0

As of June 25, the version of Bower shipped with Visual Studio was deprecated, resulting in Bower operations failing when run in Visual Studio. If you use Bower, you will see an error something like:

EINVRES Request to https://bower.herokuapp.com/packages/bootstrap failed with 502

This will be fixed in Visual Studio 15.8. In the meantime, you can work around the issue by using a new version of Bower or by adding some configuration to each Bower project.

The Issue

Some time, ago Bower switched their primary registry feed but continued to support both. On June 25th, they turned off the older feed, which the copy in Visual Studio tries to use by default.

The Fix

There are two options to fix this issue:

  1. Update the configuration for each Bower project to explicitly use the new registry: https://reigstry.bower.io
  2. Manually install a newer version of Bower and configure Visual Studio to use it.

Workaround 1: Define the new registry entry in the project’s Bower config file (.bowerrc)

Add a .bowerrc file to the project (or modify the existing .bowerrc) with the following content:

{
  "registry": "https://registry.bower.io"
}

With the registry property defined in a .bowerrc file in the project root, Bower operations should run successfully on the older versions of Bower that shipped with Visual Studio 2015 and Visual Studio 2017.

Workaround 2: Configure Visual Studio to point to use a newer version of Bower

An alternative solution is to configure Visual Studio use to a newer version of Bower that you have installed as a global tool on your machine. (For instructions on how to install Bower, refer to the guidance on the Bower website.) If you have installed Bower via npm, then the path to the bower tools will be contained in the system $(PATH) variable. It might look something like this: C:\Users\[username]\AppData\Roaming\npm. If you make this path available to Visual Studio via the External Web Tools options page, then Visual Studio will be able to find and use the newer version.

To configure Visual Studio to use the globally installed Bower tools:

  1. Inside Visual Studio, open Tools->Options.
  2. Navigate to the External Web Tools options page (under Projects and Solutions->Web Package Management).
  3. Select the “$(PATH)” item in the Locations of external tools list box.
  4. Repeatedly press the up-arrow button in the top right corner of the Options dialog until the $(PATH) item is at the top of the list.
  5. Press OK to confirm the change.

Configure External Web Tools Path
Ordered this way, when Visual Studio is searching for Bower tools, it will search your system path first and should find and use the version you installed, rather than the older version that ships with Visual Studio in the $(VSINSTALLDIR)\Web\External directory.

Note: This change affects path resolution for all external tools. So, if you have Grunt, Gulp, npm or any other external tools on the system path, those tools will be used in preference to any other versions that shipped with VS. If you only want to change the path for Bower, leave the system path where it is and add a new entry at the top of the list that points to the instance of Bower installed locally. It might look something like this: C:\Users\[username]\AppData\Roaming\npm\node_modules\bower\bin

We trust this will solve any issues related to the recent outage of the older bower registry. If you have any questions or comments, please leave them below.

Happy coding!

Justin Clareburt, Senior Program Manager, Visual Studio

Justin Clareburt (justcla) Profile Pic Justin Clareburt is the Web Tools PM on the Visual Studio team. He has over 20 years of Software Engineering experience and brings to the team his expert knowledge of IDEs and a passion for creating the ultimate development experience.

Follow Justin on Twitter @justcla78

Razor Improvements – Feedback Wanted

$
0
0

In recent releases of Visual Studio 2017, there has been a great focus on improving the experience of working with Razor files (*.cshtml). The improvements were aimed at addressing the most pressing customer-facing issues and included changes from formatting and IntelliSense to general performance and reliability. Now that the fixes and enhancements have been publicly available for a few months, we hope you’ve been having a much-improved experience with the Razor editor.

Please let us know how we’re doing by taking a short, two-minute survey. Also, feel free to leave relevant feedback in the comments section below.

If you haven’t already downloaded the latest version, update your copy of Visual Studio 2017 through the Visual Studio Installer, or follow the links to download the installer from the Visual Studio website.

Razor editor in Visual Studio IDE

We know that despite our improvements, Razor editing isn’t perfect yet, so if you run into issues please file a report using the Visual Studio feedback tool. We review this feedback frequently and will continue to fix issues that are identified.

To launch the feedback tool, choose “Report a Problem…” under the Help->Send Feedback menu. When filing a report, please provide as much of your Razor file as you can share, with a description of what happened versus what you expected. (Sample code and screenshots are very helpful!)

Report a Problem menu item

Thanks for your interest in Web Development in Visual Studio.
Happy coding!

Justin Clareburt, Senior Program Manager, Visual Studio

Justin Clareburt (justcla) Profile Pic Justin Clareburt is the Web Tools PM on the Visual Studio team. He has over 20 years of Software Engineering experience and brings to the team his expert knowledge of IDEs and a passion for creating the ultimate development experience.

Follow Justin on Twitter @justcla78

Exploring Azure App Service – Azure Diagnostics

$
0
0

If you’ve followed our previous posts about using Azure App Service to host web apps in the cloud (1. Introduction to App Service, 2. Hosting web apps that use SQL) you’re already familiar with how easy it is to get an app running in the cloud; but what if the app doesn’t work correctly (it’s crashing, running too slow, etc.)?  In this post we’ll explore how to use Azure’s Application Insights to have always on diagnostics that will help you find and fix these types of issues.

Azure Application Insights provides seamless integration with Azure App Service for monitoring, triaging and diagnosing code-level issues. It can easily be enabled on an existing web app with a single button click. Profiler traces and exception snapshots will be available for identifying the lines of code that caused issues. Let’s take a closer look at this experience.

Enable Application Insights on an existing web app to investigate issues

We recommend you follow along using your own application, but if you don’t have one readily available we will be using the Contoso University sample. The instructions on how to deploy it to App Service are in the readme file.

If you are following along with Contoso University, you will notice the Instructors page throws errors. In addition, the Courses tab loads a bit slower than others.

Let’s turn on Application Insights to investigate. After the app is deployed to App service, Application Insights can be enabled from the App Service portal by clicking the button on the overview blade:

Fill out the Application Insights enablement blade the following way:

  • Create a new resource, with an appropriate name.
  • Leave all default options for Code-level diagnostics on. The added section Code level diagnostics is on by default to enable Profiler and Snapshot Debugger for diagnosing slow app performance and runtime exceptions.
  • Click the ‘OK’ button. Once prompted if to restart the web app, click ‘Continue’ to proceed.

Once Application Insights is enabled, you will be able to see its connection status. You can now navigate to the Application Insights overview blade by clicking on the link next to the green check mark:

Generate traffic for your web app in order to reproduce issues

Let’s generate some traffic to reproduce our two issues: a) Courses page loading slowly, b) Instructors page throwing errors. You are going to use performance test with Azure portal to make requests to the following URLs:

  • http://<your_webapp_name>.azurewebsites.net/Courses
  • http://<your_webapp_name>.azurewebsites.net/Instructors

You are going to be creating two different performance tests, once for each URL. For the Courses page you are going to simulate 250 users over a duration of 5 minutes, since you are experiencing a performance issue. For the Instructors page you can simulate 10 users over 1 minutes since we’d generally expect less instructors than users on the site at any given time.

Profile your app during performance tests to identify performance issues

A performance test will generate traffic, but if you want to understand how you app performs you have to analyze its performance while the test is running using a profiler. Let’s do exactly that, using the Performance | Configure Profiler blade while one of our performance tests is running:

Later on we will walkthrough how to use the profiler to identify the exact lines of code responsible for the slow-down. For now, let’s focus on simply profiling . After clicking on “Profile now”, wait until the performance test finishes and the profiler has completed its analysis. After a new entry in the section “Recent profiling sessions” appears, navigate back to the Overview blade.

Diagnose runtime exceptions

If your web app has any failed requests, you need to root cause and solve the issues to ensure your app works reliably. After running your performance test on the Instructors page you have some example failed requests to take a look at:

Let’s go to Failures blade to investigate what failed.

On the Failures blade, the top failed operation is ‘GET Instructors/Index’ and the top exception is ‘InvalidOperationException’. Click on the ‘COUNT’ column of the exception count to open list of sample exceptions. Click on the suggested exception to open the End-to-End Transaction blade.

In the End-to-End Transaction blade, you can see ‘System.InvalidOperationException’ exceptions thrown from GET Instructors/Index operation. Select the exception row and click on ‘Open debug snapshot’.

If it’s the first time you use Snapshot Debugger, you will prompt to request RBAC access to snapshots to safeguard the potentially sensitive data shown in local variables:

Once you get access, you will see a snapshot view like the following:

From the local variables and call stack, you can see the exception is thrown at InstructorsController.cs line 56 with message ‘Nullable object must have a value’. This provides sufficient information to proceed with debugging the app’s source code.

To get a better experience, download the snapshot and debug it using Visual Studio Enterprise. You will be able to interactively see which line of code caused the exception:

Looking at the code, the exception was thrown because ‘id’ is null and you are missing the appropriate check. When your app is running in the cloud, resources are dynamically provisioned and destroyed and so may not always get the chance to access the state of a failed component before it is reset. The Snapshot Debugger is a powerful tool that can maintain the failed state of the component even after the component’s state has been reset, by capturing local variables and call stack at the time the exception is thrown.

Diagnose bad performance from your web app

The server response time chart on the overview blade provides quick information on how performant your web app is over time. In the Contoso example, we see some spikes on the chart indicating there is a short period of time where users experienced slow responses for the requests they made.

To investigate further, navigate to the Performance blade in App Insights portal:

Zoom into the time range 6pm-10pm in the ‘Operation times: zoom into range’ chart to see spikes on the Request count.

Sort the Operations table by duration and request count to figure out where your web app spent the most time. In our example GET Courses/Index operation has the longest average duration. Let’s click on it to investigate why this operation takes so long.

The right side of the blade provides insights based on the Course/Index operation.

From the chart you can see although most operations only took around 400ms, the worst ones took up to 35 seconds. This means some users are getting really bad experience when hitting this URL and you should address it. Let’s look at Profiler traces to troubleshoot why GET Courses/Index was being so slow.

You should see profiler traces similar to the following:

The code path that’s taking the most time is prefixed with the flame icon. In this particular request, most time was spent on reading the list of courses from the database. Browsing to the code CourseController.cs we can see that when loading the list of courses the AsNoTracking() optimization option is not used. By default, Entity Framework will turn on tracking which caches the results to compare with what’s modified. This could add an approx. ~30% overhead to your app’s performance. For simple read operation like this one, we can optimize the query performance by using the AsNoTracking() option.

Conclusion

We hope that you find it easy to use Application Insights to diagnose performance and errors in your web apps. We believe Azure App Service is a great place to get started hosting and maintaining your web apps. You don’t have to enable App Insights upfront; the option is always there to be turned on when and as needed without re-deployment.

If you have any questions or issues, let us know by leaving comments below.

Catherine Wang Program Manager, VS and .NET

Catherine is on Azure developer experience team and is responsible for Azure diagnostics, security and storage tools.

Blazor 0.5.0 experimental release now available

$
0
0

Blazor 0.5.0 is now available! This release explores scenarios where Blazor is run in a separate process from the rendering process. Specifically, Blazor 0.5.0 enables the option to run Blazor on the server and then handle all UI interactions over a SignalR connection. This release also adds some very early support for debugging your Blazor .NET code in the browser!

New features in this release:

  • Server-side Blazor
  • Startup model aligned with ASP.NET Core
  • JavaScript interop improvements
    • Removed requirement to preregister JavaScript methods
    • Invoke .NET instance method from JavaScript
    • Pass .NET objects to JavaScript by reference
  • Add Blazor to any HTML file using a normal script tag
  • Render raw HTML
  • New component parameter snippet
  • Early support for in-browser debugging

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

Get Blazor 0.5.0

To get setup with Blazor 0.5.0:

  1. Install the .NET Core 2.1 SDK (2.1.300 or later).
  2. Install Visual Studio 2017 (15.7 or later) with the ASP.NET and web development workload selected.
  3. Install the latest Blazor Language Services extension from the Visual Studio Marketplace.

To install 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.5.0

To upgrade an existing Blazor project from 0.4.0 to 0.5.0:

  • Install all of the required bits listed above.
  • Update your Blazor package and .NET CLI tool references to 0.5.0. Your upgraded Blazor project file should look like this:

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
    <PropertyGroup>
        <TargetFramework>netstandard2.1</TargetFramework>
        <RunCommand>dotnet</RunCommand>
        <RunArguments>blazor serve</RunArguments>
        <LangVersion>7.3</LangVersion>
    </PropertyGroup>
    
    <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.5.0" />
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.5.0" />
        <DotNetCliToolReference Include="Microsoft.AspNetCore.Blazor.Cli" Version="0.5.0" />
    </ItemGroup>
    
    </Project>
    
  • Update index.html to replace the blazor-boot script tag with a normal script tag that references _framework/blazor.webassembly.js..

    index.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width">
        <title>BlazorApp1</title>
        <base href="/" />
        <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
        <link href="css/site.css" rel="stylesheet" />
    </head>
    <body>
        <app>Loading...</app>  
        <script src="_framework/blazor.webassembly.js"></script>
    </body>
    </html>
    
  • Add a Startup class to your project and update Program.cs to setup the Blazor host.

    Program.cs

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
            BlazorWebAssemblyHost.CreateDefaultBuilder()
                .UseBlazorStartup<Startup>();
    }
    

    Startup.cs

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
        }
    
        public void Configure(IBlazorApplicationBuilder app)
        {
            app.AddComponent<App>("app");
        }
    }
    
  • Update to the new JavaScript interop model. The changes to the JavaScript interop model are covered in the "JavaScript interop changes" section below.

What is server-side Blazor?

Blazor is principally a client-side web framework intended to run in a browser where the component logic and DOM interactions all happen in the same process.

Blazor client-side

However, Blazor was built to be flexible enough to handle scenarios where the Blazor app runs apart from the rendering process. For example, you might run Blazor in a Web Worker thread so that it runs separately from the UI thread. Events would get pushed from the UI thread to the Blazor worker thread, and Blazor would push UI updates to the UI thread as needed. This scenario isn't supported yet, but it's something Blazor was designed to handle.

Blazor web worker

Another potential use case for running Blazor in a separate process is writing desktop applications with Electron. The Blazor component logic could run in a normal .NET Core process, while the UI updates are handled in the Electron rendering process.

Blazor Electron

We have a working prototype that you can try out of using Blazor with Electron in this way.

Blazor 0.5.0 takes the out-of-process model for Blazor and streeeetches it over a network connection so that you can run Blazor on the server. With Blazor 0.5.0 you can run your Blazor components server-side on .NET Core while UI updates, event handling, and JavaScript interop calls are handled over a SignalR connection.

Blazor server-side

There are a number of benefits to running Blazor on the server in this way:

  • You can still write your entire app with .NET and C# using the Blazor component model.
  • Your app still has a rich interactive feel and avoids unnecessary page refreshes.
  • Your app download size is significantly smaller and the initial app load time is much faster.
  • Your Blazor component logic can take full advantage of server capabilities including using any .NET Core compatible APIs.
  • Because you're running on .NET Core on the server existing .NET tooling, like debugging, just works.
  • Works with thin clients (ex browsers that don't support WebAssembly, resource constrained devices, etc.).

Of course there are some downsides too:

  • Latency: every user interaction now involves a network hop.
  • No offline support: if the client connection goes down the app stops working.
  • Scalability: the server must manage multiple client connections and handle client state.

While our primary goal for Blazor remains to provide a rich client-side web development experience, enough developers expressed interest in the server-side model that we decided to experiment with it. And because server-side Blazor uses the exact same component model as running Blazor on the client, it is well aligned with our client-side efforts.

Get started with server-side Blazor

To create your first server-side Blazor app use the new server-side Blazor project template.

dotnet new blazorserverside -o BlazorApp1

Build and run the app from the BlazorApp1.Server directory to see it in action:

cd BlazorApp1.Server
dotnet run

You can also create a server-side Blazor app from Visual Studio.

Blazor server-side template

When you run the Blazor server-side app it looks like a normal Blazor app, but the download size is significantly smaller (under 100KB), because there is no need to download a .NET runtime, the app assembly, or any of its dependencies.

Blazor server-side running app

Blazor server-side download size

You're also free to run the app under the debugger (F5) as all the .NET logic is running on .NET Core on the server.

The template creates a solution with two projects: an ASP.NET Core host project, and a project for your server-side Blazor app. In a future release we hope to merge these two projects into one, but for now the separation is necessary due to the differences in the Blazor compilation model.

The server-side Blazor app contains all of your component logic, but instead of running client-side in the browser the logic is run server-side in the ASP.NET Core host application. The Blazor app uses a different bootstrapping script (blazor.server.js instead of blazor.webassembly.js), which establishes a SignalR connection with the server and handles applying UI updates and forwarding events. Otherwise the Blazor programming model is the same.

The ASP.NET Core app hosts the Blazor app and sets up the SignalR endpoint. Because the Blazor app runs on the server, the event handling logic can directly access server resources and services. For example, the FetchData page no longer needs to issue an HTTP request to retrieve the weather forecast data, but can instead use a service configured on the server:

protected override async Task OnParametersSetAsync()
{
    forecasts = await ForecastService.GetForecastAsync(StartDate);
}

The WeatherForecastService in the template generates the forecast data in memory, but it could just as easily pull the data from a database using EF Core, or use other server resources.

Startup model

All Blazor projects in 0.5.0 now use a new startup model that is similar to the startup model in ASP.NET Core. Each Blazor project has a Startup class with a ConfigureServices method for configuring the services for your Blazor app, and a Configure method for configuring the root components of the application.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
    }

    public void Configure(IBlazorApplicationBuilder app)
    {
        app.AddComponent<App>("app");
    }
}

The app entry point in Program.cs creates a Blazor host that is configured to use the Startup class.

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

    public static IWebAssemblyHostBuilder CreateHostBuilder(string[] args) =>
        BlazorWebAssemblyHost.CreateDefaultBuilder()
            .UseBlazorStartup<Startup>();
}

In server-side Blazor apps the entry point comes from the host ASP.NET Core app, which references the Blazor Startup class to both add the server-side Blazor services and to add the Blazor app to the request handling pipeline:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddServerSideBlazor<App.Startup>();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
        app.UseServerSideBlazor<App.Startup>();
    }
}

While the server-side Blazor project may also have a Program class, it is not used when running on the server. However it would be used if you switched to client-side (WebAssembly) execution just by changing the <script> tag in index.html to load blazor.webassembly.js instead of blazor.server.js.

The Blazor app and the ASP.NET Core app share the same service provider. Services added in either ConfigureServices methods are visible to both apps. Scoped services are scoped to the client connection.

State management

When running Blazor on the server the UI state is all managed server-side. The initial state is established with the client connects to the server and is maintained in memory as the user interacts with the app. If the client connection is lost then the server-side app state will be lost, unless it is otherwise persisted and restored by the app. For example, you could maintain your app state in an AppState class that you serialize into session state periodically and then initialize the app state from session state when it is available. While this process is currently completely manual in the future we hope to make server-side state management easier and more integrated.

JavaScript interop changes

You can use JavaScript interop libraries when using server-side Blazor. The Blazor runtime handles sending the JavaScript calls to the browser and then sending the results back to the server. To accommodate out-of-process usage of JavaScript interop the JavaScript interop model was significantly revised and expanded upon in this release.

Calling JavaScript from .NET

To call into JavaScript from .NET use the new IJSRuntime abstraction, which is accessible from JSRuntime.Current. The InvokeAsync<T> method on IJSRuntime takes an identifier for the JavaScript function you wish to invoke along with any number of JSON serializable arguments. The function identifier is relative to the global scope (window). For example, if you wish to call window.someScope.someFunction then the identifier would be someScope.someFunction. There is no longer any need to register the function before it can be called. The return type T must also be JSON serializable.

exampleJsInterop.js

window.exampleJsFunctions = {
  showPrompt: function (message) {
    return prompt(message, 'Type anything here');
  }
};

ExampleJsInterop.cs

using Microsoft.JSInterop;

public class ExampleJsInterop
{
    public static Task<string> Prompt(string message)
    {
        // Implemented in exampleJsInterop.js
        return JSRuntime.Current.InvokeAsync<string>(
            "exampleJsFunctions.showPrompt",
            message);
    }
}

The IJSRuntime abstraction is async to allow for out-of-process scenarios. However, if you are running in-process and want to invoke a JavaScript function synchronously you can downcast to IJSInProcessRuntime and call Invoke<T> instead. We recommend that most JavaScript interop libraries should use the async APIs to ensure the libraries can be used in all Blazor scenarios, client-side or server-side.

Calling .NET from JavaScript

To invoke a static .NET method from JavaScript use the DotNet.invokeMethod or DotNet.invokeMethodAsync functions passing in the identifier of the static method you wish to call, the name of the assembly containing the function, and any arguments. Again, the async version is required to support out-of-process scenarios. To be invokable from JavaScript, the .NET method must be public, static, and attributed with [JSInvokable]. By default, the method identifier is the method name, but you can specify a different identifier using the JSInvokableAttribute constructor. Calling open generic methods is not currently supported.

JavaScriptInteroperable.cs

public class JavaScriptInvokable
{
    [JSInvokable]
    public static Task<int[]> ReturnArrayAsync()
    {
        return Task.FromResult(new int[] { 1, 2, 3 });
    }
}

dotnetInterop.js

DotNet.invokeMethodAsync(assemblyName, 'ReturnArrayAsync').then(data => ...)

New in Blazor 0.5.0, you can also call .NET instance methods from JavaScript. To invoke a .NET instance method from JavaScript you first pass the .NET instance to JavaScript by wrapping it in a DotNetObjectRef instance. The .NET instance will then be passed by reference to JavaScript and you can invoke .NET instance methods on the instance using the invokeMethod or invokeMethodAsync functions. The .NET instance can also be passed as an argument when invoking other .NET methods from JavaScript.

ExampleJsInterop.cs

public class ExampleJsInterop
{
    public static Task SayHello(string name)
    {
        return JSRuntime.Current.InvokeAsync<object>(
            "exampleJsFunctions.sayHello", 
            new DotNetObjectRef(new HelloHelper(name)));
    }
}

exampleJsInterop.js

window.exampleJsFunctions = {
  sayHello: function (dotnetHelper) {
    return dotnetHelper.invokeMethodAsync('SayHello')
      .then(r => console.log(r));
  }
};

HelloHelper.cs

public class HelloHelper
{
    public HelloHelper(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    [JSInvokable]
    public string SayHello() => $"Hello, {Name}!";
}

Output

Hello, Blazor!

Add Blazor to any HTML file

In previous Blazor releases the project build modified index.html to replace the blazor-boot script tag with a real script tag that handled downloading the starting up the runtime. This setup made it difficult to use Blazor in arbitrary HTML files.

In Blazor 0.5.0 this mechanism has been replaced. For client-side projects add a script tag that references the _framework/blazor.webassembly.js script (which is generated as part of the build). For server-side projects you reference _framework/blazor.server.js. You can add this script to any HTML file, including server generated content.

For example, instead of using the static index.html file from the Blazor client project you could add a Razor Page to your ASP.NET Core host project and then add the Blazor script tag there along with any server-side rendering logic.

Render raw HTML

Blazor normally renders strings using DOM text nodes, which means that any markup they may contain will be ignored and treated as literal text. This new feature lets you render special MarkupString values that will be parsed as HTML or SVG and then inserted into the DOM.

WARNING: Rendering raw HTML constructed from any untrusted source is a major security risk!

Use the MarkupString type to add blocks of static HTML content.

@((MarkupString)myMarkup)

@functions {
    string myMarkup = "<p class='markup'>This is a <em>markup string</em>.</p>";
}

Component parameter snippet

Thanks to a community contribution from Benjamin Vertonghen (vertonghenb) we now have a Visual Studio snippet for adding component parameters. Just type para and then hit Tab twice to add a parameter to your component.

Debugging

Blazor 0.5.0 introduces some very basic debugging support in Chrome for client-side Blazor apps running on WebAssembly. While this initial debugging support is very limited and unpolished it does show the basic debugging infrastructure coming together.

To debug your client-side Blazor app in Chrome:

  • Build a Blazor app in Debug configuration (the default for non-published apps)
  • Run the Blazor app in Chrome
  • With the keyboard focus on the app (not in the dev tools, which you should probably close as it's less confusing that way), press the following Blazor specific hotkey:
    • Shift+Alt+D on Windows/Linux
    • Shift+Cmd+D on macOS

You need to run Chrome with remote debugging enabled to debug your Blazor app. If you don't, you will get an error page with instructions for running Chrome with the debugging port open so that the Blazor debugging proxy can connect to it. You will need to close all Chrome instances and then restart Chrome as instructed.

Blazor debugging error page

Once you have Chrome running with remote debugging enabled, hitting the debugging hotkey will open a new debugger tab. After a brief moment the Sources tab will show a list of the .NET assemblies in the app. You can expand each assembly and find the .cs/.cshtml source files you want to debug. You can then set breakpoints, switch back to your app's tab, and cause the breakpoints to be hit. You can then single-step (F10) or resume (F8).

Blazor debugging

How does this work? Blazor provides a debugging proxy that implements the Chrome DevTools Protocol and augments the protocol with .NET specific information. When you hit the debugging hotkey, Blazor points the Chrome DevTools at the proxy, which in turn connects to the browser window you are trying to debug (hence the need for enabling remote debugging).

You might be wondering why we don't just use browser source maps. Source maps allow the browser to map compiled files back to their original source files. However, Blazor does not map C# directly to JS/WASM (at least not yet). Instead, Blazor does IL interpretation within the browser, so source maps are not relevant.

NOTE: The debugger capabilities are very limited. You can currently only:

  • Single-step through the current method (F10) or resume (F8)
  • In the Locals display, observe the values of any local variables of type int/string/bool
  • See the call stack, including call chains that go from JavaScript into .NET and vice-versa

That's it! You cannot step into child methods (i.e., F11), observe the values of any locals that aren't an int/string/bool, observe the values of any class properties or fields, hover over variables to see their values, evaluate expressions in the console, step across async calls, or do basically anything else.

Our friends on the Mono team have done some great work tackling some of the hardest technical problems to enable source viewing, breakpoints, and stepping, but please be patient as completing the long tail of debugger features remains a significant ongoing task.

Community

The Blazor community has produced a number of great Blazor extensions, libraries, sample apps, articles, and videos.
You can find out about these community projects on the Blazor Community page. Recent additions include a Blazor SignalR client, Redux integration, and various community authored samples (Toss, Clock, Chat). If you have a Blazor related project that you'd like to share on the community page let us know by sending us a pull request to the Blazor.Docs repo.

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 please 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 also 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!

Improvements in Visual Studio 2017 15.8 for web developers

$
0
0

This week we released Visual Studio 2017 version 15.8. Our 15.8 update brings the following improvements for web developers:

  • Custom docker image tags during Publish
  • Zip push deployment for Azure Functions
  • Managing Azure Functions application settings
  • Enabling Application Insights as part of publishing to Azure App Service
  • Managing user secrets in ASP.NET Framework projects (targeting .NET 4.7.1 or higher) work projects
  • Optimizing build performance for solutions containing ASP.NET Frame
  • Author and source information for ASP.NET Core templates

Custom docker image tags during Publish

You can now customize the “Image tag” for Docker containers when publishing them to a container registry. The value can either be automatically generated by Visual Studio every time you publish (the previous behavior), or it be manually changed if you need a consistent tag (e.g. “latest”):

Screenshot of new property called "Image Tag" in Publish

Zip push deployment & run from zip for Azure Functions

Visual Studio now provides the option to deploy and run Azure Functions projects as zip files:

Screenshot of publish and run from zip option in Publish

Run-From-Zip is a runtime feature that allows ‘mounting’ a zip file and running directly from it. Your App runs directly over the ‘mounted’ zip file, which completely takes over your wwwrootfolder (which becomes read-only).  Using run from Zip offers the following benefits:

  • Atomicity: when your application is deployed as as single unit, and updated as a single unit meaning publishing an update will never leave your app in a partially updated state
  • Faster deployment of large applications
  • Improved cold start performance

Managing Azure Functions application settings

After you publish your Azure Functions project using Visual Studio, you can manage the application settings from the publish summary:

Screenshot of manage application settings in the publish summary

 

That’s a feature we added back in update 15.5 of Visual Studio 2017. Since then you gave us feedback that a very common task is to copy the local value of a setting to the remove environment. So now in update 15.8 of Visual Studio 2017 that’s as easy as clicking a button:

Screenshot of the button that copies the local value of a setting to remote

Enabling Application Insights as part of publishing to Azure App Service

When publishing to Azure App Service, Visual Studio asks you to either create a new App Service or re-use an existing one. If you choose to create a new App Service to host your application, Visual Studio now offers you the ability to also provision and configure Application Insights:

Screenshot of new drop-down related to Application Insights when creating a new App Service

All you need to do is pick the region you would like Application Insights to be provisioned in and Visual Studio will make sure it’s configured to pick up telemetry events and metrics from the new App Service. If you wish to add custom events and metrics follow this guide. Of course, you can always set the field to “None” and Visual Studio will not provision nor configure Application Insights on your behalf.

Managing user secrets in ASP.NET Framework projects (targeting .NET 4.7.1 or higher)

A feature that ASP.NET Framework projects were missing compared to ASP.NET Core was support for storing application secrets (e.g. connection strings, API keys, etc.) in a file outside of source control unique to each user. Now, with .NET Framework 4.7.1 and Visual Studio 15.8 it’s as simple as right clicking on the project in Solution Explorer and selecting “Manage User Secrets”:

Screenshot of the new "Manage user secrets" menu item when right clicking in Solution Explorer

Visual Studio will take care of the rest including downloading the necessary NuGet packages, updating the web.config file, creating the secrets file on disk and finally opening it for you to edit:

Screenshot of an example user secrets file

Note: Only available for projects targeting .NET Framework 4.7.1 or higher, if you can’t see the menu item make sure you have the 4.7.1 targeting pack installed and that the project is actually targeting 4.7.1, you can change it from project properties:

Screenshot of the run time drop-down available in project properties

Optimizing build performance for solutions containing ASP.NET Framework projects

We added a new menu item under Build | ASP.NET Compilation | Optimize Build Performance for Solution:

Screenshot of new menu item Build | ASP.NET Compilation | Optimize Build Performance for Solution

ASP.NET compiles its views at runtime, which means your ASP.NET project carries with it a copy of the compiler. However, on a developer machine when the copy of the compiler doesn’t match Visual Studio’s copy, your build performance is impacted on the order of 1-3 seconds per incremental build. This feature will update your project’s copy of the compiler to match Visual Studio’s which should speed up your incremental builds.

This is applicable to ASP.NET Framework projects only, it does not apply to ASP.NET Core.

Author and source information for ASP.NET Core templates

The dialog for new ASP.NET Core projects now shows you the author and source for the selected template:

Screenshot of author and source information available in the New Project Dialog

  • If the template is coming from a .NET Core SDK installed on the machine, the dialog will now display the version of the SDK as the source
  • If the template is coming from a VSIX (i.e. Visual Studio extension) installed on the machine, the dialog will now display the name of the VSIX as the source

Conclusion

If you’re interested in the many other great things that Visual Studio 2017 15.8 brings, check out our Visual Studio 15.8 post on the Visual Studio blog.

We hope that you’ll give 15.8 a try and let us know how it works for you. If you run into any issues please report them using Visual Studio, or let us know what you think below, or via Twitter.

LibMan CLI Released

$
0
0

The Command Line Interface (CLI) is now available for Microsoft Library Manager (LibMan) and can be downloaded via NuGet. Look for Microsoft.Web.LibraryManager.CLI
The LibMan CLI is cross-platform, so you’ll be able to use it anywhere that .NET Core is supported (Windows, Mac, Linux).

Install the LibMan CLI

To install LibMan, type:

> dotnet tool install --global Microsoft.Web.LibraryManager.Cli

Once the LibMan CLI is installed, you can start using LibMan from the root of your web project (or any folder).

Using LibMan from the Command Line

When using LibMan CLI, begin commands with “libman” then follow with the action you wish to invoke.
For example, to install all files from the latest version of jquery, type:

> libman install jquery

Follow the prompts to select the provider and destination. Type the values you want, or press [Enter] to accept the defaults.

The install operation creates a libman.json file in the current directory if one does not already exist, then adds the new library configuration. It then downloads the files and places them in the destination folder. See the example below.

LibMan CLI example

To learn more about the LibMan CLI, refer to the LibMan CLI documentation on the Library Manager Wiki.

Happy coding!

Justin Clareburt, Senior Program Manager, Visual Studio

Justin Clareburt (justcla) Profile Pic Justin Clareburt is the Web Tools PM on the Visual Studio team. He has over 20 years of Software Engineering experience and brings to the team his expert knowledge of IDEs and a passion for creating the ultimate development experience.

Follow Justin on Twitter @justcla78

ASP.NET Core 2.2.0-preview1 now available

$
0
0

Today we’re very happy to announce that the first preview of the next minor release of ASP.NET Core and .NET Core is now available for you to try out. We’ve been working hard on this release over the past months, along with many folks from the community, and it’s now ready for a wider audience to try it out and provide the feedback that will continue to shape the release.

How do I get it?

You can download the new .NET Core SDK for 2.2.0-preview1 (which includes ASP.NET 2.2.0-preview1) from https://www.microsoft.com/net/download/dotnet-core/2.2.

Visual Studio requirements

Customers using Visual Studio should also install and use the Preview channel of Visual Studio 2017 (15.9 Preview 1 at the time of writing) in addition to the SDK when working with .NET Core 2.2 and ASP.NET Core 2.2 projects.

Azure App Service Requirements

If you are hosting your application on Azure App Service, you should follow these instructions to install the site extension for hosting your 2.2.0-preview1 applications.

Impact to machines

Please note that is a preview release and there are likely to be known issues and as-yet-to-be discovered bugs. While the .NET Core SDK and runtime installs are side-by-side, your default SDK will become the latest one. If you run into issues working on existing projects using earlier versions of .NET Core after installing the preview SDK, you can force specific projects to use an earlier installed version of the SDK using a global.json file as documented here. Please log an issue if you run into such cases as SDK releases are intended to be backwards compatible.

What’s new in 2.2

We’re publishing a series of posts here that go over some of the new feature areas in detail. We’ll update the post with links to these posts as they go live over the coming days:

  • API Controller Conventions
  • Endpoint Routing
  • Health Checks
  • HTTP/2 in Kestrel
  • Improvements to IIS hosting
  • SignalR Java client

In addition to these features area, we’ve also:

  • Updated our web templates to Bootstrap 4 and Angular 6

You can see these new features in action in our most recent ASP.NET Community Standup.

For a detailed list of all features, bug fixes, and known issues refer to our release notes.

Migrating an ASP.NET Core 2.1 project to 2.2

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

Giving Feedback

The main purpose of providing previews is to solicit feedback so we can refine and improve the product in time for the final release. Please help provide us feedback by logging issues in the appropriate repository at https://github.com/aspnet or https://github.com/dotnet. We look forward to receiving your feedback!


ASP.NET Core 2.2.0-preview1: HTTP/2 in Kestrel

$
0
0

As part of the 2.2.0-preview1 release, we’ve added support for HTTP/2 in Kestrel.

What is HTTP/2?

HTTP/2 is a major revision of the HTTP protocol. Some of the notable features of HTTP/2 are support for header compression and fully multiplexed streams over the same connection. While HTTP/2 preserves HTTP’s semantics (HTTP headers, methods, etc) it is a breaking change from HTTP/1.x on how this data is framed and sent over the wire.

As a consequence of this change in framing, servers and clients need to negotiate the protocol version used. While it is possible to have prior knowledge between the server and the client on the protocol, all major browsers support ALPN as the only way to establish a HTTP/2 connection.

Application-Layer Protocol Negotiation (ALPN)

Application-Layer Protocol Negotiation (ALPN) is a TLS extension that allows the server and client negotiate the protocol version used as part of their TLS handshake.

How do I use it?

In 2.2.0-preview1 of Kestrel, HTTP/2 is enabled by default (we may change this in subsequent releases). Since most browsers already support HTTP/2 any request you make will already happen over HTTP/2 provided certain conditions are met:

  • The request is made over an HTTPS connection.
  • The native crypto library used by .NET Core on your platform supports ALPN

In the event that either of these conditions is unmet, the server and client will transparently fallback to using HTTP1.1.

The default binding in Kestrel advertises support for both HTTP/1.x and HTTP/2 via ALPN. You can always configure additional bindings via KestrelServerOptions. For example,

WebHost.CreateDefaultBuilder()
    .ConfigureKestrel(options =>
    {
        options.Listen(IPAddress.Any, 8080, listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
            listenOptions.UseHttps("testcert.pfx", "testPassword")
        }); 
    })
    .UseStartup<Startup>();

If you do not enable HTTPS/TLS then Kestrel will be unable to use ALPN to negotiate HTTP/2 connections.

It is possible to establish a HTTP/2 connection in Kestrel using prior knowledge on all platforms (since we don’t rely on ALPN). However, no major browser supports prior knowledge HTTP/2 connections. This approach does not allow for graceful fallback to HTTP/1.x.

WebHost.CreateDefaultBuilder()
    .ConfigureKestrel(options =>
    {
        options.Listen(IPAddress.Any, 8080, listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http2;
        }); 
    })
    .UseStartup<Startup>();

Caveats

As mentioned earlier, it is only possible to negotiate an HTTP/2 connection if the native crypto library on your server supports ALPN.

ALPN is supported on:

  • .NET Core on Windows 8.1/Windows Server 2012 R2 or higher
  • .NET Core on Linux with OpenSSL 1.0.2 or higher (e.g., Ubuntu 16.04)

ALPN is not supported on:

  • .NET Framework 4.x on Windows
  • .NET Core on Linux with OpenSSL older than 1.0.2
  • .NET Core on OS X

What’s missing in Kestrel’s HTTP/2?

  • Server Push: An HTTP/2-compliant server is allowed to send resources to a client before they have been requested by the client. This is a feature we’re currently evaluating, but haven’t planned to add support for yet.
  • Stream Prioritization: The HTTP/2 standard allows for clients to send a hint to the server to express preference for the priority of processing streams. Kestrel currently does not act upon hints sent by the client.
  • HTTP Trailers: Trailers are HTTP headers that can be sent after the message body in both HTTP requests and responses.

What’s coming next?

In ASP.NET Core 2.2,

  • Hardening work on HTTP/2 in Kestrel. As HTTP/2 allows multiplexed streams over the same TCP connection, we need to introduce HTTP/2 specific limits as part of the hardening.
  • Performance work on HTTP/2.

Feedback

The best place to provide feedback is by opening issues at https://github.com/aspnet/KestrelHttpServer/issues.

ASP.NET Core 2.2.0-preview1: Healthchecks

$
0
0

What is it?

We’re adding a health checks service and middleware in 2.2.0 to make it easy to use ASP.NET Core in environments that require health checks – such as Kubernetes. The new features are set of libraries defining an IHealthCheck abstraction and service, as well as a middleware for use in ASP.NET Core.

Health checks are used by a container orchestrator or load balancer to quickly determine if a system is responding to requests normally. A container orchestrator might respond to a failing health check by halting a rolling deployment, or restarting a container. A load balancer might respond to a health check by routing traffic away from the failing instance of the service.

Typically health checks are exposed by an application as a simple HTTP endpoint used by monitoring systems. Creating a dedicated health endpoint allows you to specialize the behavior of that endpoint for the needs of monitoring systems.

How to use it?

Like many ASP.NET Core features, health checks comes with a set of services and a middleware.

public void ConfigureServices(IServiceCollection services)
{
...

    services.AddHealthChecks(); // Registers health checks services
}

public void Configure(IApplicationBuilder app)
{
...

    app.UseHealthChecks("/healthz");

...
}

This basic configuration will register the health checks services and and will create a middleware that responds to the URL path “/healthz” with a health response. By default no health checks are registered, so the app is always considered healthy if it is capable of responding to HTTP.

You can find a few more samples in the repo:

Understanding liveness and readiness probes

To understand how to make the most out out health checks, it’s important to understand the difference between a liveness probe and a readiness probe.

A failed liveness probe says: The application has crashed. You should shut it down and restart.

A failed readiness probe says: The application is OK but not yet ready to serve traffic.

The set of health checks you want for your application will depend on both what resources your application uses and what kind of monitoring systems you interface with. An application can use multiple health checks middleware to handle requests from different systems.

What health checks should I add?

For many applications the most basic configuration will be sufficient. For instance, if you are using a liveness probe-based system like Docker’s built in HEALTHCHECK directive, then this might be all you want.

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...

    services.AddHealthChecks(); // Registers health checks services
}

public void Configure(IApplicationBuilder app)
{
...

    app.UseHealthChecks("/healthz");

...
}


# Dockerfile
...

HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit

If your application is running in Kubernetes, you may want to support a readiness probe that health checks your database. This will allow the orchestrator to know when a newly-created pod should start receiving traffic.

public void ConfigureServices(IServiceCollection services)
{
...
    services
        .AddHealthChecks()
        .AddCheck(new SqlConnectionHealthCheck("MyDatabase", Configuration["ConnectionStrings:DefaultConnection"]));
...
}

public void Configure(IApplicationBuilder app)
{
    app.UseHealthChecks("/healthz");
}

...
spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /healthz
        port: 80
        # length of time to wait for a pod to initialize
        # after pod startup, before applying health checking
        initialDelaySeconds: 30
        timeoutSeconds: 1
    ports:
      - containerPort: 80

Customization

The health checks middleware supports customization along a few axes. All of these features can be accessed by passing in an instance of HealthCheckOptions.

  • Filter the set of health checks run
  • Customize the HTTP response
  • Customize the mappings of health status -> HTTP status codes

What is coming next?

In a future preview we plan to add official support for health checks based on an ADO.NET DbConnection or Entity Framework Core DbContext.

We expect that the way that IHealthCheck instances interact with Dependency Injection will be improved. The current implementation doesn’t provide good support for interacting with services of varying lifetimes.

We’re working with the authors of Polly to try and integrate health checks for Polly’s circuit breakers.

We plan to also provide guidance and examples for using the health check service with push-based health systems.

How can you help?

There are a few areas where you can provide useful feedback during this preview. We’re interested in any thoughts you have of course, these are a few specific things we’d like opinions on.

Is the IHealthCheck interface general and useful enough to be used broadly?

  • Including other health check systems
  • Including health checks written by other libraries and frameworks
  • Including health checks written by application authors

The best place to provide feedback is by logging issues on https://github.com/aspnet/Diagnostics

Caveats and notes

The health check middleware doesn’t disable caching for responses to the health endpoint. We plan to add this in the future, but it didn’t make it into the preview build.

ASP.NET Core 2.20-preview1: Open API Analyzers & Conventions

$
0
0

What is it?

Open API (alternatively known as Swagger) is a language-agnostic specification for describing REST APIs. The Open API ecosystem has tools that allows for discovering, testing and producing client code using the specification. Support for generating and visualizing Open API documents in ASP.NET Core MVC is provided via community driven projects such as NSwag, and Swashbuckle.AspNetCore. Visit https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-2.1 to learn more about Open API Swagger and for details on configuring your applications to use it.

For 2.2, we’re investing in tooling and runtime experiences to to allow developers to produce better Open API documents. This work ties in with ongoing work to perform client code SDK generation during build.

How to use it?

Analyzer

For 2.2, we’re introducing a new API-specific analyzers NuGet package – Microsoft.AspNetCore.Mvc.Api.Analyzers. These analyzers work with controllers annotated with ApiController introduced in 2.1, while building on API conventions that we’re also introducing in this release. To start using this, install the package:


<PackageReference Include="Microsoft.AspNetCore.Mvc.Api.Analyzers"
    Version="2.2.0-preview1-final"
    PrivateAssets="All" />

Open API documents contain each status code and response type an operation may return. In MVC, you use attributes such as ProducesResponseType and Produces to document these. The analyzer inspects controllers annotated with ApiController and identifies actions that do not entirely document their responses. You should see this as warnings (squiggly lines) highlighting return types that aren’t documented as well as warnings in the output. In Visual Studio, this should additionally appear under the “Warnings” tab in the “Error List” dialog. You now have the opportunity to address these warnings using code fixes.

Let’s look at the analyzer in action:

The analyzer identified that the action returned a 404 but did not document it using a ProducesResponseTypeAttribute. We used a code fix to document this. The added attributes would now become available for Swagger / Open API tools to consume. It’s a great way to identify areas of your application that are lacking swagger documentation and correct it.

Conventions

If your controllers follows some common patterns, e.g. they are all primarily CRUD endpoints, and you aren’t already using ProducesResponseType or Produces to document them, you could consider using API conventions. Conventions let you define the most common “conventional” return types and status codes that you return from your action, and apply them to individual actions or controllers, or all controllers in an assembly. Conventions are a substitute to decorating individual actions with ProducesResponseType attributes.

By default, ASP.NET Core MVC 2.2 ships with a set of default conventions – DefaultApiConventions – that’s based on the controller that ASP.NET Core scaffolds. If your actions follow the pattern that scaffolding produces, you should be successful using the default conventions.

At runtime, ApiExplorer understand conventions. ApiExplorer is MVC’s abstraction to communicate with Open API document generators. Attributes from the applied convention get associated with an action and will be included in action’s Swagger documentation. API analyzers also understand conventions. If your action is unconventional i.e. it returns a status code that is not documented by the applied convention, it will produce a warning, encouraging you to document it.

There are 3 ways to apply a convention to a controller action:

  • Applying the ApiConventionType attribute as an assembly level attribute. This applies the specified convention to all controllers in an assembly.
[assembly: ApiConvention(typeof(DefaultApiConventions))]
  • Using the ApiConventionType attribute on a controller.
[ApiConvention(typeof(DefaultApiConventions))]
[ApiController]
[Route("/api/[controller]")]
public class PetsController : ControllerBase
{
    ...
}
  • Using ApiConventionMethod. This attributes accepts both the type and the convention method.
// PUT: api/Pets/5
[ApiConventionMethod(typeof(DefaultApiConventions), nameof(DefaultApiConventions.Put))]
[HttpPut("{id}")]
public async Task<ActionResult<Pet>> PutPet(long id, Pet pet)
{
    ...
}

Like many other features in MVC, more specific attributes will supersede less specific ones. An API metadata attribute such as ProducesResponseType or Produces applied to an action will stop applying any convention atributes. The ApiConventionMethod will supersede a ApiConventionType attribute applied to the method’s controller or the assembly; and an ApiConventionType attribute applied to a controller will supersede ones applied to the assembly.

Authoring conventions

A convention is a static type with methods. These methods are annotated with ProducesResponseType or ProducesDefaultResponseType attributes.

public static class MyAppConventions
{
    [ProducesResponseType(200)]
    [ProducesResponseType(404)]
    public static void Find(int id)
    {

    }
}

Applying this convention to an assembly would result in the convention method applying to any action with the name Find and having exactly one parameter named id, as long as they do not have other more specific metadata attributes.

In addition to ProducesResponseType and ProducesDefaultResponseType, two additional attributes – ApiConventionNameMatch and ApiConventionTypeMatch – can be applied to the convention method that determines the methods they apply to.

[ProducesResponseType(200)]
[ProducesResponseType(404)]
[ApiConventionNameMatch(ApiConventionNameMatchBehavior.Prefix)]
public static void Find(
    [ApiConventionNameMatch(ApiConventionNameMatchBehavior.Suffix)]
    int id)
{ }

The ApiConventionNameMatchBehavior.Prefix applied to the method, indicates that the convention can match any action as long as it starts with the prefix “Find”. This will include methods such as Find, FindPet or FindById. The ApiConventionNameMatchBehavior.Suffix applied to the parameter, indicates that the convention can match methods with exactly one parameter that terminate in the suffix id. This will include parameters such as id, or petId. ApiConventionTypeMatch can be similarly applied to types to constrain the type of the parameter. A params[] arguments can be used to indicate remaining parameters that do not need not be explicitly matched.

An easy way to get started authoring a custom convention is to start by copying the body of DefaultApiConventions and modifying it. Here’s a link to the source of the type: https://raw.githubusercontent.com/aspnet/Mvc/release/2.2/src/Microsoft.AspNetCore.Mvc.Core/DefaultApiConventions.cs

Feedback

This is one on our earliest forays in trying to use tooling to enhance runtime experiences. We’re interested in any thoughts you have about this as well as your experiences using this in your applications. The best place to provide feedback is by opening issues at https://github.com/aspnet/Mvc.

Additional help

ASP.NET Core 2.2.0-preview1: SignalR Java Client

$
0
0

This post was authored by Mikael Mengistu.

In ASP.NET Core 2.2 we are introducing a Java Client for SignalR. The first preview of this new client is available now. This client supports connecting to an ASP.NET Core SignalR Server from Java code, including Android apps.

The API for the Java client is very similar to that of the already existing .NET and JavaScript clients but there are some important differences to note.

The HubConnection is initialized the same way, with the HubConnectionBuilder type.

HubConnection hubConnection = new HubConnectionBuilder()
        .withUrl("www.example.com/myHub")
        .configureLogging(LogLevel.Information)
        .build();

Just like in the .NET client, we can send an invocation using the send method.

hubConnection.send("Send", input);

Handlers for server invocations can be registered using the on method. One major difference here is that the argument types must be specified as parameters, due to differences in how Java handles generics.

hubConnection.on("Send", (message) -> {
      // Your logic here
}, String.class);

Installing the Java Client

If you’re using Gradle you can add the following line to your build.gradle file:

implementation 'com.microsoft.aspnet:signalr:0.1.0-preview1-35029'

If you’re using Maven you can add the following lines to the dependencies section of your pom.xml file:

<dependency>
  <groupId>com.microsoft.aspnet</groupId>
  <artifactId>signalr</artifactId>
  <version>0.1.0-preview1-35029</version>
</dependency>

For a complete sample, see https://github.com/aspnet/SignalR-samples/tree/master/AndroidJavaClient

This is an early preview release of the Java client so there are many features that are not yet supported. We plan to close all these gaps before the RTM release:

  • Only primitive types can be accepted as parameters and return types.
  • The APIs are synchronous.
  • Only the “Send” call type is supported at this time, “Invoke” and streaming return values are not supported.
  • The client does not currently support the Azure SignalR Service.
  • Only the JSON protocol is supported.
  • Only the WebSockets transport is supported.

ASP.NET Core 2.2.0-preview1: Endpoint Routing

$
0
0

Endpoint Routing in 2.2

What is it?

We’re making a big investment in routing starting in 2.2 to make it interoperate more seamlessly with middleware. For 2.2 this will start with us making a few changes to the routing model, and adding some minor features. In 3.0 the plan is to introduce a model where routing and middleware operate together naturally. This post will focus on the 2.2 improvements, we’ll discuss 3.0 a bit further in the future.

So, without further ado, here are some changes coming to routing in 2.2.

How to use it?

The new routing features will be on by default for 2.2 applications using MVC. UseMvc and related methods with the 2.2 compatibility version will enable the new ‘Endpoint Routing’ feature set. Existing conventional routes (using MapRoute) or attribute routes will be mapped into the new system.

public void ConfigureServices(IServiceProvider services)
{
    ...
    
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

public void Configure(IApplicationBuilder app)
{
    ....
    
    app.UseMvc();
}

If you need to specifically revert the new routing features, this can be done by setting an option. We’ve tried to make the new endpoint routing system as backwards compatible as is feasible. Please log issues at https://github.com/aspnet/Routing if you encounter problems.

We don’t plan to provide an experience in 2.2 for using the new features without MVC – our focus for right now is to make sure we can successfully shift MVC applications to the new infrastructure.

Link Generator Service

We’re introducing a new singleton service that will support generating a URL. This new service can be used from middleware, and does not require an HttpContext. For right now the set of things you can link to is limited to MVC actions, but this will expand in 3.0.

public class MyMiddleware
{
    public MyMiddleware(RequestDelegate next, LinkGenerator linkGenerator) { ... }
    
    public async Task Invoke(HttpContext httpContext)
    {
        var url = _linkGenerator.GenerateLink(new { controller = "Store",
                                                    action = "ListProducts" });
    
        httpContext.Response.ContentType = "text/plain";
        return httpContext.Response.WriteAsync($"Go to {url} to see some cool stuff.");
    }
}

This looks a lot like MVC’s link generation support (IUrlHelper) for now — but it’s usable anywhere in your application. We plan to expand the set of things that are possible during 2.2.

Performance Improvements

One of the biggest reasons for us to revisit routing in 2.2 is to improve the performance of routing and MVC’s action selection.

We still have more work to, but the results so far are promising:
image

This chart shows the trend of Requests per Second (RPS) of our MVC implementation of the TechEmpower plaintext benchmark. We’ve improved the RPS of this benchmark about 10% from 445kRPS to 515kRPS.

To test more involved scenarios, we’ve used the Swagger/OpenAPI files published by Azure and Github to build code-generated routing benchmarks. The Azure API benchmark has 5160 distinct HTTP endpoints, and the Github benchmark has 243. The new routing system is significantly faster at processing the route table of these real world APIs than anything we’ve had before. In particular MVC’s features that select actions such as matching on HTTP methods and [Consumes(...)] are significantly less costly.

Improvements to link generation behavior for attribute routing

We’re also using this opportunity to revisit some of the behaviors that users find confusing when using attribute routing. Razor Pages is based on MVC’s attribute routing infrastructure and so many new users have become familiar with these problems lately. Inside the team, we refer to this feature as ‘route value invalidation’.

Without getting into too many details, conventional routing always invalidates extra route values when linking to another action. Attribute routing didn’t have this behavior in the past. This can lead to mistakes when linking to another action that uses the same route parameter names. Now both forms of routing invalidate values when linking to another action.

A conceptual understanding

The new routing system is called ‘Endpoint Routing’ because it represents the route table as a set of Endpoints that can be selected by the the routing system. If you’ve ever thought about how attribute routing might work in MVC, the above description should not be surprising. The new part is that a bunch of concerns traditionally handled by MVC have been pushed down to a very low level of the routing system. Endpoint routing now processes HTTP methods, [Consumes(...)], versioning, and other policies that used to be part of MVC’s action selection process.

In contrast to this, the existing routing system models the application is a list of ‘Routes’ that need to be processed in order. What each route does is a black-box to the routing system – you have to run the route to see if it will match.

To make MVC’s conventional routing work, we flatten the list of actions multiplied by the number of routes into a list of endpoints. This flattening allows us to process all of MVC’s requirements very efficiently inside the routing system.


The list of endpoints gets compiled into a tree that’s easy for us to walk efficiently. This is similar to what attribute routing does today but using a different algorithm and much lower complexity. Since routing builds a graph based on the endpoints, this means that the complexity of the tree scales very directly with your usage of features. We’re confident that we can scale up this design nicely while retaining the pay-for-play characteristics.

New round-tripping route parameter syntax

We are introducing a new catch-all parameter syntax {**myparametername}. During link generation, the routing system will encode all the content in the value captured by this parameter except the forward slashes.
Note that the old parameter syntax {*myparametername} will continue to work as it did before. Examples:

  • For a route defined using the old parameter syntax : /search/{*page},
    a call to Url.Action(new { category = "admin/products" }) would generate a link /search/admin%2Fproducts (notice that the forward slash is encoded)
  • For a route defined using the new parameter syntax : /search/{**page},
    a call to Url.Action(new { category = "admin/products" }) would generate a link /search/admin/products

What is coming next?

Expect more refinement and polish on the LinkGenerator API in the next preview. We want to make sure that this new API will support a variety of scenarios for the foreseeable future.

How can you help?

There are a few areas where you can provide useful feedback during this preview. We’re interested in any thoughts you have of course, these are a few specific things we’d like opinions on. The best place to provide feedback is by opening issues at https://github.com/aspnet/Routing

What are you using IRouter for? The ‘Endpoint Routing’ system doesn’t support IRouter-based extensibility, including inheriting from Route. We want what you’re using IRouter for today so we can figure out how to accomplish those things in the future.

What are you using IActionConstraint for? ‘Endpoint Routing’ supports IActionConstraint-based extensibility from MVC, but we’re trying to find better ways to accomplish these tasks.

What are your ‘most wanted’ issues from Routing? We’ve revisited a bunch of old closed bugs and brought back a few for reconsideration. If you feel like there are missing details or bugs in routing that we should consider please let us know.

Caveats and notes

We’ve worked to make the new routing system backwards compatible where possible. If you run into issues we’d love for you to report them at https://github.com/aspnet/Routing.

DataTokens are not supported in 2.2.0-preview1. We plan to address this for the next preview.

By nature the new routing system does not support IRouter based extensibility.

Generating links inside MVC to conventionally routed actions that don’t yet exist will fail (resulting in the empty string). This is in contrast to the current MVC behavior where linking usually succeeds even if the action being linked hasn’t been defined yet.

We know that the performance of link generation will be bad in 2.2.0-preview1. We worked hard to get the API definitions in so that you could try it out, and ignored performance. Expect the performance of URL generation to improve significantly for the next preview.

Endpoint routing does not support WebApiCompatShim. You must use the 2.1 compatibility switch to continue using the compat shim.

Viewing all 7144 articles
Browse latest View live


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