Posted on Leave a comment

Upcoming SameSite Cookie Changes in ASP.NET and ASP.NET Core

Avatar

Barry

SameSite is a 2016 extension to HTTP cookies intended to mitigate cross site request forgery (CSRF). The original design was an opt-in feature which could be used by adding a new SameSite property to cookies. It had two values, Lax and Strict. Setting the value to Lax indicated the cookie should be sent on navigation within the same site, or through GET navigation to your site from other sites. A value of Strict limited the cookie to requests which only originated from the same site. Not setting the property at all placed no restrictions on how the cookie flowed in requests. OpenIdConnect authentication operations (e.g. login, logout), and other features that send POST requests from an external site to the site requesting the operation, can use cookies for correlation and/or CSRF protection. These operations would need to opt-out of SameSite, by not setting the property at all, to ensure these cookies will be sent during their specialized request flows.

Google is now updating the standard and implementing their proposed changes in an upcoming version of Chrome. The change adds a new SameSite value, “None”, and changes the default behavior to “Lax”. This breaks OpenIdConnect logins, and potentially other features your web site may rely on, these features will have to use cookies whose SameSite property is set to a value of “None”. However browsers which adhere to the original standard and are unaware of the new value have a different behavior to browsers which use the new standard as the SameSite standard states that if a browser sees a value for SameSite it does not understand it should treat that value as “Strict”. This means your .NET website will now have to add user agent sniffing to decide whether you send the new None value, or not send the attribute at all.

.NET will issue updates to change the behavior of its SameSite attribute behavior in .NET 4.7.2 and in .NET Core 2.1 and above to reflect Google’s introduction of a new value. The updates for the .NET Framework will be available on November 19th as an optional update via Microsoft Update and WSUS if you use the “Check for Update” functionality. On December 10th it will become widely available and appear in Microsoft Update without you having to specifically check for updates. .NET Core updates will be available with .NET Core 3.1 starting with preview 1, in November.

.NET Core 3.1 will contain an updated enum definition, SameSite.Unspecified which will not set the SameSite property.

The OpenIdConnect middleware for Microsoft.Owin v4.1 and .NET Core will be updated at the same time as their .NET Framework and .NET updates, however we cannot introduce the user agent sniffing code into the framework, this must be implemented in your site code. The implementation of agent sniffing will vary according to what version of ASP.NET or ASP.NET Core you are using and the browsers you wish to support.

For ASP.NET 4.7.2 with Microsoft.Owin 4.1.0 agent sniffing can be implemented using ICookieManager;

public class SameSiteCookieManager : ICookieManager
{ private readonly ICookieManager _innerManager; public SameSiteCookieManager() : this(new CookieManager()) { } public SameSiteCookieManager(ICookieManager innerManager) { _innerManager = innerManager; } public void AppendResponseCookie(IOwinContext context, string key, string value, CookieOptions options) { CheckSameSite(context, options); _innerManager.AppendResponseCookie(context, key, value, options); } public void DeleteCookie(IOwinContext context, string key, CookieOptions options) { CheckSameSite(context, options); _innerManager.DeleteCookie(context, key, options); } public string GetRequestCookie(IOwinContext context, string key) { return _innerManager.GetRequestCookie(context, key); } private void CheckSameSite(IOwinContext context, CookieOptions options) { if (DisallowsSameSiteNone(context) && options.SameSite == SameSiteMode.None) { options.SameSite = null; } } public static bool DisallowsSameSiteNone(IOwinContext context) { // TODO: Use your User Agent library of choice here. var userAgent = context.Request.Headers["User-Agent"]; return userAgent.Contains("BrokenUserAgent") || userAgent.Contains("BrokenUserAgent2") }
}

And then configure OpenIdConnect settings to use the new CookieManager;

app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // … Your preexisting options … CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
});

SystemWebCookieManager will need the .NET 4.7.2 or later SameSite patch installed to work correctly.

For ASP.NET Core you should install the patches and then implement the agent sniffing code within a cookie policy. For versions prior to 3.1 replace SameSiteMode.Unspecified with (SameSiteMode)(-1).

