Announcing .NET 5.0 RC 2

Avatar

Richard

Today, we are shipping .NET 5.0 Release Candidate 2 (RC2). It is a near-final release of .NET 5.0, and the last of two RCs before the official release in November. RC2 is a “go live” release; you are supported using it in production. At this point, we’re looking for reports of any remaining critical bugs that should be fixed before the final release.

We also released new versions of ASP.NET Core and EF Core today.

You can download .NET 5.0, for Windows, macOS, and Linux:

You need the latest preview version of Visual Studio (including Visual Studio for Mac) to use .NET 5.0.

.NET 5.0 includes many improvements, notably single file applications, smaller container images, more capable JsonSerializer APIs, a complete set of nullable reference type annotations, new target framework names, and support for Windows ARM64. Performance has been greatly improved, in the NET libraries, in the GC, and the JIT. ARM64 was a key focus for performance investment, resulting in much better throughput and smaller binaries. .NET 5.0 includes new language versions, C# 9 and F# 5.0. Check out some .NET 5.0 examples so you can try these features out for yourself.

Today is an auspicious day because we’re kicking off the 2020 .NET@Microsoft internal conference. There will be many speakers from the .NET team, but also developers and architects from services teams that rely on .NET to power the Microsoft cloud, sharing their victories and also their challenges. I’m presenting (unsurprisingly) “What’s new in .NET 5.0”. My talk will be easy; I’ll just read the .NET 5.0 blog posts, preview by preview! It will be a great talk. More seriously, the conference is our opportunity to make the case why Microsoft teams should adopt .NET 5.0 soon after it is available. At least one large team I know of is running on RC1 in production. The official .NET Microsoft site has been running on .NET 5.0 since Preview 1. It is now running RC2. The case we’ll make to Microsoft teams this week is very similar to the case that I’ve intended to make to you across all of these .NET 5.0 blog posts. .NET 5.0 is a great release and will improve the fundamentals of your app.

Speaking of conferences, please save the date for .NET Conf 2020. This year, .NET 5.0 will launch at .NET Conf 2020! Come celebrate and learn about the new release. We’re also celebrating our 10th anniversary and we’re working on a few more surprises. You won’t want to miss this one.

Just like I did for .NET 5.0 Preview 8 and .NET 5.0 RC1, I’ve chosen a selection of features to look at in more depth and to give you a sense of how you’ll use them in real-world usage. This post is dedicated to C# 9 pattern matching, Windows ARM64, and ClickOnce.

C# 9 Pattern Matching

Pattern matching is a language feature was first added in C# 7.0. It’s best to let Mads reintroduce the concept. This is what he had to say when he originally introduced the feature.

C# 7.0 introduces the notion of patterns, which, abstractly speaking, are syntactic elements that can test that a value has a certain “shape”, and extract information from the value when it does.

That’s a really great description, perfectly worded.

The C# team has added new patterns in each of the C# 7, C# 8, and C# 9 versions. In this post, you’ll see patterns from each of those language versions, but we’ll focus on the new patterns in C# 9.

The three new patterns in C# 9 are:

  • Relational patterns, using relational operators such as < and >=.
  • Logical patterns, using the keywords and, or, and not. The poster child example is foo is not null. This type of pattern is most useful when you want to compare multiple things in one pattern.
  • Simple type patterns, using solely a type and no other syntax for matching.

I’m a big fan of the BBC Sherlock series. I’ve written a small app that determines if a given character should have access to a given piece of content within that series. Easy enough. The app is written with two constraints: stay true to the show timeline and characters, and be a great demonstration of patterns. If anything, I suspect I’ve failed most on the second constraint. You’ll find a broader set of patterns and styles than one would expect in a given app (particularly such a small one).

When I’m using patterns, I sometimes want to do something subtly different than a pattern I’m familiar with achieves and am not sure how to extend that pattern to satisfy my goal. Given this sample, I’m hoping you’ll discover more approaches than perhaps you were aware of before, and can extend your repertoire of familiar patterns.

There are two switch expressions within the app. Let’s start with the smaller of the two.

    public static bool IsAccessOKAskMycroft(Person person) => person switch
    {
        // Type pattern
        OpenCaseFile f when f.Name == "Jim Moriarty"    => true,
        // Simple type pattern
        Mycroft                                         => true,
        _                                               => false,
    };

The first two patterns are type patterns. The first pattern is supported with C# 8. The second one — Mycroft — is an example of the new simple type pattern. With C# 8, this pattern would require an identifier, much like the first pattern, or at the very least a discard such as Mycroft _. In C# 9, the identifier is no longer needed. Yes, Mycroft is a type in the app.

