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

ASP.NET Core 2.1-preview1: Introducing HTTPClient factory

$
0
0

HttpClient factory is an opinionated factory for creating HttpClient instances to be used in your applications. It is designed to:

  1. Provide a central location for naming and configuring logical HttpClients. For example, you may configure a client that is pre-configured to access the github API.
  2. Codify the concept of outgoing middleware via delegating handlers in HttpClient and implementing Polly based middleware to take advantage of that.
    1. HttpClient already has the concept of delegating handlers that could be linked together for outgoing HTTP requests. The factory will make registering of these per named client more intuitive as well as implement a Polly handler that allows Polly policies to be used for Retry, CircuitBreakers, etc.
  3. Manage the lifetime of HttpClientMessageHandlers to avoid common problems that can occur when managing HttpClient lifetimes yourself.

Usage

There are several ways that you can use HttpClient factory in your application. For the sake of brevity we will only show you one of the ways to use it here, but all options are being documented and are currently listed in the HttpClientFactory repo wiki.

In the rest of this section we will use HttpClient factory to create a HttpClient to call the default API template from Visual Studio, the ValuesController API.

1. Create a typed client

Typed clients are a class that accepts a HttpClient and optionally uses it to call some HTTP service. For example:

NOTE: The Content.ReadAsAsync method comes from the Microsoft.AspNet.WebApi.Client package. You will need to add that to your application if you want to use it.

The typed client is activated by DI, meaning that it can accept any registered service in its constructor.

2. Register the typed client

Once you have a type that accepts a HttpClient you can register it with the following:

The function here will execute to configure your HttpClient instance before it is passed to the ValuesClient. A typed client is, effectively, a transient service, meaning that a new instance is created each time one is needed and it will receive a new HttpClient instance each time it is constructed. This means that your configuration func, in this case retrieving the URI from configuration, will run every time something needs a ValuesClient.

3. Use the client

Now that you have registerd your client you can use it anywhere that can have services injected by DI, for example I could have a Razor Pages page model like this:

or perhaps like this:

Diagnostics

By default, when you use a HttpClient created by HttpClient factory, you will see logs like the following appear:

Log of outgoing HTTP requests

The log messages about starting and processing a HTTP request are being logged because we are using a HttpClient created by the HttpClient factory. From these 7 log messages you can see:

  1. An incoming request in to localhost:5001 in this case this is the browser navigating to my Razor Pages page.
  2. MVC selecting a handler for the request, the OnGetAsync method of my PageModel.
  3. The beginning of an outgoing HTTP request, this marks the start of the outgoing pipeline that we will discuss in the next section.
  4. We send a HTTP request with the given verb.
  5. Recieve the request back in 439.6606 ms, with a status of OK.
  6. End the outgoing HTTP pipeline.
  7. End and return from our handler.

If you set the LogLevel to at least Debug then we will also log header information. In the following screenshot I added an accept header to my request, and you can see the response headers:

Debug logs showing outgoing headers

The outgoing middleware pipeline

For sometime now ASP.NET has had the concept of middleware that operates on an incoming request. With HttpClientFactory we are going to bring a similar concept to outgoing HTTP requests using the existing DelegatingHttpHandler type that has been in .NET for some time. As an example of how this works we will look at how we generate the log messages that we looked at in the previous section:

NOTE: This code is simplified for the sake of brevity and ease of understanding, the actual class can be found here

Let’s look at another example that isn’t already built in. When using client based service discovery systems then you will ask another service for the host/port combination that you should use to communicate to a given service type. For example, you could be using the HTTP API of Consul.io to resolve the name ‘values’ to an IP and port combination. In the following handler we will replace the incoming host name with the result of a request to an IServiceRegistry type that would be implemented to communicate with whatever service discovery system you used. In this way we could make a request to ‘http://values/api/values’ and it would actually be connect to ‘http://:/api/values’.

NOTE: This sample is inspired by the CondensorDotNet project. Which has a HttpClientHandler that works the same way.

We can then register this with the following:

The type being give to the AddHttpMessageHandler must be registered as a transient service. However, because we have the IServiceRegistry as its own service it can have a different lifetime to the handler, allowing caching and other features to be implemented in the service registry instead of the handler itself.

Now that we’ve registered the handler all requests will have their Host and Port set to whatever is returned from the IServiceRegistry type. If we continued our example we would implement IServiceRegistry to call the Consul.io HTTP Endpoint to resolve the URI from the requested HostName.

HttpClient lifetimes

In general you should get a HttpClient from the factory per unit of work. In the case of MVC this means you would generally accept a typed client in the constructor of your controller and let it be garbage collected when the controller does. If you are using IHttpClientFactory directly, which we don’t talk about in this post but can be done, then the equivalent would be to create a HttpClient in the constructor and let it be collected the same way.

Disposing of the client is not mandatory, but doing so will cancel any ongoing requests and ensure the given instance of HttpClient cannot be used after Dispose is called. The factory takes care of tracking and disposing of the important resources that instances of HttpClient use, which means that HttpClient instances can be generally be treated as .NET objects that don’t require disposing.

One effect of this is that some common patterns that people use today to handle HttpClient instances, such as keeping a single HttpClient instance alive for a long time, are no longer required. Documentation about what exactly the factory does and what patterns it resolves will be available, but hasn’t been completed yet.

In the future we hope that a new HttpClientHandler will mean that HttpClient instances created without the factory will also be able to be treated this way. We are working on this in the corefx GitHub repositories now.

Future

Before 2.1 is released

  • Polly integration.
  • Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. We will be building a package that allows easy integration of Polly policies with HttpClients created by the HttpClient factory.

Post 2.1
  • Auth Handlers.
  • The ability to have auth headers automatically added to outgoing HTTP requests.

Conclusion

The HTTPClient factory is available in 2.1 Preview 1 apps. You can ask questions and file feedback in the HttpClientFactory github repository.


ASP.NET Core 2.1.0-preview1: Improvements to IIS hosting

$
0
0
The ASP.NET Core Module (ANCM) is a global IIS module that has been responsible for proxying requests over from IIS to your backend ASP.NET application running Kestrel. Since 2.0 we have been hard at work to bring to two major improvements to ANCM: version agility and performance. In the 2.1.0-preview1 release, we have chosen not to update the global module to avoid impacting any existing 1.x/2.0 applications. This blog post details the changes in ANCM and how you can try out these changes today.

Version agility

It has been hard to iterate on ANCM since we’ve had to ensure forward and backward compatibility between every version of ASP.NET Core and ANCM that has shipped thus far. To mitigate this problem going forward, we’ve refactored our code into two separate components- the ASP.NET Core Shim (shim) and the ASP.NET Core Request Handler (request handler). The shim (aspnetcore.dll) as the name suggests is a lightweight shim where as the request handler (aspnetcorerh.dll) does all the request processing. Going forward, the shim will ship globally and will continue to be installed via the Server Hosting Bundle. The request handler will now ship via a NuGet package- Microsoft.AspNetCore.Server.IIS which you can directly reference in your application or consume via the ASP.NET metapackage or shared runtime. As a consequence, two different ASP.NET Core applications running on the same server can use a different version of the request handler.

Performance

In addition to the packaging changes, ANCM also adds supports for an in-process hosting model. Instead of serving as a reverse-proxy, ANCM can now boot the CoreCLR and host your application inside the IIS worker process. Our preliminary performance tests have shown that this model delivers 4.4x the request throughput compared to hosting your dotnet application out-of-process and proxying over the requests.

How do I try it?

If you have already installed the 2.1.0-preview1 ServerHosting bundle, you can install the latest ANCM by running this script.

Alternatively, you can deploy an Azure VM which is already setup with the latest ANCM by clicking the Deploy to Azure button below.
 

Create a new project or update your existing project

Now that we have an environment to publish to, let’s create a new application that targets 2.1.0-preview1 of ASP.NET Core.
Alternatively, you can upgrade an existing project by following the instructions on this blog post.

Modify your project

Let’s go ahead and modify our project by setting a project property to indicate that we want to our published application to be run inprocess.
Add this to your csproj file.

Publish your project

Create a new publish profile and select the Azure VM that you just created. If you’re using Visual Studio, you can easily publish to the Azure VM you just created. In the Solution Explorer, right-click the project and select Publish to open the Publish wizard where you can choose to publish to an Azure VM that you just created.
You may need to allow WebDeploy to publish to a server using an untrusted certificate. This can be accomplished by adding the following attribute to your publish profile (.pubxml file)
If you’re running elsewhere, go ahead publish your app to a Folder and copy over your artifacts or publish directly via WebDeploy.

web.config

As part of the publish process, the WebSDK will read the AspNetCoreModuleHostingModel property and transform your web.config to look something like this. (Observe the new hostingModel attribute)

Debugging

To view the Cloud Explorer, select View > Cloud Explorer on the menu bar
If you’ve been following along using an Azure VM, you can enable remote debugging on your Azure VM via the cloud explorer. In the Actions tab associated with your VM, you should be able to Enable Debugging.
Once you’ve enabled remote debugging, you should be able to attach directly to the w3wp.exe process. If you don’t see the process listed, you may need to send a request to your server to force IIS to start the worker process.
If you’ve been following along locally, you can use Visual Studio to attach a be directly to your IIS worker process and debug your application code running in the IIS worker process as shown below. (You may be prompted to restart Visual Studio as an Administrator for this).
We don’t yet have an experience for debugging with IIS Express. At the moment, you will have to publish to IIS and then attach a debugger.

Switching between in-process and out-of-process

Switching hosting models can be deployment-time decision. To change between hosting models, all you have to do is change the hostingModel attribute in your web.config from inprocess to outofprocess.
It can be easily observed in this simple app where you’ll observe either Hello World from dotnet or Hello World from w3wp based on your hosting model.

ASP.NET Core 2.1.0-preview1: Razor UI in class libraries

$
0
0

One frequently requested scenario that ASP.NET Core 2.1 improves is building UI in reusable class libraries. With ASP.NET Core 2.1 you can package your Razor views and pages (.cshtml files) along with your controllers, page models, and data models in reusable class libraries that can be packaged and shared. Apps can then include pre-built UI components by referencing these packages and customize the UI by overriding specific views and pages.

To try out building Razor UI in a class library first install the .NET Core SDK for 2.1.0-preview1.

Create an ASP.NET Core Web Application by running dotnet new razor or selecting the corresponding template in Visual Studio. The default template has fivestandard pages: Home, About, Contact, Error, and Privacy. Let’s move the Contact page into a class library. Add a .NET Standard class library to the solution and reference it from the ASP.NET Core Web Application.

We need to make some modifications to the class library .csproj file to enable Razor compilation. We need to set the RazorCompileOnBuild, IncludeContentInPack, and ResolvedRazorCompileToolset MSBuild properties as well as add the .cshtml files as content and also a package reference to Microsoft.AspNetCore.Mvc. Your class library project file should look like this:

ClassLibrary1.csproj

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

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <ResolvedRazorCompileToolset>RazorSdk</ResolvedRazorCompileToolset>
    <RazorCompileOnBuild>true</RazorCompileOnBuild>
    <IncludeContentInPack>false</IncludeContentInPack>
  </PropertyGroup>

  <ItemGroup>
    <Content Include="Pages\**\*.cshtml" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.0-preview1-final" />
  </ItemGroup>

</Project>

For Preview1 making these project file modifications is a manual step, but in future previews we will provide a Razor MSBuild SDK (Microsoft.NET.Sdk.Razor) as well as project templates to handle these details for you.

Now we can add some Razor files to our class library. Add a Pages directory to the class library project and move over the Contact page along with its page model (Contact.cshtml, Contact.cshtml.cs) from the web app project. You’ll also need to move over _ViewImports.cshtml to get the necessary using statements.

Class library with Razor

Add some content to the Contact.cshtml file so you can tell it’s being used.

@page
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>

<h2>BTW, this is from a Class Library!</h2>

Run the app and browse to the Contact page.

Contact page from a class library

You can override views and pages from a class library in your app by putting the page or view at the same path in your app. For example, let’s add a _Message.cshtml partial view that gets called from the contact page.

In the class library project add a Shared folder under the Pages folder and add the following partial view:

_Message.cshtml

<h2>You can override me!</h2>

Then call the _Message partial from the contact page using the new partial tag helper.

Contact.cshtml

@page
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>

<h2>BTW, this is from a Class Library!</h2>

<partial name="_Message" />

Run the app to see that the partial is now rendered.

Contact page with partial

Now override the partial by adding a _Message.cshtml file to the web app under the /Pages/Shared folder.

_Message.cshtml

<h2>Overridden!</h2>

Rebuild and run the app to see the update.

Overridden partial

Summary

By compiling Razor views and pages into shareable libraries you can reuse existing UI with minimal effort. Please give this feature a try and let us know what you think on GitHub. Thanks!

ASP.NET Core 2.1.0-preview1: Introducing Identity UI as a library

$
0
0

ASP.NET Core has historically provided project templates with code for setting up ASP.NET Core Identity, which enables support for identity related features like user registration, login, account management, etc. While ASP.NET Core Identity handles the hard work of dealing with passwords, two-factor authentication, account confirmation, and other hairy security concerns, the amount of code required to setup a functional identity UI is still pretty daunting. The most recent version of the ASP.NET Core Web Application template with Individual User Accounts setup has over 50 files and a couple of thousand lines of code dedicated to setting up the identity UI!

Identity files

Having all this identity code in your app gives you a lot of flexibility to update and change it as you please, but also imposes a lot of responsibility. It's a lot of security sensitive code to understand and maintain. Also if there is an issue with the code, it can't be easily patched.

The good news is that in ASP.NET Core 2.1 we can now ship Razor UI in reusable class libraries. We are using this feature to provide the entire identity UI as a prebuilt package (Microsoft.AspNetCore.Identity.UI) that you can simply reference from an application. The project templates in 2.1 have been updated to use the prebuilt UI, which dramatically reduces the amount of code you have to deal with. The one identity specific .cshtml file in the template is there solely to override the layout used by the identity UI to be the layout for the application.

Identity UI files

_ViewStart.cshtml

@{
    Layout = "/Pages/_Layout.cshtml";
}

The identity UI is enabled by both referencing the package and calling AddDefaultUI when setting up identity in the ConfigureServices method.

services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultUI()
    .AddDefaultTokenProviders();

If you want the flexibility of having the identity code in your app, you can use the new identity scaffolder to add it back.

Currently you have to invoke the identity scaffolder from the command-line. In a future preview you will be able to invoke the identity scaffolder from within Visual Studio.

From the project directory run the identity scaffolder with the -dc option to reuse the existing ApplicationDbContext.

dotnet aspnet-codegenerator identity -dc WebApplication1.Data.ApplicationDbContext

