Asp.Net 5 Semantic Versioning - c#

It seems that versioning works differently than in previous versions of .Net. The project.json seems to use semantic versioning (from what I have seen online) with the format Major.Minor.Patch-Special.
Does this replace the Assembly version idea or add to it? Or does it just get used with Nuget.
How does one access the version during runtime. I came across Nuget.SemanticVersion object online in the Microsoft.Framework.Runtime package but I can't find out how to retrieve it in code.
Is there a programmatic way to update this value on a build or just custom scripts?

I wouldn't say that versioning has changed in a particularly dramatic way. In a version number x.y.z, the "x" means "big changes / breaking changes," the "y" means "minor additions and fixes," and the "z" means "very minor fixes." That's pretty close to what Semantic Versioning (SemVer) states.
In a project.json-based project, there is only one place to specify the version, and that's in the project.json file itself. That one version is a SemVer (e.g. x.y.z-prerel) and is used for the NuGet package version and the assembly version, and the assembly informational version. If you've explicitly set the assembly version or informational version in the assembly, those will be respected and not overridden. (You can see the code here.)
At runtime you can read the assembly version through reflection (just like you always could).
When running in a DNX application there's also an ILibraryManager interface that you can use to inspect the running application. However, that's a fairly advanced scenario.
Lastly, in the project.json file you can hard-code the x.y.z part of the version, e.g. 1.2.3 but you can also specify a * for the pre-release specifier, e.g. 1.2.3-*. If you use * for the pre-release specifier, you can set an environment variable named DNX_BUILD_VERSION to specify the value of the *, e.g. beta1 or rc2-54289.
There are some feature requests logged to allow more flexibility in specifying the entire version number externally.

Related

Defining console app version, and referencing version information from app

I have a .NET 5.0 console application. How can I create a version resource and then display that version in my application?
In the past, I have seen an AssemblyInfo.cs file. But I don't see anything like that in my new project.
I had to solve this problem recently: how do you know which version of a tool is deployed? And how can you automate the version number, so you don't accidentally use an old version?
In the past, that information was stored as attributes in AssemblyInfo.cs. In .NET Core, those attributes are now generated by project properties at runtime.
Andrew Lock explains how the various properties like Version, VersionPrefix, VersionSuffix,AssemblyVersion FileVersion, PackageVersion, InformationalVersion are used.
The most important ones are Version, VersionPrefix and VersionSuffix. That's because Version is used as the default for the other ones. Version in turn can be calculated as VersionPrefix-VersionSuffix if there's no explicit value.
Quoting the article:
The Version property is the value most commonly set when building .NET Core applications. It controls the default values of all the version numbers embedded in the build output, such as PackageVersion and AssemblyVersion so it's often used as the single source of the app/library version.
If you use System.Commandline, the version info displayed by --version is the InformationalVersion whose default comes from Version.
The default VersionPrefix is 1.0.0 and the default suffix is empty, resulting in version 1.0.0.
*Formulas
The nice thing is that the properties can have formulas. I was able to automatically generate a date-related version number simply by adding this to a csproj that contains no other version information
<VersionSuffix>$([System.DateTime]::UtcNow.ToString(`yyyyMMdd-HHmm`))</VersionSuffix>
Each time I build my tools now I get versions like 1.0.0-2021061501836
Overriding the properties
The project values can be overridden during build, either by specifying an explicit version suffix, or specifying an explicit value for the project properties, eg :
dotnet build --configuration Release --version-suffix preview2-final
Or
dotnet build --configuration Release /p:Version=1.2.3-preview2-final
This way, an automated release pipeline can specify a new version that overrides anything set in the project file

Deploy assembly as part of .Net Framework