private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{ if (options.SameSite > SameSiteMode.Unspecified) { var userAgent = httpContext.Request.Headers["User-Agent"].ToString(); // TODO: Use your User Agent library of choice here. if (/* UserAgent doesn’t support new behavior */) { // For .NET Core < 3.1 set SameSite = -1 options.SameSite = SameSiteMode.Unspecified; } }
} public void ConfigureServices(IServiceCollection services)
{ services.Configure<CookiePolicyOptions>(options => { options.MinimumSameSitePolicy = SameSiteMode.Unspecified; options.OnAppendCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); options.OnDeleteCookie = cookieContext => CheckSameSite(cookieContext.Context, cookieContext.CookieOptions); });
} public void Configure(IApplicationBuilder app)
{ app.UseCookiePolicy(); // Before UseAuthentication or anything else that writes cookies. app.UseAuthentication(); // …
}

Under testing with the Azure Active Directory team we have found the following checks work for all the common user agents that Azure Active Directory sees that don’t understand the new value.

public static bool DisallowsSameSiteNone(string userAgent)
{
    // Cover all iOS based browsers here. This includes:
    // - Safari on iOS 12 for iPhone, iPod Touch, iPad
    // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
    // - Chrome on iOS 12 for iPhone, iPod Touch, iPad
    // All of which are broken by SameSite=None, because they use the iOS networking stack
    if (userAgent.Contains("CPU iPhone OS 12") || userAgent.Contains("iPad; CPU OS 12"))
    {
        return true;
    }     // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
    // - Safari on Mac OS X.
    // This does not include:
    // - Chrome on Mac OS X
    // Because they do not use the Mac OS networking stack.
    if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&  userAgent.Contains("Version/") && userAgent.Contains("Safari"))
    {
        return true;
    }     // Cover Chrome 50-69, because some versions are broken by SameSite=None,  // and none in this range require it.
    // Note: this covers some pre-Chromium Edge versions,  // but pre-Chromium Edge does not require SameSite=None.
    if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
    {
        return true;
    }     return false;
}

This browser list is by no means canonical and you should validate that the common browsers and other user agents your system supports behave as expected once the update is in place.

Chrome 80 is scheduled to turn on the new behavior in February or March 2020, including a temporary mitigation added in Chrome 79 Beta. If you want to test the new behavior without the mitigation use Chromium 76. Older versions of Chromium are available for download.

If you cannot update your framework versions by the time Chrome turns the new behavior in early 2020 you may be able to change your OpenIdConnect flow to a Code flow, rather than the default implicit flow that ASP.NET and ASP.NET Core uses, but this should be viewed as a temporary measure.

We strongly encourage you to download the updated .NET Framework and .NET Core versions when they become available in November and start planning your update before Chrome’s changes are rolled out.

Avatar

Posted on Leave a comment

Redesigning Configuration Refresh for Azure App Configuration

Avatar

Overview

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

Initial design : Timer-based watch

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

