This setup works great, but it can be confusing as there are a lot of moving parts. One of the most confusing parts is the amount of different version / build numbers you end up juggling. This post explains how to configure everything so that the same version number is used in every piece across the entire process.
Already we have achieved some parity and traceability: TeamCity versions now refer back to the source control revision number that was used to create that build. But we aren't done yet.
The next step is to ensure that the .NET assemblies created during this build use the same version number, and it requires a bit of custom scripting. In order to achieve this, we are going to add a build step to TeamCity that uses the AssemblyInfo task from MSBuild Community Tasks to generate an AssemblyInfo file on the fly that contains this version number.
Keeping the AssemblyVersion attribute separate means that we can overwrite this file during the build process and none of the other assembly attributes will be lost. Also, if you have multiple assemblies for your shared library, you can link each project to this same file so that you only have to overwrite it in one spot. Having the file in source control contain 0.0.0.0 as a version makes it obvious when there is a problem with the build process, or when a sneaky developer has released code that was built directly on their machine.
This script generates an AssemblyInfo file that contains an AssemblyVersion attribute with a value of $(BUILD_NUMBER). TeamCity automatically sets this variable to the current build number when it executes MSBuild. As long as you execute this script in a Build Step before your Visual Studio solution is compiled, your assemblies should end up with the same version from TeamCity.
TeamCity does come out of the box with a build feature called AssemblyInfo Patcher. This is obviously much simpler than the above and in simple scenarios can achieve the same results. However, if you are doing anything interesting with AssemblyInfo files (such as consolidating them among projects), the patcher won't be able to find the files correctly and update them. So I end up still going the complicated MSBuild route most of the time as it gives a lot more control. But if you can get away with the patcher, go for it!
If you set everything up correctly, you should have TeamCity, NuGet, and your .NET assemblies all referring to the same version. And, as a bonus, that version includes a pointer back to the source control revision that was used to build them. This level of traceability between these different artifacts will come in handy when you are troubleshooting build issues or trying to determine the audit trail of a particular change. Enjoy!