I have an assembly (MYASM.dll) targeting .NETFramework 4.0 (with a strong name)
I want to deploy this assembly in a way it is part of .NETFramework (or the whole system thinks it is) on target machine.
By that I mean:
.NET runtime sees it at it sees System.dll (no need to deploy locally or provide a reference path)
MSBuild sees it when I do <Reference Include="MYASM" /> without needing a hintpath
User is able to make Add reference in Visual Studio and that introduces <Reference Include="MYASM" /> without the strong/full name
I have solved 1. (and apparently 2.) by adding it to the GAC. But this is apparently not sufficient.
I have partially solved 3. by putting my assembly in a special folder ([INSTALLFOLDER]\lib) and set registryKey HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0\AssemblyFoldersEx\MyAssemblies
Then I can do Add reference, but then I get:
<Reference Include="MYASM, Version=1.1, Culture=neutral, ..." /> in my csproj instead of just <Reference Include="MYASM" /> as I'd like.
With the second approach, if I manually edit the csproj, everything is OK, but I can't ask my users to do that.
What should I do here?
[EDIT] apparently it’s not obvious I have my own MSI. But yes I have. I don’t control users machines with a magic wand
No, you've taken this as far as it can go. It isn't actually that obvious how VS figures out to put the partial assembly name into the project file. This is not public code and can't be tampered with. Pretty sure it does not use a white-list and it can't pay attention to the reference assembly location.
Most likely detail is the PublicKeyToken of the assembly. The framework assemblies always have to exact same value for them, b77a5c561934e089. Its value is even prescribed in the CLI spec (Ecma-335). Next most likely by a considerable distance is the signing certificate, identifying the assembly as owned by Microsoft. Both however present the exact same problem, you can't get the private key that is required to strong-name or sign the assembly. They are locked inside a vault in Redmond, only trusted build engineers have access to them.
There is another nasty little detail you are overlooking, you are not nearly scared enough of DLL Hell. Cold hard fact is that if you ever expose the assembly in the GAC on another machine that is not in your control then you can never change it again. You can no longer modify the public interface of the assembly. Can't add a new public method or type, can't modify the arguments and return type of a method, can't add an enum member, etc. Even harsher, something Microsoft worries about, is that you can't really change private and internal members either. Programmers have a knack for using Reflection to poke around, terrific bug fixing tool. But at least you can tell them "don't do that!".
Making such modification requires increasing the [AssemblyVersion]. Now you get a different kind of DLL Hell, the machine might not have been updated by your installer. Or worse, a solution uses projects that have different references. Microsoft had to solve this problem for framework assemblies, they did so by modifying the CLR. Automatically forwarding old versions to new ones. The basic reason why using an assembly built for .NET 2.0 can be used in a .NET 4.x project. You can't get that kind of service for your own DLL.
"Don't do it" is the only good advice, getting in DLL Hell trouble is however a terrific learning experience I can recommend for anybody. Hell has to be experienced to be feared.
Best advice is to publish a Nuget package. They do the exact opposite, never deployed in the GAC and version numbers change very rapidly. But always available when a programmer needs it.
There are a few ways...
1) is to create a new setup and package this for the framework you target. You can Package this and have it deployed using the domain controller. When your users log in the domain will update the packages, this way you'll be able to deploy your software to specific users and or user groups. Depending on your infrastructure you'll have a software management infrastructure that you can use (2 links included).
2) Create a NuGet package if you're targeting developers. If your organisation host your own NuGet server limiting the distribution. Add the Package source to Visual studio open the Options Page, type NuGet in the search field and set the URL/ UNC path.
3) use OneClick deployment, this allows you to have the application download the updated dll's and install them on the machine. It requires a Code Sign certificate but you're probably signing your code anyway (better for Anti-Virus tools if you do).
Now linking your MyAsam.dll will be done by the application linking definition or IoC container. Basically, if it finds the dll and no version is defined it will take the first one it finds I think the order is 1 AppFolder, 2 GAC, 3 Path, not sure. This "take what you find" is generally referred to as "DLL-Hell", The NuGet and OneClick solution works best in this as You will always get the Updated dll that works for the application. Placing the DLL in GAC is going to get problematic if you have moe than 1 application using your dll and both need the "right" version where the "right version" differes between them....
If you have the source code available for MYASM.dll, then I would prefer adding a project reference to your consuming application. When doing so, Visual Studio shall create a GUID for all the referenced project.

Adding properties to DLL after it's been built