The identity scaffolder will generate all of the identity related code in a new area under /Areas/Identity/Pages.

In the ConfigureServices method in Startup.cs you can now remove the call to AddDefaultUI.

services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    // .AddDefaultUI()
    .AddDefaultTokenProviders();

Note that the ScaffoldingReadme.txt says to remove the entire call to AddIdentity, but this is a typo that will be corrected in a future release.

To also have the scaffolded identity code pick up the layout from the application, remove _Layout.cshtml from the identity area and update _ViewStart.cshtml in the identity area to point to the layout for the application (typically /Pages/_Layout.cshtml or /Views/Shared/_Layout.cshtml).

/Areas/Identity/Pages/_ViewStart.cshtml

@{
    Layout = "/Pages/_Layout.cshtml";
}

You should now be able to run the app with the scaffolded identity UI and log in with an existing user.

You can also use the code from the identity scaffolder to customize different pages of the default identity UI. For example, you can override just the register and account management pages to add some additional user profile data.

Let's extend identity to keep track of the name and age of our users.

Add an ApplicationUser class in the Data folder that derives from IdentityUser and adds Name and Age properties.

public class ApplicationUser : IdentityUser
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Update the ApplicationDbContext to derive from IdentityContext<ApplicationUser>.

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
    }

In the Startupclass update the call to AddIdentity to use the new ApplicationUser and add back the call to AddDefaultUI if you removed it previously.

services.AddIdentity<ApplicationUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultUI()
    .AddDefaultTokenProviders();

Now let's update the register and account management pages to add UI for the two additional user properties.

In a future release we plan to update the identity scaffolder to support scaffolding only specific pages and provide a UI for selecting which pages you want, but for now the identity scaffolder is all or nothing and you have to remove the pages you don't want.

Remove all of the scaffolded files under /Areas/Identity except for:

  • /Areas/Identity/Pages/Account/Manage/Index.*
  • /Areas/Identity/Pages/Account/Register.*
  • /Areas/Identity/Pages/_ViewImports.cshtml
  • /Areas/Identity/Pages/_ViewStart.cshtml

