Quantcast
Channel: Rick Strahl's Web Log
Viewing all articles
Browse latest Browse all 665

Rolling Forward to Major Versions in .NET

$
0
0

I'm currently playing around with .NET 8 RC Preview release and upgrading several of my applications to run under .NET 8. In my early testing, moving to .NET 8 been very much a painless operation.

But - especially for my desktop applications - I wanted to start running the existing .NET 7 targeted applications under the .NET 8.0 preview to see if I'd run into any issues.

Turns out .NET has the ability to define a RollForward policy that lets you move an application to a newer version than it was compiled under. You can specify this value in the .csproj file using a <RollForward>Minor</RollForward> key in the <PropertyGroup> section.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>    
    <TargetFramework>net7.0-windows</TargetFramework>
    <RollForward>LatestMajor</RollForward>
  <PropertyGroup>    
</Project>  

Here are the options you can specify for RollForward (from Microsoft):

ValueDescription
MinorDefault if not specified.
Roll-forward to the lowest higher minor version, if requested minor version is missing. If the requested minor version is present, then the LatestPatch policy is used.
MajorRoll-forward to the next available higher major version, and lowest minor version, if requested major version is missing. If the requested major version is present, then the Minor policy is used.
LatestPatchRoll-forward to the highest patch version. This value disables minor version roll-forward.
LatestMinorRoll-forward to highest minor version, even if requested minor version is present.
LatestMajorRoll-forward to highest major and highest minor version, even if requested major is present.
DisableDon't roll-forward, only bind to the specified version. This policy isn't recommended for general use since it disables the ability to roll-forward to the latest patches. This value is only recommended for testing.

The Minor default is sensible - it basically tries to find the next higher minor version installed, if any. LastestMinor on the other hand will find the latest higher minor version installed.

In my scenario however, I want to roll forward the lastest major version, so for my scenario I'd want to use LatestMajor, which effectively says - use the latest version of the .NET Core runtime available.

So my app is compiled to .NET 7.0 but I would like to run on the .NET 8.0 RC, so I expected the following to work:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>    
    <Title>Markdown Monster</Title>
    <Version>3.0.4.1</Version>
    
    <TargetFramework>net7.0-windows</TargetFramework>
    <RollForward>LatestMajor</RollForward>
    ...
  <PropertyGroup>    
  ...
</Project>  

You can also use the --roll-forwardcommand line option to specify the roll forward mode at runtime or set these modes in an optional global.json of your project. More info here)

It turns out that does not work. The above does not roll forward to the .NET 8.0 RC Preview and the application continues to run under .NET 7.0.

The problem is that the current release is net8.0.0-rc-123419.4 which is a pre-release version, and preview releases are excluded from automatic roll forward operations.

To make RollForward work with a pre-release version an additional step is needed: It involves creating an Environment variable that enables the functionality:

$env:DOTNET_ROLL_FORWARD_TO_PRERELEASE=1
#Run MM
MarkdownMonster
# or mm

Alternately you can add the environment variable to your machine's environment settings.

Add a global Environment Variable

Now with that in place you can launch the pre-release version of .NET 8.0 RC even though the application is compiled for .NET 7.0.

Markdown Monster About Screen with Prerelease for .NET 8.0 RC

Yay!

Unlike the <RollForward> project option which is project specific and can be compiled in, the DOTNET_ROLL_FORWARD_TO_PRERELEASE is an add-on to the <RollForward> project flag that is externally applied. The environment variable has no effect unless <RollForward> behavior is enabled in the first place, so it doesn't all of a sudden roll forward any .NET Core application to .NET 8.0.

Running a Preview Rollforward Release? Is this a good idea?

For a production application this obviously not a great idea. But since you can only enable roll forward to a pre-release version with an environment variable, users who want to try this would have to be pretty explicit in doing this.

That said, I've found that the last few .NET Core releases have been very good about not breaking existing functionality, so I've felt pretty comfortable running application in this sort of preview environment at least locally for myself.

And true to form .NET 8.0 RC doesn't disappoint!

I have 3 separate desktop applications that are in production and running them under .NET 8.0 RC, and none of them have any issues that I've been able to pick up compared to running under 7.0. I did notice that one of my apps - West Wind WebSurge - is seeing a nice performance boost and resource reduction running under .NET 8.0 however which is very welcome.

Doing it right: Migrate to .NET 8.0 proper

Now, the right way to do this is to actually take the applications and properly target them to net8.0 for each project.

As a matter of fact, I did that with Markdown Monster first, to ensure that there weren't any obvious API difference in the framework libraries. Just be forewarned, that you may end up having to re-target multiple projects. At minimum all top level projects, and if you want to do it right probably also your child projects. In Markdown Monster's case this involves:

  • The main EXE project
  • 3 Addin Projects
  • 2 Test Projects
  • 2 Support libraries that are compiled in

To do this right is not a 5 minute affair. But if you stick to the top level project(s) you can get this done fairly quickly.

The re-targeting allows the compiler to find actual runtime call changes, but neither Markdown Monster or WebSurge including their compiled dependencies showed any hard API breaks, although there were a few additional warnings related to crypto APIs and deprecated old Http clients that were not flagged in previous versions.

Once compiled I can easily run the application under .NET 8.0 preview and that works fine without any RollForward semantics at all. Prim and proper and all!

So, why use RollForward?

So why not compile for .NET 8.0 and ship that in the first place?

Well, I didn't want to wait until November when .NET 8.0 officially ships - until then the runtimes are in Preview, and for commercial software installation, it wouldn't be appropriate to install a preview version of the runtime.

By using the above RollForward plus an Environment variable, I can set up my environment locally to run on .NET 8.0, while leaving all the old .NET 7.0 runtime compilation and behavior for the release version in place. It gives me a chance to test, and also some of my more enthusiastic users to do the same and report any issues they might be running into. I can point them at directions on how to run on a preview version of .NET as described in the MM documentation.

When .NET 8.0 ships RTM, the RollForward directive automatically kicks in and so if .NET 8.0 (released) is installed on the machine it'll automatically be used.

By then however I would also have a newer version of the software that's explicitly compiled for .NET 8.0, so this would only apply to users who haven't upgraded, but then could still take advantage of the improved features of a new runtime.

Summary

You have to appreciate that .NET supports the ability to specify how applications roll forward with so many options. And appreciate that understanding all the different combinations is going to take a minute to figure out which one is appropriate. But I'm very happy that I'm able to keep creating releaseable builds that I can also run on the latest unreleased version of .NET, without having to manage to separate compilation targets.

When .NET 8.0 gets closer to release I'll switch over all projects to .NET 8.0 and update libraries etc. for a complete upgrade. But for now I can use my tools as is on the new version of .NET...

Resources

this post created and published with the Markdown Monster Editor
© Rick Strahl, West Wind Technologies, 2005-2023
Posted in .NET  

Viewing all articles
Browse latest Browse all 665

Trending Articles