I have a set of C# DLLs that have already been built--they've gone through the process of setting the version numbers in AssemblyInfo.cs, they've been formally built by our configuration management team, and they've been archived off where they belong so we don't lose the built DLLs.
Now I have to take a collection of these DLLs and package them up into a couple umbrellas, and these umbrellas can have different versions. For example:
Collection1 v1.0 Collection1 v1.1 Collection2 v1.0
---------------- ---------------- ----------------
MyDll1.dll v1.0 MyDll1.dll v1.0 MyDll1.dll v1.0
MyDll2.dll v1.1 MyDll2.dll v1.2 MyDll4.dll v1.0
MyDll3.dll v1.2 MyDll3.dll v1.2 MyDll5.dll v1.1
Looking through each DLL's properties, I already see its usual fields, including File version and Product version set to its respective version number.
What I would like to do is to capture the collection name and version number somewhere in order to show which collection it belonged to when it was packaged up. Again, the DLLs are already built, so I can't add anything to AssemblyInfo.cs now.
Ideally, this would be another property that shows up on the DLL's Details tab, and it would be something that I can inject into a DLL using some tool, but I'm not familiar with any Windows API calls that can add/modify these properties.
Keep in mind this is for internal releases of these DLLs so we can keep track of what we have installed ourselves during development; the ones that will be packaged and released "for real" would be the pristine ones formally built and won't have any properties added into them.
EDIT: Third-party tools will be difficult to use; if it doesn't come with Windows or Visual Studio, then it would be strongly preferred if it's something that can be written very quickly.
Thanks.
You can try ILMerge tool provided by Microsoft: http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx
Just create a DLL containing all custom assembly-level attributes you want to merge. Then run ILMerge specifying MyDll.dll as a primary assembly and your DLL with custom attributes as a secondary one. Don't forget to specify /copyattrs flag.
Full ILMerge documentation can be found here: http://research.microsoft.com/en-us/people/mbarnett/ilmerge.doc
If your input assembly is signed, you also have an option to provide .snk file, so that your output assembly will be signed as well.
Another option is to use a combination of ILdasm/ILasm tools, which seem to be part of the SDK. But it requires a little bit more efforts because you need to modify IL code in between.

How do I make automatic version numbers work in Visual Studio