Let's start with updating the register page. In /Areas/Identity/Pages/Account/Register.cshtml.cs make the following changes:

  • Replace IdentityUser with ApplicationUser
  • Replace ILogger<LoginModel> with ILogger<RegisterModel> (known bug that will get fixed in a future release)
  • Update the InputModel to add Name and Age properties:

      public class InputModel
      {
          [Required]
          [DataType(DataType.Text)]
          [Display(Name = "Full name")]
          public string Name { get; set; }
    
          [Required]
          [Range(0, 199, ErrorMessage = "Age must be between 0 and 199 years")]
          [Display(Name = "Age")]
          public string Age { get; set; }
    
          [Required]
          [EmailAddress]
          [Display(Name = "Email")]
          public string Email { get; set; }
    
          [Required]
          [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
          [DataType(DataType.Password)]
          [Display(Name = "Password")]
          public string Password { get; set; }
    
          [DataType(DataType.Password)]
          [Display(Name = "Confirm password")]
          [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
          public string ConfirmPassword { get; set; }
      }
    
  • Update the OnPostAsync method to bind the new input values to the created ApplicationUser

      var user = new ApplicationUser()
      {
          Name = Input.Name,
          Age = Input.Age,
          UserName = Input.Email,
          Email = Input.Email
      };
    

Now we can update /Areas/Identity/Pages/Account/Register.cshtml to add the new fields to the register form.

<div class="row">
    <div class="col-md-4">
        <form asp-route-returnUrl="@Model.ReturnUrl" method="post">
            <h4>Create a new account.</h4>
            <hr />
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Input.Name"></label>
                <input asp-for="Input.Name" class="form-control" />
                <span asp-validation-for="Input.Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.Age"></label>
                <input asp-for="Input.Age" class="form-control" />
                <span asp-validation-for="Input.Age" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.Email"></label>
                <input asp-for="Input.Email" class="form-control" />
                <span asp-validation-for="Input.Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.Password"></label>
                <input asp-for="Input.Password" class="form-control" />
                <span asp-validation-for="Input.Password" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.ConfirmPassword"></label>
                <input asp-for="Input.ConfirmPassword" class="form-control" />
                <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
            </div>
            <button type="submit" class="btn btn-default">Register</button>
        </form>
    </div>
</div>

Run the app and click on Register to see the updates:

Register updated

Now let's update the account management page. In /Areas/Identity/Pages/Account/Manage/Index.cshtml.cs make the following changes:

  • Replace IdentityUser with ApplicationUser
  • Update the InputModel to add Name and Age properties:

      public class InputModel
      {
          [Required]
          [DataType(DataType.Text)]
          [Display(Name = "Full name")]
          public string Name { get; set; }
    
          [Required]
          [Range(0, 199, ErrorMessage = "Age must be between 0 and 199 years")]
          [Display(Name = "Age")]
          public int Age { get; set; }
    
          [Required]
          [EmailAddress]
          public string Email { get; set; }
    
          [Phone]
          [Display(Name = "Phone number")]
          public string PhoneNumber { get; set; }
      }
    
  • Update the OnGetAsync method to initialize the Name and Age properties on the InputModel:

      Input = new InputModel
      {
          Name = user.Name,
          Age = user.Age,
          Email = user.Email,
          PhoneNumber = user.PhoneNumber
      };
    
  • Update the OnPostAsync method to update the name and age for the user:

      if (Input.Name != user.Name)
      {
          user.Name = Input.Name;
      }
    
      if (Input.Age != user.Age)
      {
          user.Age = Input.Age;
      }
    
      var updateProfileResult = await _userManager.UpdateAsync(user);
      if (!updateProfileResult.Succeeded)
      {
          throw new InvalidOperationException($"Unexpected error ocurred updating the profile for user with ID '{user.Id}'");
      }
    

Now update /Areas/Identity/Pages/Account/Manage/Index.cshtml to add the additional form fields:

<div class="row">
    <div class="col-md-6">
        <form method="post">
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Username"></label>
                <input asp-for="Username" class="form-control" disabled />
            </div>
            <div class="form-group">
                <label asp-for="Input.Email"></label>
                @if (Model.IsEmailConfirmed)
                {
                    <div class="input-group">
                        <input asp-for="Input.Email" class="form-control" />
                        <span class="input-group-addon" aria-hidden="true"><span class="glyphicon glyphicon-ok text-success"></span></span>
                    </div>
                }
                else
                {
                    <input asp-for="Input.Email" class="form-control" />
                    <button asp-page-handler="SendVerificationEmail" class="btn btn-link">Send verification email</button>
                }
                <span asp-validation-for="Input.Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.Name"></label>
                <input asp-for="Input.Name" class="form-control" />
            </div>
            <div class="form-group">
                <label asp-for="Input.Age"></label>
                <input asp-for="Input.Age" class="form-control" />
            </div>
            <div class="form-group">
                <label asp-for="Input.PhoneNumber"></label>
                <input asp-for="Input.PhoneNumber" class="form-control" />
                <span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
            </div>
            <button type="submit" class="btn btn-default">Save</button>
        </form>
    </div>
</div>

Run the app and you should now see the updated account management page.

Manage account updated

You can find a complete version of this sample app on GitHub.

Summary

Having the identity UI as a library makes it much easier to get up and running with ASP.NET Core Identity, while still preserving the ability to customize the identity functionality. For complete flexibility you can also use the new identity scaffolder to get full access to the code. We hope you enjoy these new features! Please give them a try and let us know what you think about them on GitHub.

ASP.NET Core 2.1.0-preview1: GDPR enhancements

$
0
0

2018 sees the introduction of the General Data Protection Regulation, an EU framework to allow EU citizens to control, correct and delete their data, no matter where in the word it is held. In ASP.NET Core 2.1 Preview 1 we’ve added some features to the ASP.NET Core templates to allow you to meet some of your GDPR obligations, as well as a cookie “consent” features to allow you to annotate your cookies and control whether they are sent to the user based on their consent to have such cookies delivered.

HTTPS

In order to help keep users’ personal data private, ASP.NET Core configures new projects to be served over HTTPS by default. You can read more about this feature in Improvements to using HTTPS.

Cookie Consent

When you create an ASP.NET Core application targeting version 2.1 and run it you will see a new banner on your home page,

Cookie Consent Bar

Cookie Consent Bar

This is the consent feature in action. This feature allows you to prompt a user to consent to your application creating “non-essential” cookies. Your application should have a privacy policy and an explanation of what the user is consenting to that conforms to your GDPR requirements. By default, clicking “Learn more” will navigate the user to /Privacy where you could publish the details about your app.
The banner itself is contained in the _CookieConsentPartial.cshtml shared view. If you open this file you can see some code showing how the user’s consent value is retrieved and how it can be updated. The current consent status is exposed as an HttpFeature, ITrackingConsentFeature. If a user consents to allowing the use of cookies a new cookie will be created by calling CreateConsentCookie() on the feature. The status of the user’s consent can be examined by the CanTrack property on the feature, however you don’t need to do this manually, instead you can use the IsEssential property on cookie options. For example

context.Response.Cookies.Append("Test", "Value", new CookieOptions { IsEssential = false });

would append a non-essential cookie to the response. If a user has not indicated their consent this cookie will not be appended to the response but will be silently dropped. Conversely marking a cookie as essential,

context.Response.Cookies.Append("Test", "Value", new CookieOptions { IsEssential = true });

will always create the cookie in the response, no matter the user’s consent status.

You can provide feedback on the cookie consent tracking feature at https://github.com/aspnet/Security/issues.

Data Control

The GDPR gives users the right to examine the data your application holds on it, edit the data and delete the data entirely from your application. Obviously, we cannot know what data you have, where it lives or how its all linked together but what we do know is what personal data a default ASP.NET Core Identity application holds and how to delete Identity users, so we can give you a starting point. When you create an ASP.NET Core application with Individual Authentication and the data stored in-app you might notice two new options in the user profile page, Download and Delete.

Default Data Control actions

Default Data Control actions

Download takes its data from ASP.NET Core Identity and creates a JSON file for download, delete does as you’d expect, it deletes the user. You will probably have extended the identity models or added new tables to your database which uses a user’s identity as a foreign key, so you will need to customize both these functions to match your own data structure and your own GDPR requirements, to do this you’ll need to override the view for each of these functions.

If you look at the code created in your application you will see that a lot of the old template code has vanished, this is because of the new “Identity UI as a library” feature. To override the functionality, you need to manually create the view as it would appear if ASP.NET Identity’s UI were not bundled into a library. For now, until tooling arrives, this is a manual process. The Download capability is contained in DownloadPersonalData.cshtml.cs and the Delete capability is in DeletePersonalData.cshtml.cs. You can see each of these files in the Identity UI GitHub repository. For example, to override the data in the download page you must create an Account Folder under Areas\Identity\Pages, then a Manage folder under the account folder and finally a DownloadPersonalData.cshtml and associated DownloadPersonalData.cshtml.cs.

For the cshtml file you can take the source from GitHub as a starting point, then add your own namespace, a using statement for Microsoft.AspNetCore.Identity.UI.Pages.Account.Manage.Internal and the instruction to wire up MVC Core Tag Helpers, for example if application namespace is WebApplication21Auth the .cshtml file would look like this:

Then for the corresponding .cs file you can take the default implementation from the source as a starting point for the OnPost implementation so your version might look like the following:

You can give feedback on the data control features of Identity at https://github.com/aspnet/Identity/issues.

Conclusion

These features should put you in a good starting position for the GDPR but remember the GDPR places a lot more requirements on your company and application than just the features we provide, including protection of data at rest, risk assessments and management, data breach reporting and so on. You should consult with a GDPR specialist to see what implications the regulation has for your company.

ASP.NET Core 2.1.0-preview1: Functional testing of MVC applications

$
0
0

For ASP.NET Core 2.1 we have created a new package, Microsoft.AspNetCore.Mvc.Testing, to help streamline in-memory end-to-end testing of MVC applications using TestServer.

This package takes care of some of the typical pitfalls when trying to test MVC applications using TestServer.

  • It copies the .deps file from your project into the test assembly bin folder.
  • It sets the content root the application's project root so that static files and views can be found.
  • It provides a class WebApplicationTestFixture<TStartup> that streamlines the bootstrapping of your app on TestServer.

Create a test project

To try out the new MVC test fixture, let's create an app and write an end-to-end in-memory test for the app.

First, create an app to test.

dotnet new razor -au Individual -o TestingMvc/src/TestingMvc

Add an xUnit based test project.

dotnet new xunit -o TestingMvc/test/TestingMvc.Tests

Create a solution file and add the projects to the solution.

cd TestingMvc
dotnet new sln
dotnet sln add src/TestingMvc/TestingMvc.csproj
dotnet sln add test/TestingMvc.Tests/TestingMvc.Tests.csproj

Add a reference from the test project to the app we're going to test.

dotnet add test/TestingMvc.Tests/TestingMvc.Tests.csproj reference src/TestingMvc/TestingMvc.csproj

Add a reference to the Microsoft.AspNetCore.Mvc.Testing package.

dotnet add test/TestingMvc.Tests/TestingMvc.Tests.csproj package Microsoft.AspNetCore.Mvc.Testing -v 2.1.0-preview1-final

In the test project create a test using the WebApplicationTestFixture<TStartup> class that retrieves the home page for the app. The test fixture sets up an HttpClient for you that allows you to invoke your app in-memory.

using Xunit;

namespace TestingMvc.Tests
{
    public class TestingMvcFunctionalTests : IClassFixture<WebApplicationTestFixture<Startup>>
    {
        public MyApplicationFunctionalTests(WebApplicationTestFixture<Startup> fixture)
        {
            Client = fixture.Client;
        }

        public HttpClient Client { get; }

        [Fact]
        public async Task GetHomePage()
        {
            // Arrange & Act
            var response = await Client.GetAsync("/");

            // Assert
            Assert.Equal(HttpStatusCodes.OK, response.StatusCode);
        }
    }
}

To correctly invoke your app the test fixture tries to find a static method on the entry point class (typically Program) of the assembly containing the Startup class with the following signature:

public static IWebHostBuilder CreateWebHostBuilder(string [] args)

Fortunately the built-in project templates are already setup this way:

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

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

If you don't have the Program.CreateWebHostBuilder method the text fixture won't be able to initialize your app correctly for testing. Instead you can configure the WebHostBuilder yourself by overriding CreateWebHostBuilder on WebApplicationTestFixture<TStartup>.

Specifying the app content root

The test fixture will also attempt to guess the content root of the app under test. By convention the test fixture assumes the app content root is at <<SolutionFolder>>/<<AppAssemblyName>>. For example, based on the folder structure defined below, the content root of the application is defined as /work/MyApp.

/work
    /MyApp.sln
    /MyApp/MyApp.csproj
    /MyApp.Tests/MyApp.Tests.csproj

Because we are using a different layout for our projects we need to inherit from WebApplicationTestFixture and pass in the relative path from the solution to the app under test when calling the base constructor. In a future preview we plan to make configuration of the content root unnecessary, but for now this explicit configuration is required for our solution layout.

public class TestingMvcTestFixture<TStartup> : WebApplicationTestFixture<TStartup> where TStartup : class
{
    public TestingMvcTestFixture()
        : base("src/TestingMvc") { }
}

Update the test class to use the derived test fixture.

public class TestingMvcFunctionalTests : IClassFixture<TestingMvcTestFixture<Startup>>
{
    public TestingMvcFunctionalTests(TestingMvcTestFixture<Startup> fixture)
    {
        Client = fixture.Client;
    }

    public HttpClient Client { get; }

    [Fact]
    public async Task GetHomePage()
    {
        // Arrange & Act
        var response = await Client.GetAsync("/");

        // Assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}

For some end-to-end in-memory tests to work properly, shadow copying needs to be disabled in your test framework of choice, as it causes the tests to execute in a different folder than the output folder. For instructions on how to do this with xUnit see https://xunit.github.io/docs/configuring-with-json.html.

Run the test

Run the test by running dotnet test from the TestingMvc.Tests project directory. It should fail because the HTTP response is a temporary redirect instead of a 200 OK. This is because the app has HTTPS redirection middleware in its pipeline (see Improvements for using HTTPS) and base address setup by the test fixture is an HTTP address ("http://localhost"). The HttpClient by default doesn't follow these redirects. In a future preview we will update the text fixture to configure the HttpClient to follow redirects and also handle cookies. But at least now we know the test is successfully running the app's pipeline.

This test was intended to make simple GET request to the app's home, not test the HTTPS redirect logic, so let's reconfigure the HttpClient to use an HTTPS base address instead.

public TestingMvcFunctionalTests(TestingMvcTestFixture<Startup> fixture)
{
    Client = fixture.Client;
    Client.BaseAddress = new Uri("https://localhost");
}

Rerun the test and it should now pass.

Starting test execution, please wait...
[xUnit.net 00:00:01.1767971]   Discovering: TestingMvc.Tests
[xUnit.net 00:00:01.2466823]   Discovered:  TestingMvc.Tests
[xUnit.net 00:00:01.2543165]   Starting:    TestingMvc.Tests
[xUnit.net 00:00:09.3860248]   Finished:    TestingMvc.Tests

Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.

Summary

We hope the new MVC test fixture in ASP.NET Core 2.1 will make it easier to reliably test your MVC applications. Please give it a try and let us know what you think on GitHub.

Announcing Preview 1 of ASP.NET MVC 5.2.5, Web API 5.2.5, and Web Pages 3.2.5

$
0
0

Today we released Preview 1 of ASP.NET MVC 5.2.5, Web API 5.2.5, and Web Pages 3.2.5 on NuGet. This is a patch release that contains only bug fixes. You can find the full list of bug fixes for this release in the release notes.

To update an existing project to use this preview release run the following commands from the NuGet Package Manager Console for each of the packages you wish to update:

Install-Package Microsoft.AspNet.Mvc -Version 5.2.5-preview1
Install-Package Microsoft.AspNet.WebApi -Version 5.2.5-preview1
Install-Package Microsoft.AspNet.WebPages -Version 3.2.5-preview1

Please try out Preview 1 of ASP.NET MVC 5.2.5, Web API 5.2.5, and Web Pages 3.2.5 and let us know what you think. Any feedback can be submitted as issues on GitHub. Assuming everything with this preview goes smoothly, we expect to ship a stable release of these packages in a few weeks.

Enjoy!

ASP.NET Core manageability and Application Insights improvements

$
0
0

There are many great investments on the ASP.NET Core 2.1 roadmap. These investments make ASP.NET Core applications easier to write, host, test, and make security and standards compliant. This blog post talks about areas of investments in manageability and monitoring space. It covers ASP.NET Core, .NET, and Application Insights SDK for ASP.NET Core features and spans beyond 2.1 milestone.

The main themes of manageability improvements across the application stack are:

  1. Distributed tracing
  2. Cross platform features parity
  3. Runtime awareness
  4. Ease of enablement
  5. App framework self-reporting

Let’s dig into the improvements made and the roadmap ahead in these areas.

Distributed tracing

ASP.NET Core 2.0 applications are distributed tracing aware. The context required to track a distributed trace is automatically created or read from incoming HTTP requests and forwarded along with any outgoing out-of-process calls. Collection of distributed trace details does NOT require application code change. No need to register a middleware or install an agent. You can check out the preview of end-to-end trace view as shown on a picture below and more distributed tracing scenarios in Azure Application Insights.

ASP.NET Core 2.0 was shipped with the support of incoming http requests and outgoing HttpClient requests monitoring. Recently support was extended for outgoing calls made via SqlClient for .NET Core, Azure Event Hub, and the Azure Service Bus SDKs. Libraries are instrumented with the DiagnosticSource callbacks. It makes distributed tracing easy to consume by any APM or diagnostics tool. More libraries plan to enable DiagnosticSource support to participate in distributed trace.

Application Insights SDK for ASP.NET Core 2.2.1 was shipped recently. It now automatically collects outgoing calls made using the libraries mentioned above.

We are also working with the community to standardize distributed tracing protocols. Accepted standard enables even wider adoption of distributed tracing. It also simplifies mixing components written in different languages as well as serverless cloud components in a single microservice environment. Our hope is that this standard will be in place for adoption by the next version of ASP.NET Core.

Cross platform features parity

ASP.NET Core applications may target two .NET versions – .NET Framework and .NET Core. They can run on Windows and Linux. Many efforts are directed to bring feature parity between these runtime environments.

There are framework investments for better manageability of ASP.NET Core application across runtime environments. For instance, System.Diagnostics.PerformanceCounter package was recently released. It allows application to collect Performance Counters from .NET Core applications running on Windows. This package was only available for apps compiled for .NET Framework environment before.

Low level manageability interfaces like Profiling API also getting to the feature parity on various runtime platforms.

Recently more Application Insights features were ported from .NET Framework version to .NET Core. Application Insights SDK for ASP.NET Core version 2.2.1 have live metrics support, hardened telemetry channel with more reliable data upload. And adaptive sampling feature to enable better control of telemetry volume and price.

We are excited to announce the public preview for Application Insights Profiler on ASP.NET core Linux web apps. Learn more at documentation page Profile ASP.NET Core Azure Linux Web Apps with Application Insights Profiler.

Runtime awareness

Variety of runtime platforms makes the job of monitoring tools harder. Application Insights SDK needs to be runtime aware. Team makes investments to natively understand platforms like Azure Web Apps or containers run by Kubernetes.

Ability to associate infrastructure telemetry with application insights is important. Correlating container CPU and number of running instances with the request load and reliability of an application allows to get a full picture of application behavior. It allows to find out the root cause of the problem faster and apply remediations curated to the runtime environment.

Ease of enablement

When time comes to manageability and diagnostics – the last thing you want to do is to redeploy an application to enable additional data collection. Especially when application is running in production. There are set of investments teams making to simplify enablement of manageability, monitoring and diagnostics settings.

Snapshot Debugger will be enabled by default for the ASP.NET Core applications running as Azure Web App.

Another aspect of easier onboarding is Application Insights SDK configuration story ironing. Today Application Insights predefine many monitoring settings. Those settings work great for majority of application. However, changing of them is not always easy and intuitive when needed.

ASP.NET Core has many built-in self-reporting capabilities. Exposing them in a form that is easy to consume across runtime platforms is one of the goals of .NET team. There is a proposal to expose many of manageability settings and monitoring data via http callbacks.

App framework self-reporting

ASP.NET framework improves manageability by exposing more internal app metrics. As a result of this discussion these metrics are exposed in a platform-independent way via EventCounters. Metrics exposed via EventCounters are available for in-process and out-of-process consumption.

There is another example of a great improvement made in .NET for better manageability and monitoring. Stack traces became way more readable in .NET 2.1. This blog post outlines few improvements made recently in this area.

Summary

There are many new manageability and monitoring features coming up. Some of them committed, some planned, and some are just proposals. You can help prioritizing features by commenting on GitHub for ASP.NET, Application Insights and .NET. You can also get live updates and participate in the conversation by watching the weekly ASP.NET Community Standup at https://live.asp.net. Your feedback is welcome and appreciated!


Get started building .NET web apps that run in the browser with Blazor

$
0
0

Today we released our first public preview of Blazor, a new experimental .NET web framework using C#/Razor and HTML that runs in the browser with WebAssembly. Blazor enables full stack web development with the stability, consistency, and productivity of .NET. While this release is alpha quality and should not be used in production, the code for this release was written from the ground up with an eye towards building a production quality web UI framework.

In this release we've laid the ground work for the Blazor component model and added other foundational features, like routing, dependency injection, and JavaScript interop. We've also been working on the tooling experience so that you get great IntelliSense and completions in the Razor editor. Other features that have been demonstrated previously in prototype form, like live reload, debugging, and prerendering, have not been implemented yet, but are planned for future preview updates. Even so, there is plenty in this release for folks to start kicking the tires and giving feedback on the current direction. For additional details on what's included in this release and known issue please see the release notes.

Let's get started!

Help & feedback

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 let us know!

  • File issues on GitHub for any problems you run into or to make suggestions for improvements.
  • Chat with us and the Blazor community on Gitter if you get stuck or to share how blazor is working for you.

Also, after you've tried out Blazor for a while please 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

Get started

To get setup with Blazor:

  1. Install the .NET Core 2.1 Preview 1 SDK.
  2. Install the latest preview of Visual Studio 2017 (15.7) with the Web development workload.
    • Note: You can install Visual Studio previews side-by-side with an existing Visual Studio installation without impacting your existing development environment.
  3. Install the ASP.NET Core Blazor Language Services extension from the Visual Studio Marketplace.

To create your first project from Visual Studio:

  1. Select File -> New Project -> Web -> ASP.NET Core Web Application
  2. Make sure .NET Core and ASP.NET Core 2.0 are selected at the top.
  3. Pick the Blazor template

    New Blazor app dialog

  4. Press Ctrl-F5 to run the app without the debugger. Running with the debugger (F5) is not supported at this time.

If you're not using Visual Studio you can install the Blazor templates from the command-line:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates
dotnet new blazor -o BlazorApp1
cd BlazorApp1
dotnet run

Congrats! You just ran your first Blazor app!

Building components

When you browse to the app, you'll see that it has three prebuilt pages: a home page, a counter page, and a fetch data page:

Blazor app home page

These three pages are implemented by the three Razor files in the Pages folder: Index.cshtml, Counter.cshtml, FetchData.cshtml. Each of these files implements a Blazor component. The home page only contains static markup, but the counter and fetch data pages contain C# logic that will get compiled and executed client-side in the browser.

The counter page has a button that increments a count each time you press it without a page refresh.

Blazor app home page

Normally this kind of client-side behavior would be handled in JavaScript, but here it's implemented in C# and .NET by the Counter component. Take a look at the implementation of the Counter component in the Counter.cshtml file:

@page "/counter"
<h1>Counter</h1>

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

<button @onclick(IncrementCount)>Click me</button>

@functions {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

Each Razor (.cshtml) file defines a Blazor component. A Blazor component is a .NET class that defines a reusable piece of web UI. The UI for the Counter component is defined using normal HTML. Dynamic rendering logic (loops, conditionals, expressions, etc.) can be added using Razor syntax. The HTML markup and rendering logic are converted into a component class at build time. The name of the generated .NET class matches the name of the file.

Members of the component class are defined in a @functions block. In the @functions block you can specify component state (properties, fields) as well as methods for event handling or for defining other component logic. These members can then be used as part of the component's rendering logic and for handling events.

Note: Defining components in a single Razor file is typical, but in a future update you will also be able to define component logic in a code behind file.

Each time an event occurs on a component (like the onclick event in the Counter component), that component regenerates its render tree. Blazor will then compare the new render tree against the previous one and apply any modifications to the browser DOM.

Routing to components

The @page directive at the top of the Counter.cshtml file specifies that this component is a page to which requests can be routed. Specifically, the Counter component will handle requests sent to /counter. Without the @page directive the component would not handle any routed request, but it could still be used by other components.

Routing requests to specific components is handled by the Router component, which is used by the root App component in App.cshtml:

<!--
    Configuring this here is temporary. Later we'll move the app config
    into Program.cs, and it won't be necessary to specify AppAssembly.
-->
<Router AppAssembly=typeof(Program).Assembly />

Using components

Once you define a component it can be used to implement other components. For example, we can add a Counter component to the home page of the app, like this:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

<Counter />

If you build and run the app again (live reload coming soon!) you should now see a separate instance of the Counter component on the home page.

Blazor home page with counter

Component parameters

Components can also have parameters, which you define using public properties on the component class. Let's update the Counter component to have an IncrementAmount property that defaults to 1, but that we can change to something different.

@page "/counter"
<h1>Counter</h1>

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

<button @onclick(IncrementCount)>Click me</button>

@functions {
    int currentCount = 0;

    public int IncrementAmount { get; set; } = 1;

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

The component parameters can be set as attributes on the component tag. In the home page change the increment amount for the counter to 10.

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

<Counter IncrementAmount="10" />

When you build and run the app the counter on the home page now increments by 10, while the counter page still increments by 1.

Blazor count by ten

Layouts

The layout for the app is specified using the @layout directive in _ViewImports.cshtml in the Pages folder.

@layout MainLayout

Layouts in Blazor are also also built as components. In our app the MainLayout component in Shared/MainLayout.cshtml defines the app layout.

@implements ILayoutComponent

<div class='container-fluid'>
    <div class='row'>
        <div class='col-sm-3'>
            <NavMenu />
        </div>
        <div class='col-sm-9'>
            @Body
        </div>
    </div>
</div>

@functions {
    public RenderFragment Body { get; set; }
}

Layout components implement ILayoutComponent. In Razor syntax interfaces can be implemented using the @implements directive. The Body property on the ILayoutComponent interface is used by the layout component to specify where the body content should be rendered. In our app the MainLayout component adds a NavMenu component and then renders the body in the main section of the page.

The NavMenu component is implemented in Shared/NavMenu.cshtml and creates a Bootstrap nav bar. The nav links are generated using the built-in NavLink component, which generates an anchor tag with an active CSS class if the current page matches the specified href.

The root component

The root component for the app is specified in the app's Program.Main entry point defined in Program.cs. This is also where you configure services with the service provider for the app.

class Program
{
    static void Main(string[] args)
    {
        var serviceProvider = new BrowserServiceProvider(configure =>
        {
            // Add any custom services here
        });

        new BrowserRenderer(serviceProvider).AddComponent<App>("app");
    }
}

The DOM element selector argument determines where the root component will get rendered. In our case, the app element in index.html is used.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <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> <!--Root component goes here-->

    <script src="css/bootstrap/bootstrap-native.min.js"></script>
    <script type="blazor-boot"></script>
</body>
</html>

Bootstrapping the runtime

At build-time the blazor-boot script tag is replaced with a bootstrapping script that handles starting the .NET runtime and executing the app's entry point. You can see the updated script tag using the browser developer tools.

<script src="_framework/blazor.js" main="BlazorApp1.dll" entrypoint="BlazorApp1.Program::Main" references="Microsoft.AspNetCore.Blazor.dll,netstandard.dll,..."></script>

As part of the build Blazor will analyze which code paths are being used from the referenced assemblies and then remove unused assemblies and code.

Dependency injection

Services registered with the app's service provider are available to components via dependency injection. You can inject services into a component using constructor injection or using the @inject directive. The latter is how an HttpClient is injected into the FetchData component.

@page "/fetchdata"
@inject HttpClient Http

The FetchData component uses the injected HttpClient to retrieve some JSON from the server when the component is initialized.

@functions {
    WeatherForecast[] forecasts;

    protected override async Task OnInitAsync()
    {
        forecasts = await Http.GetJsonAsync<WeatherForecast[]>("/sample-data/weather.json");
    }

    class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureC { get; set; }
        public int TemperatureF { get; set; }
        public string Summary { get; set; }
    }
}

The data is deserialized into the forecasts C# variable as an array of WeatherForecast objects and then used to render the weather table.

<table class='table'>
    <thead>
        <tr>
            <th>Date</th>
            <th>Temp. (C)</th>
            <th>Temp. (F)</th>
            <th>Summary</th>
        </tr>
    </thead>
    <tbody>
        @foreach (var forecast in forecasts)
        {
            <tr>
                <td>@forecast.Date.ToShortDateString()</td>
                <td>@forecast.TemperatureC</td>
                <td>@forecast.TemperatureF</td>
                <td>@forecast.Summary</td>
            </tr>
        }
    </tbody>
</table>

Hosting with ASP.NET Core

The Blazor template creates a client-side web application that can be used with any back end, but by hosting your Blazor application with ASP.NET Core you can do full stack web development with .NET.

The "Blazor (ASP.NET Core Hosted)" project template creates a solution with three projects for you: 1. a Blazor client project, 2. an ASP.NET Core server project, and 3. a shared .NET Standard class library project.

To host the Blazor app in ASP.NET Core the server project has a reference to the client project. Blazor-specific middleware makes the Blazor client app available to browsers.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseResponseCompression();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseMvc(routes =>
    {
        routes.MapRoute(name: "default", template: "{controller}/{action}/{id?}");
    });

    app.UseBlazor<Client.Program>();
}

In the standalone Blazor app the weather forecast data was a static JSON file, but in the hosted project the SampleDataController provides the weather data Using ASP.NET Core.

The shared class library project is referenced by both the Blazor client project and the ASP.NET Core server project, so that code can be shared between the two projects. This is a great place to put your domain types. For example, the WeatherForecast class is used by the Web API in the ASP.NET Core project for serialization and in the Blazor project for deserialization.

Build a todo list

Let's add a new page to our app that implements a simple todo list. Add a Pages/Todo.cshtml file to the project. We don't have a Blazor component item template in Visual Studio quite yet, but you can use the Razor View item template as a substitute. Replace the content of the file with some initial markup:

@page "/todo"

<h1>Todo</h1>

Now add the todo list page to the nav bar. Update Shared/Navbar.cshtml to add a nav link for the todo list.

<li>
    <NavLink href="/todo">
        <span class='glyphicon glyphicon-th-list'></span> Todo
    </NavLink>
</li>

Build and run the app. You should now see the new todo page.

Blazor todo start

Add a class to represent your todo items.

public class TodoItem
{
    public string Title { get; set; }
    public bool IsDone { get; set; }
}

The Todo component will maintain the state of the todo list. In the Todo component add a field for the todos in a @functions block and a foreach loop to render them.

@page "/todo"

<h1>Todo</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@functions {
    IList<TodoItem> todos = new List<TodoItem>();
}

Now we need some UI for adding todos to the list. Add a text input and a button at the bottom of the list.

@page "/todo"

<h1>Todo</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button>Add todo</button>

@functions {
    IList<TodoItem> todos = new List<TodoItem>();
}

Nothing happens yet when we click the "Add todo" button, because we haven't wired up an event handler. Add an AddTodo method to the Todo component and register it for button click using the @onclick attribute.

@page "/todo"

<h1>Todo</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button @onclick(AddTodo)>Add todo</button>

@functions {
    IList<TodoItem> todos = new List<TodoItem>();

    void AddTodo()
    {
        // Todo: Add the todo
    }
}

The AddTodo method will now get called every time the button is clicked. To get the title of the new todo item add a newTodo string field and bind it to the value of the text input using the @bind attribute. This sets up a two-way bind. We can now update the AddTodo method to add the TodoItem with the specified title to the list. Don't forget to clear the value of the text input by setting newTodo to an empty string.

@page "/todo"

<h1>Todo</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind(newTodo) />
<button @onclick(AddTodo)>Add todo</button>

@functions {
    IList<TodoItem> todos = new List<TodoItem>();
    string newTodo;

    void AddTodo()
    {
        if (!String.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = "";
        }
    }
}

Lastly, what's a todo list without check boxes? And while we're at it we can make the title text for each todo item editable as well. Add a checkbox input and text input for each todo item and bind their values to the Title and IsDone properties respectively. To verify that these values are being bound, add a count in the header that shows the number of todo items that are not yet done.

@page "/todo"

<h1>Todo (@todos.Where(todo => !todo.IsDone).Count())</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind(todo.IsDone) />
            <input @bind(todo.Title) />
        </li>
    }
</ul>

<input placeholder="Something todo" @bind(newTodo) />
<button @onclick(AddTodo)>Add todo</button>

@functions {
    IList<TodoItem> todos = new List<TodoItem>();
    string newTodo;

    void AddTodo()
    {
        if (!String.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = "";
        }
    }
}

Build and run the app and try adding some todo items.

Finished Blazor todo list

Publishing and deployment

Now let's publish our Blazor app to Azure. Right click on the project and select Publish (if you're using the ASP.NET Core hosted template make sure you publish the server project). In the "Pick a publish target" dialog select "App Service" and "Create New".

Pick a publish target

In the "Create App Service" dialog pick a name for the application and select the subscription, resource group, and hosting plan that you want to use. Tap "Create" to create the app service and publish the app.

Create app service

Your app should now be running in Azure.

Blazor on Azure

You can mark that todo item to build your first Blazor app as done! Nice job!

For a more involved Blazor sample app check out the Flight Finder sample on GitHub.

Blazor Flight Finder

Summary

This is the first preview release of Blazor. Already you can get started building component-based web apps that run in the browser with .NET. We invite you to try out Blazor today and let us know what you think about the experience so far. You can file issues on Github, take our in-product survey, and chat with us on Gitter. But this is just the beginning! We have many new features and improvements planned for future updates. We hope you enjoy trying out this initial release and we look forward to sharing new improvements with you in the near future.

ASP.NET Core 2.1.0-preview2 now available

$
0
0

Today we’re very happy to announce that the second preview of the next minor release of ASP.NET Core and .NET Core is now available for you to try out. This second preview includes many refinements based on feedback we received from the first preview we released back in February.

You can read about .NET Core 2.1.0-preview2 over on their blog.

You can also read about Entity Framework Core 2.1.0-preview2 on their blog.

How do I get it?

You can download the new .NET Core SDK for 2.1.0-preview2 (which includes ASP.NET Core 2.1.0-preview2) from https://www.microsoft.com/net/download/dotnet-core/sdk-2.1.300-preview2

Visual Studio 2017 version requirements

Customers using Visual Studio 2017 should also install (in addition to the SDK above) and use the Preview channel (15.7 Preview 3 at the time of writing) when working with .NET Core and ASP.NET Core 2.1 projects. .NET Core 2.1 projects require Visual Studio 2017 15.7 or greater.

Impact to machines

Please note that given this is a preview release there are likely to be known issues and as-yet-to-be-discovered bugs. While .NET Core SDK and runtime installs are side-by-side on your machine, your default SDK will become the latest version, which in this case will be the preview. 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.

Already published applications running on earlier versions of .NET Core and ASP.NET Core shouldn’t be impacted by installing the preview. That said, we don’t recommend installing previews on machines running critical workloads.

Announcements and release notes

You can see all the announcements published pertaining to this release at https://github.com/aspnet/Announcements/issues?q=is%3Aopen+is%3Aissue+milestone%3A2.1.0-preview2

Release notes, including known issues, are available at https://github.com/aspnet/Home/releases/tag/2.1.0-preview2

Giving feedback

The main purpose of providing previews like this is to solicit feedback from customers such that we can refine and improve the changes in time for the final release. We intend to ship a release candidate in about a month (with “go-live” license and support) before the final RTW release.

Please provide feedback by logging issues in the appropriate repository at https://github.com/aspnet or https://github.com/dotnet. The posts on specific topics above will provide direct links to the most appropriate place to log issues for the features detailed.

New features

You can see a summary of the new features planned in 2.1 in the roadmap post we published previously.

Following are details of additions and changes in preview2 itself.

Improvements to Razor UI libraries

New in ASP.NET Core 2.1 is support for building Razor UI in class libraries. In Preview 2 we’ve made various improvements to simplify authoring Razor UI in class libraries through the introduction of the new Razor SDK.

To create a Razor UI class library, start with a .NET Standard class library and then update the SDK in the .csproj file to be Microsoft.NET.SDK.Razor. The Razor SDK adds the necessary build targets and properties so that Razor files can be included in the build.

To create your own Razor UI class library:

  1. Create a .NET Standard class library
    dotnet new classlib -o ClassLibrary1
    
  2. Add a reference from the class library to Microsoft.AspNetCore.Mvc
    dotnet add ClassLibrary1 package Microsoft.AspNetCore.Mvc -v 2.1.0-preview2-final
    
  3. Open ClassLibrary1.csproj and change the SDK to be Microsoft.NET.SDK.Razor
    <Project Sdk="Microsoft.NET.Sdk.Razor">
    
      <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.0-preview2-final" />
      </ItemGroup>
    
    </Project>
  4. Add a Razor page and a view imports file to the class library
    dotnet new page -n Test -na ClassLibrary1.Pages -o ClassLibrary1/Pages
    dotnet new viewimports -na ClassLibrary1.Pages -o ClassLibrary1/Pages
    
  5. Update the Razor page to add some markup
    @page
    
    <h1>Hello from a Razor UI class library!</h1>
  6. Build the class library to ensure there are no build errors
    dotnet build ClassLibrary1
    

    In the build output you should see both ClassLibrary1.dll and ClassLibrary1.Views.dll, where the latter contains the compiled Razor content.

Now let’s use our Razor UI library from an ASP.NET Core web app.

  1. Create a ASP.NET Core Web Application
    dotnet new razor -o WebApplication1
    
  2. Create a solution file and add both projects to the solution
    dotnet new sln
    dotnet sln add WebApplication1
    dotnet sln add ClassLibrary1
    
  3. Add a reference from the web application to the class library
    dotnet add WebApplication1 reference ClassLibrary1
    
  4. Build and run the web app
    cd WebApplication1
    dotnet run
    
  5. Browse to /test to see your page from your Razor UI class libraryRazor UI class library

Looks great! Now we can package up our Razor UI class library and share it with others.

  1. Create a package for the Razor UI class library
    cd ..
    dotnet pack ClassLibrary1
    
  2. Create a new web app and add a package reference to our Razor UI class library package
    dotnet new razor -o WebApplication2
    dotnet add WebApplication2 package ClassLibrary1 --source <current path>/ClassLibrary1/bin/Debug
    
  3. Run the new app with the package reference
    cd WebApplication2
    dotnet run
    
  4. Browse to /test for the new app to see that your package is getting used.Razor UI class library package

Publish your package to NuGet to share your handiwork with everyone.

Razor compilation on build

Razor compilation is now part of every build. This means that Razor compilation issues are caught at design time instead of when the app is first run. Compiling the Razor views and pages also significantly speeds up startup time. And even though your view and pages are built up front, you can still modify your Razor files at runtime and see them updated without having to restart the app.

Scaffold identity into an existing project

The latest preview of Visual Studio 2017 (15.7 Preview 3) supports scaffolding identity into an existing application and overriding specific pages from the default identity UI.

To scaffold identity into an existing application:

  1. Right-click on the project in the solution explorer and select Add -> New Scaffolded Item...
  2. Select the Identity scaffolder and click Add.Add Scaffold Identity
  3. The Add Identity dialog appears. Leave the layout unspecified. Check the checkbox in the override file list for “LoginPartial”. Also click the “+” button to create a new data context class and a custom identity user class. Click Add to run the identity scaffolder.Add default IdentityThe scaffolder will add an Identity area to your application that configures identity and also will update the layout to include the login partial.
  4. Update the Configure method in Startup.cs to add the database error page when in development and also the authentication middleware before invoking MVC.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }
    
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
    
        app.UseAuthentication();
    
        app.UseMvc();
    }
  5. The generated _ViewStart.cshtml in this preview release contains an unfortunate typo in the specified layout path. Fixup the layout path to be /Pages/Shared/_Layout.cshtml. This will be fixed in the next release.
  6. Select Tools -> NuGet Package Manager -> Package Manager Console and run the following commands to add an EF migration and create the database.
    Add-Migration Initial
    Update-Database
    
  7. Build and run the application. You should now be able to register and login users.Web app login