Let’s keep to simple a little longer, before I show you the other switch expression. The following if statement demonstrates a logical pattern, preceded by two instances of a type pattern using is.

        if (user is Mycroft m && m.CaresAbout is not object)
        {
            Console.WriteLine("Mycroft dissapoints us again.");
        }

The type isn’t known, so the user variable is tested for the Mycroft type and is then assigned to m if that test passes. A property on the Mycroft object is tested to be not an object. A test for null would have also worked, but wouldn’t have demonstrated a logical pattern.

The other switch expression is a lot more expansive.

    public static bool IsAccessOkOfficial(Person user, Content content, int season) => (user, content, season) switch 
    {
        // Tuple + property patterns
        ({Type: Child}, {Type: ChildsPlay}, _)          => true,
        ({Type: Child}, _, _)                           => false,
        (_ , {Type: Public}, _)                         => true,
        ({Type: Monarch}, {Type: ForHerEyesOnly}, _)    => true,
        // Tuple + type patterns
        (OpenCaseFile f, {Type: ChildsPlay}, 4) when f.Name == "Sherlock Holmes"  => true,
        // Property and type patterns
        {Item1: OpenCaseFile {Type: var type}, Item2: {Name: var name}} 
            when type == PoorlyDefined && name.Contains("Sherrinford") && season >= 3 => true,
        // Tuple and type patterns
        (OpenCaseFile, var c, 4) when c.Name.Contains("Sherrinford")              => true,
        // Tuple, Type, Property and logical patterns 
        (OpenCaseFile {RiskLevel: >50 and <100 }, {Type: StateSecret}, 3) => true,
        _                                               => false,
    };

The only really interesting pattern is the very last one (before the discard: -), which tests for a Risklevel that is >50 and <100. There are many times I’ve wanted to write an if statement with that form of logical pattern syntax without needing to repeat a variable name. This logical pattern could also have been written in the following way instead and would have more closely matched the syntax demonstrated in the C# 9 blog post. They are equivalent.

        (OpenCaseFile {RiskLevel: var riskLevel}, {Type: StateSecret}, 3) when riskLevel switch
            {
                >50 and <100        => true,
                _                   => false
            }                                           => true,

I’m far from a language expert. Jared Parsons and Andy Gocke gave me a lot of help with this section of the post. Thanks! The key stumbling block I had was with a switch on a tuple. At times, the positional pattern is inconvenient, and you only want to address one part of the tuple. That’s where the property pattern comes in, as you can see in the following code.

{Item1: OpenCaseFile {Type: var type}, Item2: {Name: var name}} 
            when type == PoorlyDefined && name.Contains("Sherrinford") && season >= 3 => true,

There is a fair bit going on there. The key point is that the tuple properties are being tested, as opposed to matching a tuple positionally. That approaches provides a lot more flexibility. You are free to intermix these approaches within a given switch expression. Hopefully that helps someone. It helped me.

If you are curious about what the app does, I’ve saved the output of the program in the app gist. You can also run the app for yourself. I believe it requires .NET 5.0 RC2 to run.

If there has been a pattern with the last three C# (major) versions, it has been patterns. I certainly hope the C# team matches that pattern going forward. I imagine it is the shape of things, and there are certainly more values to extract.

ClickOnce

ClickOnce has been a popular .NET deployment option for many years. It’s now supported for .NET Core 3.1 and .NET 5.0 Windows apps. We knew that many people would want to use ClickOnce for application deployment when we added Windows Forms and WPF support to .NET Core 3.0. In the past year, the .NET and Visual Studio teams worked together to enable ClickOnce publishing, both at the command line and in Visual Studio.

We had two goals from the start of the project:

  • Enable a familiar experience for ClickOnce in Visual Studio.
  • Enable a modern CI/CD for ClickOnce publishing with command-line flows, with either MSBuild or the Mage tool.

It’s easiest to show you the experience in pictures.

Let’s start with the Visual Studio experience, which is centered around project publishing. You need to publish to a Folder target.

Folder Targets

The primary deployment model we’re currently supporting is framework dependent apps. It is easy to take a dependency on the .NET Desktop Runtime (that’s the one that contains WPF and Windows Forms). Your ClickOnce installer will install the .NET runtime on user machines if it is needed. We also intend to support self-contained and single file apps.

.NET Prerequisites

 

You might wonder if you can still be able to take advantage of ClickOnce offline and updating features. Yes, you can.

Publish Settings