I've been asked to add automatic numbering to assemblies in our code library. I've been changing versions from the default 1.0.0.0 to 1.0.* like this:
[assembly: AssemblyVersion("1.0.*")]
It generates a number as I'd like.
However, the code library has many hundreds of DLLs, with many referencing each other. Now when I compile some projects they complain that the version of a DLL needed by a referenced component is not correct and they won't build :(
How can I make this work? We need it so that when a DLL at the bottom of our code library hierarchy is compiled, all other DLLs that reference it work correctly without needing recompiling.
The error I get is like this:
Error 1 CA0058 : The referenced assembly 'Library1, Version=1.0.4146.17993
, Culture=neutral, PublicKeyToken=d9c65edd2096ad48' could not be found. This assembly
is required for analysis and was referenced by:
D:\Work\Source Code\Library\Library2\bin\Release\Library2.dll.
The version 1.0.4146.17993 is not correct - the DLL has a higher value. The DLLs are set to Copy Local because the software we deliver requires it (don't ask why). The DLL that's copied locally is the one with the higher version number, which is the one we want it to be.
So far I've tried changing the references to set the "Specific Version" flag to false but this didn't help.
The version numbers that VS generates when you use the 1.0.* syntax are not necessarily going to increment in sequence. The documentation has this to say (emphasis added):
You can specify all the values or you can accept the default build number, revision number, or both by using an asterisk (). For example, [assembly:AssemblyVersion("2.3.25.1")] indicates 2 as the major version, 3 as the minor version, 25 as the build number, and 1 as the revision number. A version number such as [assembly:AssemblyVersion("1.2.")] specifies 1 as the major version, 2 as the minor version, and accepts the default build and revision numbers. A version number such as [assembly:AssemblyVersion("1.2.15.*")] specifies 1 as the major version, 2 as the minor version, 15 as the build number, and accepts the default revision number. The default build number increments daily. The default revision number is random.
If it's vital that you get versioning exactly right, I highly recommend that you use a third-party solution. The Build Version Increment add-in is excellent.
What you want to do is manage the assembly version yourself. Only increment this when you make a breaking change to the assembly's public interface. Changing this attribute makes your assembly incompatible with other assemblies that reference it, even if you didn't change a thing in your code. Instead, the only thing you want to automatically increment is the assembly file version. Unlike the assembly version, this attribute is not checked by the CLR to determine compatibility.
The Build Version Increment add-in gives you the kind of fine-grained control over what is incremented that you need to get this right. It's what probably should be included in VS to begin with.
This is actually a pretty indepth question, and I hope someone answers this in detail for you, but my 2 cents after you get the assembly infos under control is you should look at using Nuget to manage your dependencies. This way when team A releases v2 of assembly X, all they do is put it on your Nuget repo (network share probably) and then you can basically right click < update inside your projects that consume the DLLs.
I would also recommend looking at http://semver.org/ and use Semantic Versioning, if you don't want to follow a system like this one (or institute a similar standard for your shop), it's probably not worth even trying to version your DLLs you're just going to give yourself massive headaches. However using Semantic Versioning will make your version numbers actually MEAN something. And not just be whatever felt like being tagged onto the current version.
Note that the Revision number is not random. It is the time of day of the build. The Build is the day number.
See VisualStudio: translating a build version to a calendar date
delete your reference (in the project that uses it) and re-do it by pointing to the project reference type.
PS: If when you are adding the reference, you choose browse and point to a place the dll will always be, the reference will not be broken!
> However, the code library has many hundreds of DLLs,
If it is ok for you that all source projects and their generated dll-s have the same version-number you can put the versionnumber into one file that is shared between all dlls as described in
shared AssemblyInfo.cs. So you (or the version-number-generator you are using) have to update only one file if there is a new relase/Version.
This does not answer your original question but may be a simple workaroud for the dependency problem.

AssemblyInfo.cs , .net applications versions

I would like to keep version in my .net applications and let the .net to manage it. I don't really understand how it works. Is the version number per project ? How .net manages versions? If anyone could please explain it briefly i will be grateful.
What I usually do is to keep a SolutionInfo.cs that contains all the attributes that are common for the projects of my solution, for example the version-number. I keep this file in the solution root.
I then link that file into the project (right click the project and Add->Exsiting item... -> Add as link (the little arrow on the add button)).
I then can increment the version number in a single place and it will be updated in all the projects that links that file.
For more information on that for example see: http://jebsoft.blogspot.com/2006/04/consistent-version-numbers-across-all.html
The version number is per-project (.csproj file), so per built .dll or .exe file. The version number is embedded in the .dll or .exe, and can be viewed using (for example) Windows Explorer by right-clicking on the file and selecting Properties.
MSDN contains an explanatory article about how to use AssemblyVersion and AssemblyFileVersion at http://support.microsoft.com/kb/556041
[AssemblyVersion] is a very big deal in .NET. Every type in your program is imprinted with the assembly version, it is part of the type identity. In other words, when the version of your type changes then you should also change the assembly version. This forces all other assemblies that use your type to be recompiled.
One thing you can do is to let the build system automatically increment the version. You can't call this 'managing the version' by any stretch of imagination. Because now just rebuilding your assembly, even without making any change in the source code, will make your assembly incompatible with other code that uses the types in that assembly.
Clearly this can only work well if you recompile all the code in your solution.
Well, that's not great unless you like sword fighting. Furthermore, sometimes you want to make a simple bug-fix in your code. The result is an assembly that's still 100% compatible with the original version. And you don't need nor want to recompile everything else that uses it. You just want to send that one assembly to your customer. Clearly that can only work well if you don't let the version increment automatically.
So what you really need is some kind of tool that can magically determine that your source code, the publicly visible part of it, is no longer compatible with a previous version. Or the changes you made to the non-visible part of it are changing the behavior of the code too much to disallow other code that use your types to continue to use it without some changes in their code.
There's only one tool that I know of that can do this, the one we have between our ears.

Categories