Customize default Identity UI

The identity scaffolder can also scaffold individual pages to override the default identity UI. For example, you can use a custom user type and update the identity UI to add additional user properties.

  1. In the solution explorer right-click on the project you added Identity to in the previous section and select Add -> New Scaffolded Item...
  2. Select the Identity scaffolder and click Add.Add Scaffold Identity
  3. The Add Identity dialog appears. Again leave the layout unspecified. Check the checkbox for the Account\Manage\Index file. For the data context select the data context we created in the previous section. Click Add to run the identity scaffolder.Override Manage
  4. Fixup the layout path in _ViewStart.cshtml as we did previously.
  5. Open the generated /Areas/Identity/Pages/Account/Manage/Index.cshtml.cs file and replace references IdentityUser with your custom user type (ScaffoldIdentityWebAppUser). This manual edit is necessary in this preview, but will be handled by the identity scaffolder in a future update.
  6. Update ScaffoldIdentityWebAppUser to add an Age property.
        public class ScaffoldIdentityWebAppUser : IdentityUser
        {
            public int Age { get; set; }
        }
  7. Update the InputModel in /Areas/Identity/Pages/Account/Manage/Index.cshtml.cs to add a new Age property.
    public class InputModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; }
    
        [Phone]
        [Display(Name = "Phone number")]
        public string PhoneNumber { get; set; }
        
        [Range(0, 120)]
        public int Age { get; set; }
    }
  8. Update /Areas/Identity/Pages/Account/Manage/Index.cshtml to add a field for setting the Age property. You can the field below the existing phone number field.
    <div class="form-group">
        <label asp-for="Input.Age"></label>
        <input asp-for="Input.Age" class="form-control" />
        <span asp-validation-for="Input.Age" class="text-danger"></span>
    </div>
  9. Update the OnPostAsync method in /Areas/Identity/Pages/Account/Manage/Index.cshtml.cs to save the user’s age to the database:
    if (Input.Age >= 0 && Input.Age < 120)
    {
        user.Age = Input.Age;
        await _userManager.UpdateAsync(user);
    }
  10. Update the OnGetAsync method in to initialize the InputModel with the user’s age from the database:
    Input = new InputModel
    {
        Email = user.Email,
        PhoneNumber = user.PhoneNumber,
        Age = user.Age
    };
  11. Select Tools -> NuGet Package Manager -> Package Manager Console and run the following commands to add an EF migration and update the database.
    Add-Migration UserAge
    Update-Database
    
  12. Build and run the app. Register a user and then set the user’s age on the manage page:Web app manage