public static IWebHost BuildWebHost(string[] args)
{ WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { // Load settings from Azure App Configuration // Set up the provider to listen for changes triggered by a sentinel value var settings = config.Build(); string appConfigurationEndpoint = settings["AzureAppConfigurationEndpoint"]; config.AddAzureAppConfiguration(options => { options.ConnectWithManagedIdentity(appConfigurationEndpoint) .Use(keyFilter: "WebDemo:*") .WatchAndReloadAll(key: "WebDemo:Sentinel", label: LabelFilter.Null); }); settings = config.Build(); }) .UseStartup<Startup>() .Build();
}

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

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

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

New design : Activity-based refresh

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

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

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

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

public static IWebHost BuildWebHost(string[] args)
{ WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { // Load settings from Azure App Configuration // Set up the provider to listen for changes triggered by a sentinel value var settings = config.Build(); string appConfigurationEndpoint = settings["AzureAppConfigurationEndpoint"]; config.AddAzureAppConfiguration(options => { options.ConnectWithManagedIdentity(appConfigurationEndpoint) .Use(keyFilter: "WebDemo:*") .ConfigureRefresh((refreshOptions) => { // Indicates that all settings should be refreshed when the given key has changed refreshOptions.Register(key: "WebDemo:Sentinel", label: LabelFilter.Null, refreshAll: true); }); }); settings = config.Build(); }) .UseStartup<Startup>() .Build();
}

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

Try it now!

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

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

Avatar

Software Engineer, Azure App Configuration

Follow    

Posted on Leave a comment

Azure SignalR Service now supports ASP.NET!

Avatar

Zhidi

We’ve just shipped the official version of the SignalR Service SDK for ASP.NET support:

Azure SignalR Service is a fully managed Azure service for real-time messaging. It is a preferred way for scaling ASP.NET Core SignalR application. However, SignalR Service is based on SignalR for ASP.NET Core 2.0, which is not 100% compatible with ASP.NET SignalR. Some code changes and proper version of dependent libraries are needed to make ASP.NET SignalR application work with SignalR Service.

We have received many usage feedbacks from customers since we announced the preview support for ASP.NET, at Microsoft Ignite 2018. Today, we are excited to announce that we have released the generally available version 1.0.0 of ASP.NET support SDK for Azure SignalR Service!

This diagram shows the typical architecture to use Azure SignalR Service with application server either written in ASP.NET Core, or now, in ASP.NET.

arch.png

For self-hosted SignalR application, the application server listens to and serves client connections directly. With SignalR Service, the application server will only respond to clients’ negotiate requests, and redirect clients to SignalR Service to establish the persistent client-server connections.

Using the ASP.NET support for Azure SignalR Service you will be able to:

  • Continue to keep SignalR application using ASP.NET, but work with fully managed ASP.NET Core based SignalR Service.
  • Change a few lines of SignalR API codes, to switch to use SignalR Service instead of self-hosted SignalR Hubs.
  • Leverage Azure SignalR Service’s built-in features and tools to help operate the SignalR application, with guaranteed SLA.

To receive the full benefit from the new ASP.NET support feature, please download and upgrade your SDKs to the latest supported versions:

  • .NET: 4.6.1+
  • Microsoft.AspNet.SignalR.*: 2.4.1
  • Microsoft.Azure.SignalR.AspNet: 1.0.0

Many factors, including non-technical ones, make the web application migrate from ASP.NET to ASP.NET Core difficult.

The ASP.NET support for Azure SignalR Service is to enable ASP.NET SignalR application developers to easily switch to use SignalR Service with minimal code change.

Some APIs and features are no longer supported:

  • Automatic reconnects
  • Forever Frame transport
  • HubState
  • PersistentConnection class
  • GlobalHost object
  • HubPipeline module
  • Client side Internet Explorer support before Microsoft Internet Explorer 11

ASP.NET support is focus on compatibility, so not all ASP.NET Core SignalR new features are supported. To name a few: MessagePack, Streaming, etc., are only available for ASP.NET Core SignalR applications.

SignalR Service can be configured for different service mode: Classic/Default/Serverless. For ASP.NET support, the Serverless mode is not supported.

For a complete list of feature comparison between ASP.NET SignalR and ASP.NET Core SignalR, the proper version of SDKs to use in each case, and what are the recommended alternatives to use for features discontinued in ASP.NET Core SignalR, please refer to doc here.

We’d like to hear about your feedback and comments. You can reach the product team at the GitHub repo, or by email.

Avatar
Zhidi Shang

Principal Program Manager, Azure SignalR Service

Follow Zhidi   

Posted on Leave a comment

Microsoft’s Developer Blogs are Getting an Update

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

We’d love your feedback

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

Frequently Asked Questions

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

Will Saved/Bookmarked URLs Redirect?

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

Will My Feed Reader Still Send New Posts?

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

Which Blogs Are Moving?

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

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

Posted on Leave a comment

When should you right click publish

Some people say ‘friends don’t let friends right click publish’ but is that true? If they mean that there are great benefits to setting up a CI/CD workflow, that’s true and we will talk more about these benefits in just a minute. First, let’s remind ourselves that the goal isn’t always coming up with the best long-term solution.

Technology moves fast and as developers we are constantly learning and experimenting with new languages, frameworks and platforms. Sometimes we just need to prototype something rather quickly in order to evaluate its capabilities. That’s a classic scenario where right click publish in Visual Studio provides the right balance between how much time you are going to spend (just a few seconds) and the options that become available to you (quite a few depending on the project type) such as publish to IIS, FTP  & Folder (great for xcopy deployments and integration with other tools).

Continuing with the theme of prototyping and experimenting, right click publish is the perfect way for existing Visual Studio customers to evaluate Azure App Service (PAAS). By following the right click publish flow you get the opportunity to provision new instances in Azure and publish your application to them without leaving Visual Studio:

When the right click publish flow has been completed, you immediately have a working application running in the cloud:

Platform evaluations and experiments take time and during that time, right click publish helps you focus on the things that matter. When you are ready and the demand rises for automation, repeatability and traceability that’s when investing into a CI/CD workflow starts making a lot of sense:

  • Automation: builds are kicked off and tests are executed as soon as you check in your code
  • Repeatability: it’s impossible to produce binaries without having the source code checked in
  • Traceability: each build can be traced back to a specific version of the codebase in source control which can then be compared with another build and figure out the differences

The right time to adopt CI/CD typically coincides with a milestone related to maturity; either and application milestone or the team’s that is building it. If you are the only developer working on your application you may feel that setting up CI/CD is overkill, but automation and traceability can be extremely valuable even to a single developer once you start shipping to your customers and you have to support multiple versions in production.

With a CI/CD workflow you are guaranteed that all binaries produced by a build can be linked back to the matching version of the source code. You can go from a customer bug report to looking at the matching source code easily, quickly and with certainty. In addition, the automation aspects of CI/CD save you valuable time performing common tasks like running tests and deploying to testing and pre-production environments, lowering the overhead of good practices that ensure high quality.

As always, we want to see you successful, so if you run into any issues using publish in Visual Studio or setting up your CI/CD workload, let me know in the comment section below and I’ll do my best to get your question answered.

Posted on Leave a comment

Announcing CosmosDB Table Async OutputCache Provider Release and ASP.NET Providers Connected Service Extension Update

Through the years, ASP.NET team have been releasing new ASP.NET SessionState and OutputCache providers to help developers make their web applications ready for the cloud environment. Today we are announcing a new OutputCache provider, Microsoft.AspNet.OutputCache.CosmosDBTableAsyncOutputCacheProvider,  to enable your applications store the OutputCache data into CosmosDB. It supports both Azure CosmosDB Table and Azure Storage Table.

How to Use CosmosDBTableAsyncOutputCacheProvider

  1. Open the NuGet package manager and search for Microsoft.AspNet.OutputCache.CosmosDBTableAsyncOutputCacheProvider and install. Make sure that your application is targeted to .NET Framework 4.6.2 or higher version. Download the .NET Framework 4.6.2 Developer Pack if you do not already have it installed.
  2. The package has dependency on Microsoft.AspNet.OutputCache.OutputCacheModuleAsync Nuget package and Microsoft.Azure.CosmosDB.Table Nuget package. After you install the package, both Microsoft.AspNet.OutputCache.CosmosDBTableAsyncOutputCacheProvider.dll and dependent assemblies will be copied to the Bin folder.
  3. Open the web.config file, you will see two new configuration sections are added, caching and appSettings. The first one is to configure the OutputCache provider, you may want to update the table name. The provider will create the table if it doesn’t exist on the configured Azure service instance. The second one is the appSettings for the storage connection string. Depends on the connection string you use, the provider can work with either Azure CosmosDB Table or Azure Storage Table.

    ASP.NET Providers Connected Service Extension Update

    5 months ago, we released ASP.NET Providers Connected Service Visual Studio Extension to help the developers to pick the right ASP.NET provider and configure it properly to work with Azure resources. Today we are releasing an update for this extension which enables you configure ComosDB table OutputCache provider and Redis cache OutputCache.

    Summary

    The new CosmosDBTableAsyncOutputCacheProvider Nuget package enables your ASP.NET application leverage Azure CosmosDB and Azure Storage to store the OutputCache data. The new ASP.NET Providers Connected Service extension adds more Azure ready ASP.NET providers support. Please try it today and let us know you feedback.

Posted on Leave a comment

Use Hybrid Connections to Incrementally Migrate Applications to the Cloud

As the software industry shifts to running software in the cloud, organizations are looking to migrate existing applications from on-premises to the cloud. Last week at Microsoft’s Ignite conference, Paul Yuknewicz and I delivered a talk focused on how to get started migrating applications to Azure (watch the talk free) where we walked through the business case for migrating to the cloud, and choosing the right hosting and data services.

If your application is a candidate for running in App Service, one of the most useful pieces of technology that we showed was Hybrid Connections. Hybrid Connections let you host a part of your application in Azure App Service, while calling back into resources and services not running in Azure (e.g. still on-premises). This enables you to try running a small part of your application in the cloud without the need to move your entire application and all of its dependencies at once; which is usually time consuming, and extremely difficult to debug when things don’t work. So, in this post I’ll show you how to host an ASP.NET front application in the cloud, and configure a hybrid connection to connect back to a service on your local machine.

Publishing Our Sample App to the Cloud

For the purposes of this post, I’m going to use the Smart Hotel 360 App sample that uses an ASP.NET front end that calls a WCF service which then accesses a SQL Express LocalDB instance on my machine.

The first thing I need to do is publish the ASP.NET application to App Service. To do this, right click on the “SmartHotel.Registration.Web” project and choose “Publish”

clip_image001

The publish target dialog is already on App Service, and I want to create a new one, so I will just click the “Publish” button.

This will bring up the “Create App Service” dialog.  Next, I will click “Create” and wait for a minute while the resources in the cloud are created and the application is published.

clip_image003

When it’s finished publishing, my web browser will open to my published site. At this point, there will be an error loading the page since it cannot connect to the WCF service. To fix this we’ll add a hybrid connection.

image

Create the Hybrid Connection

To create the Hybrid Connection, I navigate to the App Service I just created in the Azure Portal. One quick way to do this is to click the “Managed in Cloud Explorer” link on the publish summary page

clip_image005

Right click the site, and choose “Open in Portal” (You can manually navigate to the page by logging into the Azure portal, click App Services, and choose your site).

clip_image006

To create the hybrid connection:

Click the “Networking” tab in the Settings section on the left side of the App Service page

Click “Configure your hybrid connection endpoints” in the “Hybrid connections” section

image

Next, click “Add a hybrid connection”

Then click “Create a new hybrid connection”

clip_image010

Fill out the “Create new hybrid connection” form as follows:

  • Hybrid connection Name: any unique name that you want
  • Endpoint Host: This is the machine URL your application is currently using to connect to the on-premises resource. In this case, this is “localhost” (Note: per the documentation, use the hostname rather than a specific IP address if possible as it’s more robust)
  • Endpoint Port: The port the on-premises resource is listening on. In this case, the WCF service on my local machine is listening on 2901
  • Servicebus namespace: If you’ve previously configured hybrid connections you can re-use an existing one, in this case we’ll create a new one, and give it a name

clip_image011

Click “OK”. It will take about 30 seconds to create the hybrid connection, when it’s done you’ll see it appear on the Hybrid connections page.

Configure the Hybrid Connection Locally

Now we need to install the Hybrid Connection Manager on the local machine. To do this, click the “Download connection manager” on the Hybrid connections page and install the MSI.

clip_image013

After the connection manager finishes installing, launch the “Hybrid Connections Manager UI”, it should appear in your Windows Start menu if you type “Hybrid Connections”. (If for some reason it doesn’t appear on the Start Menu, launch it manually from “C:\Program Files\Microsoft\HybridConnectionManager <version#>”)

Click the “Add a new Hybrid Connection” button in the Hybrid Connections Manager UI and login with the same credentials you used to publish your application.

clip_image015

Choose the subscription you used published your application from the “Subscription” dropdown, choose the hybrid connection you just created in the portal, and click “Save”.

clip_image017

In the overview, you should see the status say “Connected”. Note: If the state won’t change from “Not Connected”, I’ve found that rebooting my machine fixes this (it can take a few minutes to connect after the reboot).

clip_image019

Make sure everything is running correctly on your local machine, and then when we open the site running in App Service we can see that it loads with no error. In fact, we can even put a breakpoint in the GetTodayRegistrations() method of Service.svc.cs, hit F5 in Visual Studio, and when the page loads in App Service the breakpoint on the local machine is hit!

clip_image021

Conclusion

If you are looking to move applications to the cloud, I hope that this quick introduction to Hybrid Connections will enable you to try moving things incrementally. Additionally, you may find these resources helpful:

As always, if you have any questions, or problems let me know via Twitter, or in the comments section below.

Posted on Leave a comment

Exploring Azure App Service – Azure Diagnostics

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.

Posted on Leave a comment

Changes to script debugging in Visual Studio 15.7

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.

Posted on Leave a comment

Use Dependency Injection In WebForms Application

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.