The same install locations and manifest signing features are included. If you have strict signing requirements, you will be covered with this new experience.

Now, let’s switch to the command line Mage experience.

The big change with Mage is that it is now a .NET tool, distributed on NuGet. That means you don’t need to install anything special on your machine. You just need the .NET 5.0 SDK and then you can install Mage as a .NET tool. You can use it to publish .NET Framework apps as well, however, SHA1 signing and partial trust support have been removed.

The Mage installation command follows:

dotnet tool install -g Microsoft.DotNet.Mage

The following commands configure and publish a sample application.

Produce First Deployment

The next command launches the ClickOnce application.

Install First Version

And then the familiar ClickOnce installation dialog appears.

Image FirstInstallClickoncePrompt

After installing the application, the app will be launched.

Image FirstVersionAppRuns

After re-building and re-publishing the application, users will see an update dialog.

Update Available

And from there, the updated app will be launched.

Note: The name of the Mage .NET tool will change from mage.net to dotnet-mage for the final release. The NuGet package name will remain the same.

This quick lap around ClickOnce publishing and installation should give you a good idea of how you might use ClickOnce. Our intention has been to enable a parity experience with the existing ClickOnce support for .NET Framework. If you find that we haven’t lived up to that goal, please tell us.

ClickOnce browser integration is the same as with .NET Framework, supported in Edge and Internet Explorer. Please tell us how important it is to support the other browsers for your users.

Windows Arm64

MSI installers are now available for Windows Arm64, as you can see in the following image of the .NET 5.0 SDK installer.

.NET 5.0 SDK Arm64 Installer

To further prove the point, I ran the dotnet-runtimeinfo tool on my Arm64 machine to demonstrate the configuration.

C:\Users\rich>dotnet tool install -g dotnet-runtimeinfo
You can invoke the tool using the following command: dotnet-runtimeinfo
Tool 'dotnet-runtimeinfo' (version '1.0.2') was successfully installed.

C:\Users\rich>dotnet-runtimeinfo
**.NET information
Version: 5.0.0
FrameworkDescription: .NET 5.0.0-rc.2.20475.5
Libraries version: 5.0.0-rc.2.20475.5
Libraries hash: c5a3f49c88d3d907a56ec8d18f783426de5144e9

**Environment information
OSDescription: Microsoft Windows 10.0.18362
OSVersion: Microsoft Windows NT 10.0.18362.0
OSArchitecture: Arm64
ProcessorCount: 8

The .NET 5.0 SDK does not currently contain the Windows Desktop components — Windows Forms and WPF — on Windows Arm64. This late change was initially shared in the .NET 5.0 Preview 8 post. We are hoping to add the Windows desktop pack for Windows Arm64 in a 5.0 servicing update. We don’t currently have a date to share. For now, the SDK, console and ASP.NET Core applications are supported on Windows Arm64.

Closing

We’re now so close to finishing off this release, and sending it out for broad production use. We believe it is ready. The production use that it is already getting at Microsoft brings us a lot of confidence. We’re looking forward to you getting the chance to really take advantage of .NET 5.0 in your own environment.

It’s been a long time since we’ve shared our social media pages. If you are on social media, check out the dotnet pages we maintain:

59 comments