Improvements to [ApiController] parameter binding

Applying [ApiController] to your controller sets up convenient conventions for how parameters get bound to request data. In Preview 2 we’ve made a number of improvements to how these conventions work based on feedback:

  • [FromBody] will no longer be inferred for complex types with specific semantics, like CancellationToken
  • Multiple [FromBody] parameters will result in an exception
  • When there are multiple routes for an action parameters that match any route value will be considered [FromRoute]

Provide constructed model type to the partial tag helper

The partial tag helper now supports passing a model instance through the new model attribute.

<partial name="MovieView" model='new Movie() { Name="Ghostsmashers" }' />

The asp-for attribute was also renamed to for.

Analyzer to warn about using Html.Partial usage

Starting in this preview, calls to Html.Partial will result in an analyzer warning due to the potential for deadlocks.

Html.Partial warning

Calls to @Html.Partial(...) should be replaced by @await Html.PartialAsync(...) or use the partial tag helper instead (<partial name="..." />).

Option to opt-out of HTTPS

HTTPS is enabled by default in ASP.NET Core 2.1 and the out of the box templates include support for handling HTTPS redirects and HSTS. But in some backend services where HTTPS is being handled externally at the edge using HTTPS at each node is not needed.

In Preview 2 you can disable HTTPS when creating new ASP.NET Core projects by passing the --no-https option at the command-line. In Visual Studio this option is surfaced from the new ASP.NET Core Web Application dialog.

Disable HTTPS

Razor Pages handling of HEAD requests

Razor Pages will now fall back to calling a matching GET page handler if no HEAD page handler is defined.

Updated to Json.NET 11

We’ve updated to Json.NET 11 to benefit from the latest Json.NET features and improvements.

Added Web API Client to ASP.NET Core meta-packages

The Web API Client is now included by the ASP.NET Core meta-packages for your convenience. This package provides convenient methods for handling formatting and deserialization when calling web APIs.

ViewData backed properties

Properties decorated with [ViewData] on controllers, page models, and Razor Pages provide a convenient way to add data that can be read by views and pages.

For example, to specify the title for a page and have it show up in the page layout you can define a property on your page model that is decorated with [ViewData]:

public class AboutModel : PageModel
{
    [ViewData]
    public string Title { get; } = "About";
}

The title can be accessed from the about page as a model property:

@page
@model AboutModel

<h2>@Model.Title</h2>

Then, in the layout, the title can be read from the ViewData dictionary:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApplication2</title>
...

Prebuilt UI libraries for Azure AD and Azure AD B2C

The UI and components required for setting up authentication with Azure AD or Azure AD B2C are now available in this preview as prebuilt packages:

These packages can be used to setup authentication with Azure AD or Azure AD B2C in any project.

Updates to launchSettings.json

The applicationUrl property in launchSettings.json can now be used to specify a semicolon separated list of server URLs.

"WebApplication1": {
  "commandName": "Project",
  "launchBrowser": true,
  "applicationUrl": "https://localhost:5001;http://localhost:5000",
  "environmentVariables": {
    "ASPNETCORE_ENVIRONMENT": "Development"
  }
}

Deprecating aspnetcore and aspnetcore-build Docker images

Starting with .NET Core 2.1.0-preview2, we intend to migrate from using the microsoft/aspnetcore-build and microsoft/aspnetcore Docker repos to the microsoft/dotnet Docker repo. We will continue to ship patches and security fixes for the existing aspnetcore images but any new images for 2.1 and higher will be pushed to microsoft/dotnet.

Dockerfiles using microsoft/aspnetcore: should change to microsoft/dotnet:-aspnetcore-runtime.

Dockerfiles using microsoft/aspnetcore-build that do not require Node should change to microsoft/dotnet:-sdk.

Dockerfiles using microsoft/aspnetcore-build that require Node will need to handle that in their own images, either with a multi-stage build or by installing Node themselves.

For more details on the change, including some example Dockerfiles and a link to a discussion issue, you can see the announcement here: https://github.com/aspnet/Announcements/issues/298

Kestrel support for SNI

Server Name Indication (SNI) can be used to allow hosting multiple domains on the same IP address and port. It does this by sending the expected host name in the TLS handshake so that the server can provide the correct certificate. Kestrel now supports this via the ServerCertificateSelector callback. This is invoked once per connection to allow you to inspect the host name and select the most appropriate certificate.

WebHost.CreateDefaultBuilder()
    .UseKestrel((context, options) =>
    {
        options.ListenAnyIP(5005, listenOptions =>
        {
            listenOptions.UseHttps(httpsOptions =>
            {
                var localhostCert = CertificateLoader.LoadFromStoreCert("localhost", "My", StoreLocation.CurrentUser, allowInvalid: true);
                var exampleCert = CertificateLoader.LoadFromStoreCert("example.com", "My", StoreLocation.CurrentUser, allowInvalid: true);
                var subExampleCert = CertificateLoader.LoadFromStoreCert("sub.example.com", "My", StoreLocation.CurrentUser, allowInvalid: true);
                var certs = new Dictionary(StringComparer.OrdinalIgnoreCase);
                certs["localhost"] = localhostCert;
                certs["example.com"] = exampleCert;
                certs["sub.example.com"] = subExampleCert;

                httpsOptions.ServerCertificateSelector = (features, name) =>
                {
                    if (name != null && certs.TryGetValue(name, out var cert))
                    {
                        return cert;
                    }

                    return exampleCert;
                };
            });
        });
    });

SNI support requires running on netcoreapp2.1. On netcoreapp2.0 and net461 the callback will be invoked but the name will always be null. The name will also be null if the client did not provide this optional parameter.

HTTTPClient Factory and Polly

As we discussed in our Preview1 post on HttpClient factory, we had planned to provide a package that integrates Polly with HTTPClient factory. In Preview2 the majority of that integrations is now available. In order to try this out you need to add the Polly integration NuGet package Microsoft.Extensions.Http.Polly:

<ItemGroup>
 <PackageReference Include="Microsoft.AspNetCore.App" Version="2.1.0-preview2-final" />
 <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.1.0-preview2-final" />
</ItemGroup>

Then you can write code like the following:

services.AddHttpClient(client => client.BaseAddress = new Uri(Configuration["ValuesServiceUri"]))
        .AddTransientHttpErrorPolicy(policyBuilder => policyBuilder.Retry(2));

With this code we would automatically retry twice before failing any requests made using the ValuesClient, the ValuesClient here being the same as the one we showed in the Preview1 post. For more information on Polly and what policies are available, you can read the Polly docs here

The Polly.PolicyBuilder provided to AddTransientHttpErrorPolicy has been preconfigured to handle errors in the following categories:

  • Network failures (System.Net.Http.HttpRequestException)
  • HTTP 5XX status codes (server errors)
  • HTTP 408 status code (request timeout)

You can use the more general AddPolicyHandler method to add a Policy that handles different conditions. In general AddTransientHttpErrorPolicy is good for reactive policies (Retry, CircuitBreaker, Fallback), which we think are likely to be the most commonly used. However, the AddPollyHandler API can be used to add any Polly policy handling any conditions that you want.

The policy will be cached indefinitely per named client, which allows policies such as CircuitBreaker to function.

If you want to share a single Policy across multiple named clients then you should create a Policy and then pass it into multiple calls, for example:

var retryPolicy = Policy.Handle()
                        .OrResult(message => !message.IsSuccessStatusCode)
                        .WaitAndRetry(new[]
                        {
                           TimeSpan.FromSeconds(1),
                           TimeSpan.FromSeconds(2),
                           TimeSpan.FromSeconds(3)
                         });

services.AddHttpClient()
        .AddPolicyHandler(retryPolicy);

services.AddHttpClient("otherClient")
        .AddPolicyHandler(retryPolicy);

With this code we will Retry all HttpRequestExceptions and non success status codes 3 times, with a slightly longer pause between each try. We could change to an exponential backoff retry policy by changing the code slightly:

var retryPolicy = Policy.Handle()
                        .OrResult(message => !message.IsSuccessStatusCode)
                        .WaitAndRetry(3, retryAttempt => 
                          TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) 
                        );

For documentation on Polly and the policies available you can read the Polly wiki.

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

Follow these steps to migrate an existing ASP.NET Core 2.0.x project to 2.1.0-preview2:

  1. Open the project’s CSPROJ file and change the value of the <TargetFramework> element to netcoreapp2.1
    • Projects targeting .NET Framework rather than .NET Core, e.g. net471, don’t need to do this
  2. In the same file, update the versions of the various <PackageReference> elements for any Microsoft.AspNetCore, Microsoft.Extensions, and Microsoft.EntityFrameworkCore packages to 2.1.0-preview2-final
  3. In the same file, remove any references to <DotNetCliToolReference> elements for any Microsoft.AspNetCore, Microsoft.VisualStudio, and Microsoft.EntityFrameworkCore packages. These tools are now deprecated and are replaced by global tools.
  4. In the same file, remove the <DotNetCliToolReference> elements for any Microsoft.AspNetCore packages. These have been replaced by global tools.

That should be enough to get the project building and running against 2.1.0-preview2. The following steps will change your project to use new code-based idioms that are recommended in 2.1

  1. Open the Program.cs file
  2. Rename the BuildWebHost method to CreateWebHostBuilder, change its return type to IWebHostBuilder, and remove the call to .Build() in its body
  3. Update the call in Main to call the renamed CreateWebHostBuilder method like so: CreateWebHostBuilder(args).Build().Run();
  4. Open the Startup.cs file
  5. In the ConfigureServices method, change the call to add MVC services to set the compatibility version to 2.1 like so: services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
  6. In the Configure method, add a call to add the HSTS middleware after the exception handler middleware: app.UseHsts();
  7. Staying in the Configure method, add a call to add the HTTPS redirection middleware before the static files middleware: app.UseHttpsRedirection();
  8. Open the project propery pages (right-mouse click on project in Visual Studio Solution Explorer and select “Properties”)
  9. Open the “Debug” tab and in the IIS Express profile, check the “Enable SSL” checkbox and save the changes

    Note that some projects might require more steps depending on the options selected when the project was created, or packages added since. You might like to try creating a new project targeting 2.1.0-preview2 (in Visual Studio or using dotnet new at the cmd line) with the same options to see what other things have changed.

    ASP.NET Core 2.1.0-preview2: Improvements to the Kestrel HTTP server

    $
    0
    0

    Change default transport to Sockets

    Building off the improvements to the managed sockets implementation in .NET Core we have changed the default transport in Kestrel from libuv to sockets. As a consequence, the Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv package is no longer part of the Microsoft.AspNetCore.App metapackage.

    How to switch back to libuv

    To continue using libuv as your transport, you will need to add reference to the libuv package and modify your application to use libuv as it’s transport. Alternatively, you can reference the Microsoft.AspNetCore.All metapackage which includes a transitive dependency on the libuv package.

    dotnet add package Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv -v 2.1.0-preview2-final
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseLibuv()
            .UseStartup<Startup>();

    SNI support

    Server Name Indication (SNI) is extension to the TLS protocol that allows clients to send the desired hostname unencrypted as part of the TLS handshake. As a consequence, you can host multiple domains on the same IP/Port and use the hostname to respond with the correct certificate. In 2.1.0-preview2, Kestrel has added a ServerCertificateSelector callback which is invoked once per connection to allow you select the right certificate. If you specify a ServerCertificateSelector, the selector will always take precedence over any specified server certificate.

    SNI support requires running on netcoreapp2.1. On netcoreapp2.0 and net461 the callback will be invoked but the name will always be null. The name will also be null if the client did not provide this optional parameter.

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseKestrel((context, options) =>
            {
                options.ListenAnyIP(5005, listenOptions =>
                {
                    listenOptions.UseHttps(httpsOptions =>
                    {
                        var localhostCert = CertificateLoader.LoadFromStoreCert("localhost", "My", StoreLocation.CurrentUser, allowInvalid: true);
                        var exampleCert = CertificateLoader.LoadFromStoreCert("example.com", "My", StoreLocation.CurrentUser, allowInvalid: true);
                        var subExampleCert = CertificateLoader.LoadFromStoreCert("sub.example.com", "My", StoreLocation.CurrentUser, allowInvalid: true);
                        var certs = new Dictionary<string, X509Certificate2>(StringComparer.OrdinalIgnoreCase);
                        certs["localhost"] = localhostCert;
                        certs["example.com"] = exampleCert;
                        certs["sub.example.com"] = subExampleCert;
    
                        httpsOptions.ServerCertificateSelector = (features, name) =>
                        {
                            if (name != null && certs.TryGetValue(name, out var cert))
                            {
                                return cert;
                            }
    
                           return exampleCert;
                        };
                    });
               });
            })
            .UseStartup<Startup>();

    Host filtering middleware

    While Kestrel supports configuration based on prefixes such as https://contoso.com:5000, it largely ignores the host name. Localhost is a special case used for binding to loopback addresses. Any host other than an explicit IP address binds to all public IP addresses. None of this information is used to validate request Host headers. In 2.1.0-preview2, we introduced a new HostFiltering middleware(Microsoft.AspNetCore.HostFiltering) that we recommend you use in conjunction with Kestrel to validate Host headers. The host filtering middleware is already included as part of the default WebHost. To configure the middleware, use a semicolon separated list of hostnames in your appSettings.json file.

    {
        "AllowedHosts": "localhost;127.0.0.1;[::1]"
    }

    Alternatively, you can configure it directly from code.

    services.AddHostFiltering(options =>
    {
        var allowedHosts = new List<String>{
            "localhost",
            "127.0.0.1",
            "[::1]"
        };
        options.AllowedHosts = allowedHosts;
    });

    Blazor 0.2.0 release now available

    $
    0
    0

    Just a few weeks ago we announced the first preview release of an experimental web UI framework called Blazor. Blazor enables full-stack web development using C# and WebAssembly. So far thousands of web developers have taken on the challenge to try out Blazor and done some pretty remarkable things:

    The feedback and support from the community has been tremendous. Thank you for your support!

    Today we are happy to announce the release of Blazor 0.2.0. Blazor 0.2.0 includes a whole bunch of improvements and new goodies to play with.

    New features in this release include:

    • Build your own reusable component libraries
    • Improved syntax for event handling and data binding
    • Build on save in Visual Studio
    • Conditional attributes
    • HttpClient improvements

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

    Many of these improvements were contributed by our friends in the community, for which, again, we thank you!

    You can find getting started instructions, docs, and tutorials for this release on our new documentation site at http://blazor.net.

    Get Blazor 0.2.0

    To get setup with Blazor 0.2.0:

    1. Install the .NET Core 2.1 Preview 2 SDK.
      • If you've installed the .NET Core 2.1 Preview 2 SDK previously, make sure the version is 2.1.300-preview2-008533 by running dotnet --version. If not, then you need to install it again to get the updated build.
    2. Install the latest preview of Visual Studio 2017 (15.7) with the ASP.NET and web development workload.
      • You can install Visual Studio previews side-by-side with an existing Visual Studio installation without impacting your existing development environment.
    3. Install the ASP.NET Core 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
    

    Upgrade a Blazor project

    To upgrade an existing Blazor project from 0.1.0 to 0.2.0:

    • Install all of the required bits listed above
    • Update your Blazor package and .NET CLI tool references to 0.2.0
    • Update the package reference for Microsoft.AspNetCore.Razor.Design to 2.1.0-preview2-final.
    • Update the SDK version in global.json to 2.1.300-preview2-008533
    • For Blazor client app projects, update the Project element in the project file to <Project Sdk="Microsoft.NET.Sdk.Web">
    • Update to the new bind and event handling syntax

    Your upgraded Blazor project file should look like this:

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>netstandard2.0</TargetFramework>
        <RunCommand>dotnet</RunCommand>
        <RunArguments>blazor serve</RunArguments>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.0-preview2-final" PrivateAssets="all" />
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.2.0" />
        <PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.2.0" />
        <DotNetCliToolReference Include="Microsoft.AspNetCore.Blazor.Cli" Version="0.2.0" />
      </ItemGroup>
    
    </Project>
    

    Build reusable component libraries

    Blazor components are reusable pieces of web UI that can maintain state and handle events. In this release we've made it easy to build reusable component libraries that you can package and share.

    To create a new Blazor component library:

    1. Install the Blazor templates on the command-line if you haven't already

       dotnet new -i Microsoft.AspNetCore.Blazor.Templates
      
    2. Create a new Blazor library project

       dotnet new blazorlib -o BlazorLib1
      
    3. Create a new Blazor app so we can try out our component.

       dotnet new blazor -o BlazorApp1
      
    4. Add a reference from the Blazor app to the Blazor library.

       dotnet add BlazorApp1 reference BlazorLib1
      
    5. Edit the home page of the Blazor app (/Pages/Index.cshtml) to use the component from the component library.

       @addTagHelper *, BlazorLib1
       @using BlazorLib1
       @page "/"
      
       <h1>Hello, world!</h1>
      
       Welcome to your new app.
      
       <SurveyPrompt Title="How is Blazor working for you?" />
      
       <Component1 />
      
    6. Build and run the app to see the updated home page

       cd BlazorApp1
       dotnet run
      

      Blazor component library

    JavaScript interop

    Blazor apps can call browser APIs or JavaScript libraries through JavaScript interop. Library authors can create .NET wrappers for browser APIs or JavaScript libraries and share them as reusable class libraries.

    To call a JavaScript function from Blazor the function must first be registered by calling Blazor.registerFunction. In the Blazor library we just created exampleJsInterop.js registers a function to display a prompt.

    Blazor.registerFunction('BlazorLib1.ExampleJsInterop.Prompt', function (message) {
        return prompt(message, 'Type anything here');
    });
    

    To call a registered function from C# use the RegisteredFunction.Invoke method as shown in ExampleJsInterop.cs

    public class ExampleJsInterop
    {
        public static string Prompt(string message)
        {
            return RegisteredFunction.Invoke<string>(
                "BlazorLib1.ExampleJsInterop.Prompt",
                message);
        }
    }
    

    In the Blazor app we can now update the Counter component in /Pages/Counter.cshtml to display a prompt whenever the button is clicked.

    @using BlazorLib1
    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button onclick="@IncrementCount">Click me</button>
    
    @functions {
        int currentCount = 0;
    
        void IncrementCount()
        {
            currentCount++;
            ExampleJsInterop.Prompt("+1!");
        }
    }
    

    Build and run the app and click the counter button to see the prompt.

    Counter prompt

    We can now package our Blazor library as a NuGet package and share it with the world!

    cd ../BlazorLib1
    dotnet pack
    

    Improved event handling

    To handle events Blazor components can register C# delegates that should be called when UI events occur. In the previous release of Blazor components could register delegates using a specialized syntax (ex <button @onclick(Foo)> or <button onclick=@{ Foo(); }>) that only worked for specific cases and for specific types. In Blazor 0.2.0 we've replaced the old syntax with a new syntax that is much more powerful and flexible.

    To register an event handler add an attribute of the form on[event] where [event] is the name of the event you wish to handle. The value of the attribute should be the delegate you wish to register preceded by an @ sign. For example:

    <button onclick="@OnClick" />
    @functions {
        void OnClick(UIMouseEventArgs e)
        {
            Console.WriteLine("hello, world");
        }
    }
    

    or using a lambda:

    <button onclick="@(e => Console.WriteLine("hello, world"))"
    

    If you don't need access to the UIEventArgs in the delegate you can just leave it out.

    <button onclick="@OnClick" />
    @functions {
        void OnClick()
        {
            Console.WriteLine("hello, world");
        }
    }
    

    With the new syntax you can register a handler for any event, including custom ones. The new syntax also enables better support for tool tips and completions for specific event types.

    The new syntax also allows for normal HTML style event handling attributes. If the value of the attribute is a string without a leading @ character then the attribute is treated as normal HTML.

    For some events we define event specific event argument types (ex UIMouseEventArgs as shown above). We only have a limited set of these right now, but we expect to have the majority of events covered in the future.

    Improved data binding

    Data binding allows you to populate the DOM using some component state and then also update the component state based on DOM events. In this release we are replacing the previous @bind(...) syntax with something more first class and that works better with tooling.

    Bind tooling

    To create setup a data binding you use the bind attribute.

    <input bind="@CurrentValue" />
    @functions {
        public string CurrentValue { get; set; }
    }
    

    The C# expression provided to bind should be something that can be assigned (i.e. an LValue).

    Using the bind attribute is essentially equivalent to the following:

    <input value="@CurrentValue" onchange="@((UIValueEventArgs __e) => CurrentValue = __e.Value)/>
    @functions {
        public string CurrentValue { get; set; }
    }
    

    When the component is rendered the value of the input element will come from the CurrentValue property. When the user types in the text box the onchange is fired and the CurrentValue property is set to the changed value. In reality the code generation is a little more complex because bind deals with a few cases of type conversions. But, in principle, bind will associate the current value of an expression with a value attribute, and will handle changes using the registered handler.

    Data binding is frequently used with input elements of various types. For example, binding to a checkbox looks like this:

    <input type="checkbox" bind="@IsSelected" />
    @functions {
        public bool IsSelected { get; set; }
    }
    

    Blazor has a set of mappings between the structure of input tags and the attributes that need to be set on the generated DOM elements. Right now this set is pretty minimal, but we plan to provide a complete set of mappings in the future.

    There is also limited support for type conversions (string, int, DataTime) and error handling is limited right now. This is another area that we plan to improve in the future.

    Binding format strings

    You can use the format-... attribute to provide a format string to specify how .NET values should be bound to attribute values.

    <input bind="@StartDate" format-value="MM/dd/yyyy" />
    @functions {
        public DateTime StartDate { get; set; }
    }
    

    Currently you can define a format string for any type you want … as long as it's a DateTime ;). Adding better support for formating and conversions is another area we plan to address in the future.

    Binding to components

    You can use bind-... to bind to component parameters that follow a specific pattern:

    @* in Counter.cshtml *@
    <div>...html omitted for brevity...</div>
    @functions {
        public int Value { get; set; } = 1;
        public Action<int> ValueChanged { get; set; }
    }
    
    @* in another file *@
    <Counter bind-Value="@CurrentValue" />
    @functions {
        public int CurrentValue { get; set; }
    }
    

    The Value parameter is bindable because it has a companion ValueChanged event that matches the type of the Value parameter.

    Build on save

    The typical development workflow for many web developers is to edit the code, save it, and then refresh the browser. This workflow is made possible by the interpreted nature of JavaScript, HTML, and CSS. Blazor is a bit different because it is based on compiling C# and Razor code to .NET assemblies.

    To enable the standard web development workflow with Blazor, Visual Studio will now watch for file changes in your Blazor project and rebuild and restart your app as things are changed. You can then refresh the browser to see the changes without having to manually rebuild.

    Conditional attributes

    Blazor will now handle conditionally rendering attributes based on the .NET value they are bound to. If the value you're binding to is false or null, then Blazor won't render the attribute. If the value is true, then the attribute is rendered minimized.

    For example:

    <input type="checkbox" checked="@IsCompleted" />
    @functions {
        public bool IsCompleted { get; set; }
    }
    
    @* if IsCompleted is true, render as: *@
    <input type="checkbox" checked />
    
    @* if IsCompleted is false, render as: *@
    <input type="checkbox" />
    

    HttpClient improvements

    Thanks to a number of contributions from the community, there are a number of improvements in using HttpClient in Blazor apps:

    • Support deserialization of structs from JSON
    • Support specifying arbitrary fetch API arguments using the HttpRequestMessage property bag.
    • Including cookies by default for same-origin requests

    Summary

    We hope you enjoy this updated 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

    Have fun!

    Library Manager: Client-side content manager for web apps

    $
    0
    0

    If you’re developing a modern web app, chances are your app will reference client-side JavaScript and CSS files like jQuery, bootstrap, or Angular libraries. Maybe you copy these from a previous project. Or perhaps you download them from the Internet (ie. from a CDN). If you’ve been using more modern practices, you might be acquiring such static content via Bower or npm. Each of these methods have their problems. With Bower announcing they won’t be offering support into the future, we thought it time to produce a lightweight, effective solution for web developers to easily manage common client-side library files.

    Introducing: Library Manager – Available in Visual Studio 2017 v15.7 Preview 3.0 in the Web Development and .NET Core workloads.

    Library Manager (“LibMan” for short) is Microsoft’s new static client-side library management system, specifically designed with web projects in mind. It provides a mechanism, similar to Bower or npm, that helps users find and fetch library files from an external source such as CDNJS or a local library catalog. Library configuration can be stored with the project and files can be downloaded during build, or with Visual Studio tooling.

    How to use Library Manager

    From a Web Project, you can include Library Manager by choosing selecting “Manage Client-Side Libraries…” from the Project menu or from the project context menu in Solution Explorer.

    Project Menu    Project context menu in Solution Explorer
    Library Manager menu items on Project menu    Project context menu in Solution Explorer

    If it doesn’t already exist, the Library Manager configuration file (libman.json) will be created with some default content and added to the root of your project. It opens in the JSON editor.
    To specify the library files required for your project, simply add them to the libman.json file. Contextual IntelliSense is available to help you fill out the fields.

    Saving the file will trigger the Library Manager restore operation, which will download the specified files and libraries and add them to the current project in the prescribed destination folder. You can see the results of the restore operation in the Output window.

    Sample web project with sample libman.json file

    Library Manager Configuration

    Provider
    There are two provider options that have been built for version 1.0 of Library Manager: cndjs and filesystem.

    • The cdnjs provider will attempt to fetch specified library files from the CDNJS public distribution network.
    • The filesystem provider will attempt to fetch library files from a local or network drive and will copy them to the destination folder.

    The library files will come from the “defaultProvider” specified at the top level unless otherwise overridden by a “provider” property in the individual library definition.

    Library
    The “library” is the unique name of the library as defined by the relevant provider.

    • For the cdnjs provider, library names have the format: [LibraryName]@[Version] (Eg. “jquery@3.3.1”)
    • For the filesystem provider, the library is the path to the folder containing the library files.
      (eg. “//NetworkShare/MyLib”, “C:/LocalLibs/MyLib”)

    Note: When using the Visual Studio editor, be sure to specify the provider element first if you want contextual IntelliSense to list the available libraries.

    Contextual IntelliSense showing all available versions of jquery, sorted by most recent

    Files
    By default, all files from the specified library will be included in your project. If you only want to include specific files from a library, you can specify the file names in a comma separated list in the “files” property.
         eg. “files”: [“jquery.min.js”, “jquery.min.map”]
    Contextual IntelliSense provides a list of available files to make it easier to discover and select the files you’re after.

    Contextual IntelliSense showing list of all files in the jQuery library, excluding those already used

    Destination
    The “destination” of a library is the folder within your project where the library files will be restored.

    There are two ways to specify the destination for a library’s files. If a “defaultDestination” property is defined at the top level, then the library files will be copied there (within the directory structure that they exist at the provider location). If a “destination” is defined at the library level, it will override the defaultDestination. Both destination and defaultDestination are relative to the location of the libman.json file.

    Clean and Restore operations

    Restore on build
    You can enable Library Manager to restore all library files during build. To do so, right-click the libman.json file and choose “Enable Restore on Build”. This will add the LibraryManager NuGet package (Microsoft.Web.LibraryManager.Build) to the project, which will trigger a restore as part of project build.

    Context menu of libman.json, showing Restore, Clean and Enable Restore on Build...

    Restore on demand
    Library Manager will restore client-side libraries whenever the libman.json file is saved. You can also force the restore operation by choosing “Restore Client-Side Libraries” from the context menu of the libman.json file in Solution Explorer.

    Clean library files
    You can use the “Clean” item on the libman.json context menu to delete all library files defined in the libman.json (if they exist in the destinations specified).
    Note: If restoring files through Visual Studio, Library Manager will automatically delete any files defined during the previous restore operation that are no longer being referenced in the libman.json file.

    Feedback/Contributions

    Microsoft’s Library Manager is open-source and available on GitHub at: https://github.com/aspnet/LibraryManager
    We welcome contributions and suggestions. For details, see the Contribution Guide. If you have any feedback or bug reports, please feel free to open new issues on the Issues repo.

    What Happened to Bower?

    $
    0
    0

    Bower is a popular package management system for managing static content used by client-side web applications. Visual Studio provides rich support for Bower, including templates and package management tools.

    In October 2017, there were announcements on Twitter hinting that the Bower platform was being deprecated. While Bower hasn’t gone away, the official website is encouraging people to use different frameworks, even going so far as to provide detailed instructions on “How to migrate away from Bower” and “How to drop Bower support”.

    In their own words:

    Message on Bower website: 'While Bower is maintained, we recommend using Yarn and Webpack for front-end projects'

    Though it doesn’t say it explicitly, it implies that Bower is deprecated. Existing projects that depend on package management via Bower will continue to work for the time being; but it’s recommended that new projects should not take a dependency on Bower.

    Introducing Library Manager

    While there are other useful package managers, as Bower points out (e.g. npm), most are designed to handle a variety of tasks, which adds unnecessary complexity when you only need them for a single task (acquiring client-side libraries). So, here at Visual Studio, we decided to create a new tool that would be as simple as possible for specifically addressing the need to acquire client-side content for web applications. Hence, the introduction of “Library Manager”.

    Library Manager (“LibMan” for short) is Visual Studio’s new client-side static content management system. Designed as a replacement for Bower and npm, LibMan helps users find and fetch library files from an external source (like CDNJS) or from any file system library catalog.

    You can specify the library files required for your project by adding entries to the LibMan configuration file – libman.json. See the image below; it shows an example libman.json file in which some jQuery files are added to the wwwroot/lib directory.

    Example libman.json

    To learn more about LibMan, see the article “Library Manager: Client-side content management for web apps“.

    Publish Improvements in Visual Studio 2017 15.7

    $
    0
    0

    Today we released Visual Studio 2017 15.7 Preview 4. Our 15.7 update brings some exciting updates for publishing applications from Visual Studio that we’re excited to tell you about, including:

    • Ability to configure publish settings before you publish or create a publish profile
    • Create Azure Storage Accounts and automatically store the connection string for App Service
    • Automatic enablement of Managed Service Identity in App Service

    If you haven’t installed a Visual Studio Preview yet, it’s worth noting that they can be installed side by side with your existing stable installations of Visual Studio 2017, so you can try the previews out, and then go back to the stable channel for your regular work. We’d be very appreciative if you’d try Visual Studio 2017 15.7 Preview 4 and give us any feedback you might have while we still have time to change or fix things before we ship the final version (download now). As always, if you run into any issues, please report them to us using Visual Studio’s built in “Report a Problem” feature.

    Configure settings before publishing

    When publishing your ASP.NET Core applications to either a folder or Azure App Service you can configure the following settings prior to creating your publish profile:

    To configure this prior to creating your profile, click the “Advanced…” link on the publish target page to open the Advanced Settings dialog.

    Advanced link on 'Pick a publish target' dialog

    Create Azure Storage Accounts and automatically store the connection string in App Settings

    When creating a new Azure App Service, we’ve always offered the ability to create a new SQL Azure database and automatically store its connection string in your app’s App Service Settings. With 15.7, we now offer the ability to create a new Azure Storage Account while you are creating your App Service, and automatically place the connection string in the App Service settings as well. To create a new storage account:

    • Click the “Create a storage account” link in the top right of the “Create App Service” dialog
    • Provide in the connecting string key name your app uses to access the storage account in the “(Optional) Connecting String Name” field at the bottom of the Storage Account dialog
    • Your application will now be able to talk to the storage account once your application is published

    Optional Connection String Name field on Storage Account dialog

    Managed Service Identity enabled for new App Services

    A common challenge when building cloud applications is how to manage the credentials that need to be in your code for authenticating to other services. Ideally, credentials never appear on developer workstations or get checked into source control. Azure Key Vault provides a way to securely store credentials and other keys and secrets, but your code needs to authenticate to Key Vault to retrieve them. Managed Service Identity (MSI) makes solving this problem simpler by giving Azure services an automatically managed identity in Azure Active Directory (Azure AD). You can use this identity to authenticate to any service that supports Azure AD authentication, including Key Vault, without having any credentials in your code.

    Starting in Visual Studio 2017 15.7 Preview 4, when you publish an application to Azure App Service (not Linux) Visual Studio automatically enables MSI for your application. You can then give your app permission to communicate with any service that supports MSI authentication by logging into that service’s page in the Azure Portal and granting access your App Service. For example, to create a Key Vault and give your App Service access

    1. In the Azure Portal, select Create a resource > Security + Identity > Key Vault.
    2. Provide a Name for the new Key Vault.
    3. Locate the Key Vault in the same subscription and resource group as the App Service you created from Visual Studio.
    4. Select Access policies and click Add new.
    5. In Configure from template, select Secret Management.
    6. Choose Select Principal, and in the search field enter the name of the App Service.
    7. Select the App Service’s name in the result list and click Select.
    8. Click OK to finishing adding the new access policy, and OK to finish access policy selection.
    9. Click Create to finish creating the Key Vault.

    Azure portal dialog: Create a Key Vault and give your App Service access

    Once you publish your application, it will have access to the Key Vault without the need for you to take any additional steps.

    Conclusion

    If you’re interested in the many other great things that Visual Studio 2017 15.7 brings for .NET development, check out our .NET tool updates in Visual Studio 15.7 post on the .NET blog.

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


    Cosmos DB Solves Common Data Challenges in App Development

    $
    0
    0

    When considering how to implement your application with a relational database, it can change how you build it dramatically. Some of these challenges include adding an abstract implementation of the schema in the code, mapping data to objects, building queries, and preventing SQL injection attacks. Wouldn’t it be great if there was a way to reduce the number of problems that can arise with data when building your app? Cosmos DB could be the answer for you.

    Azure Cosmos DB is a fully managed, globally distributed database service that alleviates the common application development stressors of working with data. Cosmos DB also comes with guaranteed high availability, low latency, and scalable throughput and storage. Getting started is fast and easy, thanks to Cosmos DB’s schema agnostic database engine and extensive number of comprehensive APIs.

    In this blog post, we’ll walk through how Cosmos DB solves these problems in addition to some of its other benefits. With a sample .NET web application, we’ll walk through how to use the Cosmos DB SQL .NET API, which allows you to use familiar SQL syntax to query data.

    Core Cosmos DB Concepts

    A Cosmos DB database is the central location of the data and users who have varying administrative rights to the data. Databases store collections, which are a repository of documents, containing the raw data in JSON format. Each document relates to one unit of data, where its properties and respective values define it. These terms can be translated directly to a traditional database, like SQL Server for example, illustrated in the comparison table below.

    SQL Server Cosmos DB
    Database Database
    Table Collection
    Record Document
    Column Property
    Sample Overview

    Imagine a common scenario where you expect a user to interact with your application and its underlying data. Usually, the user will want to view the data in a readable format, and a way to alter, add, or delete the data.

    The sample is an ASP.NET web application that allows a user to maintain a list of their favorite Microsoft documentation links and Channel 9 videos. The application’s data is stored and maintained in Cosmos DB, which contains the user populated data and web page metadata that the application finds from the provided documentation or video url.

    Visit the Url Notes repository to view the complete sample

    Domain model flexibility

    The Cosmos DB SQL .NET API makes working with your model seamless by managing the object mapping for you. You can work directly with your domain objects; perfect for applications that require create, read, update, and delete (CRUD) operations. This will look familiar if you’ve worked with the object relational mapping provided by Entity Framework.

    In the sample, GetAllDocs demonstrates getting all documents that belong to a collection. Notice that this method has a generic type parameter, this is used to pass the model type that the data set will bind to.

    The sample uses generic methods as a straightforward way to pass types to CreateDocumentQuery, which requires a type parameter.

    Here’s a example of the returned data in the debugger and the data in the portal.

    Screenshot of an object while debugging the url notes app in visual studio

    A Video object as seen while debugging in Visual Studio

    Screenshot of a document in cosmos db

    The same Video object as a document in Cosmos DB via the Cosmos DB Data Explorer in the Azure Portal

    Queries with SQL-like syntax or LINQ

    The API gives developers options how to query data using the familiar syntax of either SQL or LINQ to build queries. The API helps reduce query complexity as building queries on properties are much easier. Furthermore, you can still protect against SQL injection with parameters.

    The sample’s GetDocument method uses LINQ to search for a document by ID, a property of the Document type, as all documents have a unique ID.

    Here’s a conceptual example of a query with a Video object:

    In the sample, a user can choose up to two properties to go along with their search text, in searchTerms and searchText, respectively. The Search method uses these parameters to look for matches in the specified properties. The query is built based on those properties and are set as SQL parameters.

    Reduce the complexities of inserts, updates, and deletes

    The API provides operations for making changes to your data whether it be adding more records, altering them, or removing them. For most of these operations, the API only requires the collection, and the domain model object.

    CreateDocumentAsync requires two parameters: the url to the collection, and the object to be inserted into the collection. For example, inserting a new document into the Video collection requires passing the name of the Video collection, and the Video object parameter. When adding a new document to a collection, the API takes care of serializing the object to JSON.

    The API’s ReplaceDocumentAsync method reduces the complexities of updating by providing multiple ways to directly access and change properties. In the sample, the user-editable properties are accessed by their document’s property name.

    Before updating a document in EditDocument, the sample confirms it exists, then returns it as a Document object in the doc variable. Finally, the document’s properties are updates the via object’s SetPropertyValue method before calling ReplaceDocumentAsync.

    Alternatively, you can use your defined domain objects to update the document. Below is an example on how that could be done with the Video object:

    Use your favorite database management features

    Cosmos DB comes with the ability to create and manage stored procedures, user defined functions, and triggers. This functionality will be familiar to those using SQL Server or another database that has these features. Use either the API, Azure portal, command line (CLI), or the Cosmos DB Data Explorer  to manage these features. While this sample does not use any of these features, here’s an example stored procedure:

    A Cosmos DB stored procedure in the Azure Portal

    A Cosmos DB stored procedure in the Azure Portal

    High Availability and Scaling

    In addition to what the API offers, Cosmos DB also comes with the guarantee of optimal performance with features like low latency, automatic indexing, region-based availability, and scalable throughput.

    Cosmos DB enables region-based availability with their replication protocol that ensures database operations are performed in the region that is local to the client. One benefit of this is low latency at the 99th percentile, along with the promise of data consistency across all regions. By default, the level of consistency in Cosmos DB provides automatic indexing after each insert, delete, and replace/update of documents.

    Performance dependent variables like CPU, and memory are all calculated in a measurement specific to Cosmos DB called Request Units (RUs). With RUs, throughput is managed based on the computational complexity of operations done on a database. For common scenarios, databases with predictable performance will need 100 RUs/second, with the option to provide more as needed. You can use the request unit calculator to estimate RUs needed.

    Worried about throughput limits? With the Cosmos DB .NET APIs you get the added bonus of automatic retries for single clients that are operating above the provisioned rate. Additionally, you can catch the DocumentClientException rate limit exceptions and customize the retry process yourself.

    Summary

    Building data driven applications can come with several problems to solve, and Cosmos DB can lighten the load of addressing them. With an extensive and comprehensive API to work with domain objects directly for database operations, and a globally available and scalable database, Cosmos DB simplifies these complexities and allows developers to focus on what matters to them the most.

    Related Links

    Interested in learning more about Cosmos DB? In depth information on the topics covered in this post can be found in the links below. New to Azure?  Sign up today, no credit card required.

    Announcing ASP.NET MVC 5.2.5, Web API 5.2.5, and Web Pages 3.2.5

    $
    0
    0

    Today we released ASP.NET MVC 5.2.5, Web API 5.2.5, and Web Pages 3.2.5 on NuGet. This is a patch release that contains only bug fixes. You can find the full list of bug fixes for this release in the release notes.

    To update an existing project to use this preview release run the following commands from the NuGet Package Manager Console for each of the packages you wish to update:

    Install-Package Microsoft.AspNet.Mvc -Version 5.2.5
    Install-Package Microsoft.AspNet.WebApi -Version 5.2.5
    Install-Package Microsoft.AspNet.WebPages -Version 3.2.5
    

    If you have any questions or feedback on this release please let us know on GitHub.

    Thanks!

    Blazor 0.3.0 experimental release now available

    $
    0
    0

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

    New features in this release (details below):

    • Project templates updated to use Bootstrap 4
    • Async event handlers
    • New component lifecycle events: OnAfterRender / OnAfterRenderAsync
    • Component and element refs
    • Better encapsulation of component parameters
    • Simplified layouts

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

    Get Blazor 0.3.0

    To get setup with Blazor 0.3.0:

    1. Install the .NET Core 2.1 SDK (2.1.300-preview2-008533 or later).
    2. Install Visual Studio 2017 (15.7 Preview 5 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.3.0

    To upgrade an existing Blazor project from 0.2.0 to 0.3.0:

    • Install all of the required bits listed above.
    • Update your Blazor package and .NET CLI tool references to 0.3.0.
    • Remove any package reference to Microsoft.AspNetCore.Razor.Design as it is now a transitive dependency.
    • Update the C# language version to be 7.3. You may need to restart Visual Studio for this change to take effect.
    • Update component parameters to not be public and to add the [Parameter] attribute.
    • Update layouts to inherit from BlazorLayoutComponent and remove the implementation of ILayoutComponent including the Body property.

    Your upgraded Blazor project file should look like this:

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

    Project templates updated to use Bootstrap 4

    The Blazor project templates have been updated to use Bootstrap 4. Bootstrap 4 includes lots of new features including an improved grid system based on flexbox, an improved reset file, new components, better tooltip support, better forms styling, built-in spacing utilities, and much more.

    The new Bootstrap 4 styles also give the Blazor templates a fresh look:

    Blazor Boostrap 4 template

    Async event handlers

    Event handlers can now be asynchronous and return a Task that gets managed by the runtime. Once the task is completed the component is rendered without the need to manually invoke StateHasChanged. Any exceptions that occur during the asynchronous execution of the event handler will be correctly handled and reported.

    For example, we can update the FetchData.cshtml page to have an Update button that when selected asynchronously updates the weather forecast data by making HttpClient calls to the backend web API:

    <button class="btn btn-primary" onclick="@UpdateForecasts">Update</button>
    
    ...
    
    @functions {
        WeatherForecast[] forecasts;
    
        protected override Task OnInitAsync()
        {
            return UpdateForecasts();
        }
    
        async Task UpdateForecasts()
        {
            forecasts = await Http.GetJsonAsync<WeatherForecast[]>("/api/SampleData/WeatherForecasts");
        }
    }
    

    More strongly-typed events

    This release adds strongly typed events for the most of the commonly used browser events, including mouse and focus events. You can now handle most events from your components.

    You can see a full list of the events now supported in here.

    <h1 class="display-1" onmouseover="@OnMouseOver" onmouseout="@OnMouseOut">@inOrOut</h1>
    
    @functions {
        string inOrOut = "OUT";
    
        void OnMouseOver()
        {
            inOrOut = "IN!";
        }
    
        void OnMouseOut()
        {
            inOrOut = "OUT";
        }
    }
    

    Mouse events tooling screen shot

    Most of the event arguments don't yet capture and surface the data from the events. That's something that we expect to handle in a future release. We welcome community contributions to help out with this effort.

    Capturing references to DOM elements

    Blazor components typically interact with the DOM through their rendering logic in markup. There are cases, however, when a parent component needs to modify or interact with DOM elements directly. Example scenarios including setting element focus or integrating with existing UI libraries that require references to elements for initialization. This release adds support for capturing DOM elements from components and using them when interacting with JavaScript.

    To capture an element reference from a component attribute the element markup with a ref attribute that points to a component field of type ElementRef.

    <input ref="username" />
    
    @functions {
        ElementRef username;
    }
    

    ElementRef is an opaque handle. The only thing you can do with it is pass it through to JavaScript code, which receives the element as an HTMLElement that can be used with normal DOM APIs.

    Note that the ElementRef field (username in the previous example) will uninitialized until after the component has been rendered. If you pass an uninitialized ElementRef to JavaScript code, the JavaScript code will receive null.

    Let's create a API that lets us set the focus on an element. We could define this API in our app, but to make it reusable let's put it in a library.

    1. Create a new Blazor class library

       dotnet new blazorlib -o BlazorFocus
      
    2. Update content/exampleJsInterop.js to register a JavaScript method that sets the focus on a specified element.

       Blazor.registerFunction('BlazorFocus.FocusElement', function (element) {
           element.focus();
       });
      
    3. Add a ElementRefExtensions class to the library that defines a Focus extension method for ElementRef.

       using System;
       using Microsoft.AspNetCore.Blazor;
       using Microsoft.AspNetCore.Blazor.Browser.Interop;
      
       namespace BlazorFocus
       {
           public static class ElementRefExtensions
           {
               public static void Focus(this ElementRef elementRef)
               {
                   RegisteredFunction.Invoke<object>("BlazorFocus.FocusElement", elementRef);
               }
           }
       }
      
    4. Create a new Blazor app and reference the BlazorFocus library

       dotnet new blazor -o BlazorApp1
       dotnet add BlazorApp1 reference BlazorFocus
      
    5. Update Pages/Index.cshtml to add a button and a text input. Capture a reference to the text input by adding a ref attribute that points to a field of type ElementRef with the same name. Add an onclick handler to the first button that sets the focus on the second button using the captured reference and the Focus extension method we defined previously.

       @using BlazorFocus
      
       ...
      
       <button onclick="@SetFocus">Set focus</button>
       <input ref="input1" />
      
       @functions {
           ElementRef input1;
      
           void SetFocus()
           {
               input1.Focus();
           }
       }
      
    6. Run the app and try out behavior

       dotnet run BlazorApp1
      

      Set focus

    Capturing reference to components

    You can also capture references to other components. This is useful when you want a parent component to be able to issue commands to child components such as Show or Reset.

    To capture a component reference attribute the component with a ref attributes that points to a field of the matching component type.

    <MyLoginDialog ref="loginDialog"/>
    
    @functions {
        MyLoginDialog loginDialog;
    
        void OnSomething()
        {
            loginDialog.Show();
        }
    }
    

    Note that component references should not be used as a way of mutating the state of child components. Instead, always use normal declarative parameters to pass data to child components. This will allow child components to re-render at the correct times automatically.

    OnAfterRender / OnAfterRenderAsync

    To capture element and component references the component must already be rendered. Components now have a new life-cycle event that fires after the component has finished rendering: OnAfterRender / OnAfterRenderAsync. When this event fires element and component references have already been populated. This makes it possible to perform additional initialization steps using the rendered content, such as activating third-party JavaScript libraries that operate on the rendered DOM elements.

    For example, we can use OnAfterRender to set the focus on a specific element when a component first renders.

    The example below shows how you can receive the OnAfterRender event in your component.

    <input ref="input1" placeholder="Focus on me first!" />
    <button>Click me</button>
    
    @functions {
        ElementRef input1;
        bool isFirstRender = true;
    
        protected override void OnAfterRender()
        {
            if (isFirstRender)
            {
                isFirstRender = false;
                input1.Focus();
            }
        }
    }
    

    Note that OnAfterRender / OnAfterRenderAsync is called after each render, not just the initial one, so the component has to keep try of whether this is the first render or not.

    Better encapsulation of component parameters

    In this release we've made some changes to the programming model for component parameters. These changes are intended to improve the encapsulation of the parameter values and discourage improper mutation of component state (e.g. using component references).

    Component parameters are now defined by properties on the component type that have been attributed with [Parameter]. Parameters that are set by the Blazor runtime (e.g. ChildContent properties, route parameters) must be similarly attributed. Properties that define parameters should not be public.

    A Counter component with an IncrementAmount parameter now looks like this:

    @page "/counter"
    
    <h1>Counter</h1>
    
    <p>Current count: @currentCount</p>
    
    <button class="btn btn-primary" onclick="@IncrementCount">Click me</button>
    
    @functions {
        int currentCount = 0;
    
        [Parameter]
        private int IncrementAmount { get; set; } = 1;
    
        void IncrementCount()
        {
            currentCount += IncrementAmount;
        }
    }
    

    Simplified layouts

    Layouts now inherit from BlazorLayoutComponent instead of implementing ILayoutComponent. The BlazorLayoutComponent defines a Body parameter that can be used for specifying where content should be rendered. Layouts no longer need to define their own Body property.

    An example layout with these changes is shown below:

    @inherits BlazorLayoutComponent
    
    <div class="sidebar">
        <NavMenu />
    </div>
    
    <div class="main">
        <div class="top-row px-4">
            <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
        </div>
    
        <div class="content px-4">
            @Body
        </div>
    </div>
    

    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!

    Exploring Azure App Service – Introduction

    $
    0
    0

    Have you ever needed to quickly stand up a web site, or web API app that was publicly available? Is your team or organization thinking about moving to the cloud but aren’t sure the best place to start? One of the first places you should look is Azure App Service Web Apps. In this post we’ll look at how easy it is to get started, and a quick overview of key concepts.

    App Service offers the following benefits:

    • A fully managed platform, meaning Azure automatically updates the operating system and runtime as security and stability fixes are released.
    • 10 free plans to every subscriber, so it won’t cost you money or credits to try your app in Azure.
    • First class support in Visual Studio, meaning that you can go from your app running on your local machine to running in App Service in less than 2 minutes.
    • If offers deployment slots, which enable you to stage multiple versions of your app, and route varying amounts of traffic to the various versions (i.e. do A/B testing, or a ringed release model).
    • Scale up and down quickly and automatically based on load
    • For a more see Why use Web Apps?

    In this blog post, I’ll provide an overview of App Service’s key features and concepts by walking through using Visual Studio to publish an ASP.NET application to Azure App Service.

    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, for the purposes of this post, I’ll use a basic ASP.NET Core app

    To start I’ll right click my project in Solution Explorer and choose “Publish”

    clip_image001

    This brings up the Visual Studio publish target dialog, which will default to the Azure App Service pane. The “Create new” radio button is already selected to, so I’ll click the “Publish” button on the bottom right.

    This will open the Create App Service dialog in Visual Studio.

    Key App Service Concepts

    The dialog has four fields that represent key concepts of creating an App Service:

    1. App Name: Will be the default public facing URL in Azure (it will be of the form https://<App_Name>.azurewebsites.net –you can configure domain names later if needed).
    2. Subscription: The Azure Subscription to create the resources in if you have more than one
    3. Resource Group: Groups your application and any dependent resources (SQL Databases, Storage Accounts, etc., see resource group design to learn more). To edit the name, click “New…”.
    4. Hosting Plan: The hosting plan is a set of reserved resources for your app. You can choose to host multiple apps in a single hosting plan (we’ll explore this further in a minute).

    clip_image003

    One concept that can be confusing is the relationship between the “Hosting Plan” (or App Service plan”) and the “App Service”:

    • The Hosting/App Service plan is the virtual machine resources you are reserving in Azure to host your application. This is what you are paying or using credits for.
    • The App Service is your app and associated settings that run inside of the plan. You can run multiple apps (App Services) in the same plan (virtual machine) with the same implications as sharing any other server or VM between apps.

    To explore the App Service plan further, click the “New…” button next to the Hosting Plan dropdown to open the “Configure Hosting Plan” dialog that has three fields:

    1. App Service Plan: A non-public facing name for the plan.
    2. Location: Is the region your app will run in. You generally want to pick a region that is close to customers that will be accessing the site.
    3. Size: The size of the virtual machine you want to reserve for your application and the capabilities you want (e.g. deployment slots require a Standard or Premium plan).
      Note: Free and Shared plans run in the same VM as other App Service apps and are intended for development and testing, see App Service plan overview for more details

    Publishing the app

    At this point I’m ready to publish my app to App Service. The bottom right panel of the Create App Service dialog will show me all the resources I’m going to create in Azure (in this case a Hosting Plan and App Service). Everything looks good, so I just need to click “Create”:

    clip_image005

    Visual Studio will create all the resources on my behalf, publish my application, and open my default browser to the URL of the published application.

    Conclusion

    Hopefully, this overview of App Service concepts has been helpful and inspired you to give App Service a try. We believe that for many 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 to see additional choices). As always, let us know if you run into any issues, or have any questions below or via Twitter.

    ASP.NET Core 2.1.0-rc1 now available

    $
    0
    0

    Today we’re happy to announce the first release candidate of ASP.NET Core 2.1! This release should be very close to the final stable release of ASP.NET Core 2.1 and includes primarily bug fixes and polish for the features that we shipped in earlier previews. This is a "go live" release that can be used in production with the understanding that you will need to update to the final stable release once it is available.

    Also, be sure to read about .NET Core 2.1.0-rc1 and Entity Framework Core 2.1.0-rc1.

    Get started

    To get started with ASP.NET Core 2.1.0-rc1 download the .NET Core 2.1.0-rc1 SDK

    Customers using Visual Studio should also install Visual Studio 2017 Update 7 or Visual Studio for Mac 7.5.

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

    To migrate an existing ASP.NET Core 2.0.x project to 2.1.0-rc1:

    1. Open the project’s .csproj file and change the value of the <TargetFramework> element to netcoreapp2.1
      • Projects targeting .NET Framework rather than .NET Core, e.g. net471, don’t need to do this
    2. In the same file, update the versions of the various <PackageReference> elements for any Microsoft.AspNetCore, Microsoft.Extensions, and Microsoft.EntityFrameworkCore packages to 2.1.0-rc1-final
    3. In the same file, remove any references to <DotNetCliToolReference> elements for any Microsoft.AspNetCore, Microsoft.VisualStudio, and Microsoft.EntityFrameworkCore packages. These tools are now deprecated and are replaced by global tools.
    4. In the same file, remove the <DotNetCliToolReference> elements for any Microsoft.AspNetCore packages. These have been replaced by global tools.

    That should be enough to get the project building and running against 2.1.0-preview2. The following steps will change your project to use new code-based idioms that are recommended in 2.1

    1. Open the Program.cs file
    2. Rename the BuildWebHost method to CreateWebHostBuilder, change its return type to IWebHostBuilder, and remove the call to .Build() in its body
    3. Update the call in Main to call the renamed CreateWebHostBuilder method like so: CreateWebHostBuilder(args).Build().Run();
    4. Open the Startup.cs file
    5. In the ConfigureServices method, change the call to add MVC services to set the compatibility version to 2.1 like so: services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    6. In the Configure method, add a call to add the HSTS middleware after the exception handler middleware: app.UseHsts();
    7. Staying in the Configure method, add a call to add the HTTPS redirection middleware before the static files middleware: app.UseHttpsRedirection();
    8. Open the project property pages (right-mouse click on project in Visual Studio Solution Explorer and select “Properties”)
    9. Open the “Debug” tab and in the IIS Express profile, check the “Enable SSL” checkbox and save the changes
    10. In you project file change any package reference to Microsoft.AspNetCore.All package to Microsoft.AspNetCore.App and add additional packages as needed to restore the your required dependency graph

    Note that some projects might require more steps depending on the options selected when the project was created and modifications made to the project.

    Deploying to Azure

    Azure App Service will start deploying .NET Core 2.1.0-rc1 with the next week or so. In the meantime you can still deploy .NET Core 2.1.0-rc1 for your app as a site extension.

    New features and enhancements

    This release primarily contains refinements and bug fixes to the features we shipped in earlier previews, but there are a couple of new features and enhancements worth calling out. You can find a complete list of the features and enhancements in this release in the release notes.

    New Razor UI Class Library template

    The new Razor Class Library project template makes it easy to build reusable Razor UI class libraries. Razor class library projects are already setup with the Razor SDK to enable building Razor files (.cshtml) like MVC views and Razor Pages.

    To create a new Razor class library project from the command-line:

    dotnet new razorclasslib -o RazorClassLib1
    

    You can also create Razor class library projects in Visual Studio from the "New ASP.NET Core Web Application" dialog.

    Razor class library project template

    Improvements to MVC test infrastructure

    You can now derive from WebApplicationFactory to create a custom factory that configures the HttpClient by overriding ConfigureClient. This enables testing scenarios that requrie specific HttpClient configuration, like adding specific HTTP headers.

    We also update the default environment setup by the WebApplicationFactory to be development to simplify scenarios like accessing user secrets and other development resources.

    SignalR updates

    • The MessagePack protocol library for SignalR was renamed to Microsoft.AspNetCore.SignalR.Protocols.MessagePack
    • The JavaScript/TypeScript client now exposes a HubConnectionBuilder (similar to the C# client).
    • Sticky sessions are now required when using the WebSockets transport unless the skipNegotiation flag is set to true:

      var connection = new signalR.HubConnectionBuilder()
        .withUrl("/chat", { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets })
        .build();
      

    Summary

    Thank you for trying out ASP.NET Core 2.1.0-rc1! Assuming everything goes smoothly with this release we should have a stable release of ASP.NET Core 2.1 shortly. If you have any questions or find any issues with this release please let us know by filing issues on GitHub.

    Viewing all 7144 articles
    Browse latest View live


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