Leave a comment

  • Avatar
    VB User1

    System.Windows.Forms.OpenFileDialog

    Setting a value for the “InitialDirectory” property has no effect when running ShowDialog.

    Works fine with .NET Core 3.1.

    Dim d As System.Windows.Forms.OpenFileDialog
    d = New System.Windows.Forms.OpenFileDialog
    d.InitialDirectory = "X:\WORK"
    d.ShowDialog() 'The other directory has opened.
    d.Dispose()
  • Avatar
    John King

    I sorry that I hate ClickOnce , because I never use a app that actually use ClickOnce !!!!!!
    Visual Studio has it’s own installer and it is writing use js/electron .
    Skype for win32 has it’s own installer.
    QQ/Wechat has it’s own installer.
    Finddler has it’s own installer.
    VsCode has it’s own installer.
    Even .Net Core has it’s own installer !!!!

    so microsoft make ClickOnce for what ? just be different than others?
    ClickOnce is the wrong action.
    the right action is to improve WXI , which dotnet core in use.

    app

    1. wxi globaltool
    2. vs integrated
    3. vs code integrated
    4. standalone binary / installer
    5. msbuild/dotnet cli (dotnet publish)

    feature

    1. simple package
      • choose location
      • progress bar
      • update tool intergrated (nuget package that can be use in update tool app, we can add owe own url to our own update serve)
      • [update server]update serve protocol : maybe an open source asp.netcore app that can publish new version.
      • knwn appdata location and asking to remove it when uninstall.
      • launch app at OS start.
      • register services
      • bundle dependency(.net core runtime, or other software)
    2. custom ui
      • chose backgound-color
      • chose backgound-image / slide
    3. custom action
      • add custom script/dll /UI-script to build process
    • Avatar
      Richard LanderMicrosoft employee

      Lots of choices! Visual Studio isn’t going to use ClickOnce. Visual Studio about 1000x too complicated. Also, ClickOnce is for apps not platforms (like .NET Core). Those are not great candidates. ClickOnce is best for enterprise apps with limited installation requirements. People like ClickOnce because it’s straightforward and has an update mechanism built-in. Very few other installers have this feature. It also supports HMAC signing for manifests. There are customers that require this signing feature.

      • Avatar
        Reilly Wood

        Notably, ClickOnce is still used by VSTO Office addins. I really, really hope this lets the Office team finally move past the .NET Framework requirement for .NET Office addins – it’s the only thing keeping many enterprise devs on Framework.

      • Avatar
        John King

        if you are in the team, then please consider my suggestion, make Wix the first choice for installer , by provide UI in visual studio, and .net core global tool, and use a Target to to opt-in the bundler process. read my comment above!

        not only that, like I suggestion, we should provide more nuget package to support this tool chain, like the update tool, we can write all the update logic in the nuget, and provide a webapi service to know should it be update, the server url can be easily configured.

        • Avatar
          Richard LanderMicrosoft employee

          I better understand your viewpoint now. We talked about this general idea before taking on the ClickOnce project. We knew that there were a lot of people that specifically wanted ClickOnce. As a result, we decided to add support for that. At this point, we’ll be looking for the largest clusters of feedback: improve ClickOnce further, create an option along the lines of what you’ve described or something else.

          Thanks for the feedback. Yes, I’m on the team.

    • Avatar
      Ran Qin

      ClickOnce is actually pretty handy and quite useful in corporate environment-where Microsoft/Azure does hold an edge against AWS/Google. Excel add-in is a good example-Excel Web is not good enough for power business users- otherwise why not use Google sheet for free? Then on Excel desktop, many companies use Excel Add-Ins to pull data together and analyze/view them in spreadsheet. These addins need frequent updates, but no one wants to go through MSI installation process for every update and ClickOnce is the best choice.

    • Avatar
      Vishnu Prasanth

      I think this explanation doesn’t quite fit. “ClickOnce” is not an installer tool or a packaging tool. It’s true it does both. But it is primarily a Deployment tool. You can have WiX or other MSI installers but you still need tools like SCCM. “ClickOnce” is one such tool, but works in a slightly reverse way.

      Consider a scenario where we are not connected to internet; we are in a private network. We have 100 machines where same software is run, and 100 employees are working. You fixed a bug and now we need all the 100 computers to have it. Are we going to walk to each computer and install? With ClickOnce, you just update the server version. Each of the 100 users gets notified next time they launch the application.

        • Avatar
          Daniel Kay

          Web forms will continue to be a part of the full .NET Framework – which is supported as it’s part of the Windows OS.

          The original ASP.NET MVC will similarly be part of the full framework, but it is concept compatible with ASP.NET Core MVC so a migration would be easier than web forms, though there is an ebook I believe for migrating web forms to Blazor

          So to be clear Web forms and original ASP.NET MVC still running on .NET framework and not .NET 5. ASP.NET Core MVC will run on .NET 5 along with Blazor which has been suggested as the best upgrade path for web forms

  • Avatar
    Martin Weeks

    Love the idea of ClickOnce in .NET 5, to be honest that’s only thing holding me back from migrating our company’s internal apps to .NET Core/.NET 5.
    Appreciate that MSIX is a bit more robust, but for quickly launching a basic app to a bunch of colleagues you can’t beat ClickOnce.

    It appears that it only works for .NET Core 3.1 right now, is that the case? I tried both .NET 5 and .NET Framework 4.8, and both wouldn’t let me past the ‘Finish’ button. It briefly flashes ‘Waiting…’ but does nothing.

    • Avatar
      John HartMicrosoft employee

      Hi Martin,

      I’d really like to learn more about the issue you’re seeing.

      The new ClickOnce Publish provider should work for both .NET Core 3.1 and 5.0 projects, especially for Framework-dependent deployments, we’re still working on getting the Self-contained deployment experience working a little better. For both configurations, you should be able to successfully create a ClickOnce publish profile and publish the project.

      The projects that are targeting .NET Framework 4.8 will still use the existing Wizard and Properties pages for publishing.

      When you say it will not let you past the Finish button, do you mean the Finish button is disabled? If so, that should indicate that there is validation error on the page and either a required field is missing or not the correct format but you should see a popup style window showing the exact error.

      If the Finish button is enabled, do you see a new Publish Profile show up under the Properties>PublishProfiles folder in Solution Explorer? If it does and you click on the Publish button on main Publish page, is that were you’re seeing the “Waiting…” flash by and nothing else happens? If you then click the Action on the Summary page to “Open the publish location”, does the folder exist and contain the setup?

      If you want to you can reach me through the dotnet@Microsoft.com email address if you prefer and we’ll figure this out.

      Thanks for the help!
      John Hart

      • Avatar
        Andrew Mansell

        Great to see ClickOnce support.

        We’re in the process of moving from .Net Framework to .Net Core, but some projects will take a while to migrate. In the meantime, we’ve converted most of the Framework projects to at least use the new SDK-style project format. The trouble is that doing so removes the original ClickOnce publish wizard.

        Will it be possible to publish .Net Framework projects that use the SDK project format?

          • Avatar
            Lance Bressler

            John,

            I’m in a similar situation to Andrew above. I was doing some experimenting and I noticed that I was able to use the new publish wizard for ClickOnce to publish an app which targeted netcoreapp3.1, then re-target to net472 (and tweak the target framework and prereqs in the publish profile) to publish against net472.

            For those of us stuck on .NET Framework but at least wanting the quality-of-life improvement of the SDK project format with the convenience of a ClickOnce wizard, any chance the new tooling could be adapted to support .NET Framework? I can’t imagine we’re the only slow-moving enterprise team that would benefit from this. Otherwise, maybe remove the ClickOnce option from the dialog for .NET Framework apps to avoid giving us false hope 😉

            Thanks!

          • Avatar
            John HartMicrosoft employee

            I should add that you can absolutely use the new Mage tool for .NET Framework projects also.

            As Richard mentioned in the blog: “You can use it to publish .NET Framework apps as well, however, SHA1 signing and partial trust support have been removed.”

          • Avatar
            John HartMicrosoft employee

            Thanks Lance for the feedback.

            Right now the new ClickOnce experience should be limited to just .NET Console and Desktop apps. I’ll look into why it’s showing up for 4.7.2 SDK style projects.

            We definitely didn’t intend to give you false hope but if we do continue to hear that customers, like your self and Andrew, like it or need it, we could consider supporting it for all versions.

  • Avatar
    A L

    During internal presentations you really should promote Blazor for Office teams! The new Office add-in platform is based on an embedded web site, interaction with client app and documents is accomplished using Office.js JavaScript APIs. The Office add-ins run cross platform, but currently can only be developed using JavaScript. Blazor could enable C#-based Office add-in development, also maybe provide a smoother upgrade path for current C#-based VSTO add-ins.

  • Avatar
    Holger Schwichtenberg

    The option to use ClickOnce in .NET is great!

    However, I cannot see the target “ClickOnce” in Visual Studio 2019 v16.8 Preview 4 (latest version, published yesterday) when I select “Build/Publish…”

    How can I activate this feature?

    If it is not available in the current Visual Studio release, it should be mentioned in the blog post 😉

        • Avatar
          Kalin Todorov

          Hi Richard,

          I check Folder, but the second page looks different – there is only option to choose a local folder.. Looks like it skips the Specific target page and goes into Location page.
          How can I fix that?

          Thanks,
          Kalin

          • Avatar
            John HartMicrosoft employee

            Hi Kalin,

            Can you tell me more about your project? What type of project is it? What is the target framework and finally what version of Visual Studio are you using?

            The ClickOnce publish provider should show up when using the latest Preview release of Visual Studio and your developing .NET 3.1 or 5.0 Console, Windows Forms or WPF App.

            If all is that is correct, then the extension may not have gotten installed correctly. If you want to you can reach me through dotnet@microsoft.com and I can help diagnostic it further.

            Thanks for the help!
            John

        • Avatar
          Kenneth Benson

          Speaking of Visual Studio, as .Net 5 only works with the 16.8 Preview of VS2019, is the any idea of when that will be out of preview and going live? I only have one pc capable of working with VS2019 (any version) and I have to keep it on the current live version to work with apps I have built (I tried once in the past doing a side-by-side and was very thankful I did a backup before trying it… all I can say about the experience is KABOOM).