Using the Web Application version number from an assembly (ASP.NET/C#)

69,881

Solution 1

Here is some code I use that supports getting the application's "main" assembly from either Web or non-web apps, you can then use GetName().Version to get the version.

It first tries GetEntryAssembly() for non-web apps. This returns null under ASP.NET. It then looks at HttpContext.Current to determine if this is a web application. It then uses the Type of the current HttpHandler - but this type's assembly might be a generated ASP.NET assembly if the call is made from with an ASPX page, so it traverses the HttpHandler's BaseType chain until it finds a type that isn't in the namespace that ASP.NET uses for its generated types ("ASP"). This will usually be a type in your main assembly (eg. The Page in your code-behind file). We can then use the Assembly of that Type. If all else fails then fall back to GetExecutingAssembly().

There are still potential problems with this approach but it works in our applications.

    private const string AspNetNamespace = "ASP";

    private static Assembly getApplicationAssembly()
    {
        // Try the EntryAssembly, this doesn't work for ASP.NET classic pipeline (untested on integrated)
        Assembly ass = Assembly.GetEntryAssembly();

        // Look for web application assembly
        HttpContext ctx = HttpContext.Current;
        if (ctx != null)
            ass = getWebApplicationAssembly(ctx);

        // Fallback to executing assembly
        return ass ?? (Assembly.GetExecutingAssembly());
    }

    private static Assembly getWebApplicationAssembly(HttpContext context)
    {
        Guard.AgainstNullArgument(context);

        object app = context.ApplicationInstance;
        if (app == null) return null;

        Type type = app.GetType();
        while (type != null && type != typeof(object) && type.Namespace == AspNetNamespace)
            type = type.BaseType;

        return type.Assembly;
    }

UPDATE: I've rolled this code up into a small project on GitHub and NuGet.

Solution 2

I find that the simplest one-liner way to get the version of your "main" assembly (instead of the dynamic one) is:

typeof(MyMainClass).Assembly.GetName().Version

Use your top-level class, which isn't likely to ever "change its meaning" or to be replaced as part of a refactoring effort, as MyMainClass. You know in which assembly this very class is defined and there can no longer be confusion as to where the version number comes from.

Solution 3

I prefer the Web.Config to store the current version of the site.

You can also try create an AssemblyInfo.cs file in the web application root that has the following:

using System.Reflection;
using System.Runtime.CompilerServices;
...
[assembly: AssemblyVersion("1.0.*")]
...

then access the value via the code like this:

System.Reflection.Assembly.GetExecutingAssembly()

Here is more informaiton on the AssemblyInfo class.

Solution 4

To add to the responders that have already posted. In order to get the assembly version in an ASP.Net web application you need to place a method in the code behind file similar to:

protected string GetApplicationVersion() {
    return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
}

In the ASPX page you want to display the version number simply place:

<%= GetApplicationVersion() %>

Solution 5

Just in case anyone is still interested; this should do the trick and should be a tad safer than just taking the BaseType of ApplicationInstance to get your hands on the Global.asax implementation.

Global.asax is always compiled into the same assembly as the assembly attributes from AssemblyInfo.cs, so this should work for all web applications that define a Global.asax.

For those that don't define their own Global.asax, it will fall back to the version of the generated global_asax type, which is always 0.0.0.0, and for applications that aren't web applications, it will just return no version at all.

Bonus; using the BuildManager class does not require an active HttpContext instance, which means you should be able to use this from application startup code as well.

public static Version GetHttpApplicationVersion() {
  Type lBase = typeof(HttpApplication);
  Type lType = BuildManager.GetGlobalAsaxType();

  if (lBase.IsAssignableFrom(lType))
  {
    while (lType.BaseType != lBase) { lType = lType.BaseType; }
    return lType.Assembly.GetName().Version;
  }
  else
  {
    return null;
  }
}
Share:
69,881
David Duffett
Author by

David Duffett

.NET Architect mainly focused on e-commerce at present...

Updated on August 28, 2020

Comments

  • David Duffett
    David Duffett over 3 years

    How do I obtain the version number of the calling web application in a referenced assembly?

    I've tried using System.Reflection.Assembly.GetCallingAssembly().GetName() but it just gives me the dynamically compiled assembly (returning a version number of 0.0.0.0).

    UPDATE: In my case I needed a solution that did not require a reference back to a class within the web application assembly. Jason's answer below (marked as accepted) fulfils this requirement - a lot of others submitted here don't.

    • Joe
      Joe over 12 years
      "... I needed a solution that did not require a reference back to a class within the web application assembly" - I'd be curious to know why you require this. I must say I think Yodan Tauber's solution looks a lot cleaner to me than the accepted answer - though I'd use typeof(Global) rather than an application-specific class name.
    • David Duffett
      David Duffett over 12 years
      @Joe - The method is in a shared assembly used in various solutions. Those applications may or may not be web applications. Either way, I need to be able to obtain the version number of the application, without actually referencing a class within the application.
    • CheapReference
      CheapReference over 12 years
      @David I find this a confusing and poorly phrased question even with your update. If the answer you selected is what youre really looking for then the question needs amending to avoid confusion. You should include the requirement that you could be being called by a non web app AND you have no knowledge of the HttpApplication (global.cs) type or any type within the assembly. If this is the case I would consider refactoring this interface.
  • David Duffett
    David Duffett about 15 years
    Retrieving the version from the actual web application is fairly easy, but can only be done in code behind - using System.Reflection.GetExecutingAssembly().GetName().Version.T‌​oString().I would think there would be some way of retrieving it from a referenced assembly though...
  • David Duffett
    David Duffett over 13 years
    This is the answer I was looking for - it seems to be the only answer that actually retrieves the version of the "Web Application" (rather than the version of the assembly you are in) without relying on recording the version in a config file. Nice.
  • Cristi Potlog
    Cristi Potlog almost 13 years
    The version of getWebApplicationAssembly didn't worked for me 'cause of an null IHttpHandler. I came up with a version using httpContext.ApplicationInstance instead of context.CurrentHandler.
  • Jason Duffett
    Jason Duffett almost 13 years
    Thanks for the tip Cristi. I guess context.CurrentHandler will only work for threads directly servicing asp.net requests, and only after the IHttpHandler has been created.
  • quentin-starin
    quentin-starin almost 13 years
    @Cristi: should have made that an answer
  • toddkitta
    toddkitta over 12 years
    Duffman, I'm curious as to why @yodan 's answer didn't quite hit the mark for you.
  • David Duffett
    David Duffett over 12 years
    @toddkitta: Yodan's answer would introduce a dependency from the referenced assembly BACK to a class in the web application. I would rather a solution that I can use that does not reference any classes within that project.
  • abatishchev
    abatishchev over 12 years
    @David: Probably you mean System.Reflection.Assembly.GetExecutingAssembly()... :)
  • David Duffett
    David Duffett over 12 years
    @TomDeloford - Looks like your answer requires a reference back to a class within the web assembly. Jason's answer doesn't require that.
  • Joe
    Joe over 12 years
    +1, this seems to me to be the obvious and cleanest solution, despite the OP's update stating that he wants a solution that does not require a reference to a class within the web application assembly (it would help if he said why). If it's an ASP.NET Web Application project, the obvious class to use would be Global, the code-behind base class for Global.asax.
  • Jason Duffett
    Jason Duffett over 11 years
    @CristiPotlog I've updated the project on GitHub to include your change to use httpContext.ApplicationInstance as CurrentHandler only works in WebForms, not MVC, applications.
  • Carra
    Carra about 11 years
    The only problem with this is that my dll with the getversion code can't access the top level dll that contains the mainclass.
  • Carra
    Carra about 11 years
    Finally, something that works! Tried by using the entryassembly which is null, using the httpcontext which is null and iterating my stacktrace which didn't work either.
  • mack
    mack almost 11 years
    Thanks, this is exactly what I was after.
  • Simon Tewsi
    Simon Tewsi about 10 years
    Does this apply to web applications or just Windows Forms applications?
  • Alex
    Alex about 9 years
    Storing application version in web.config makes it easy to retrieve from scripts outside of executing code. I'll be switching to web.config from AssemblyVersion attribute
  • YipYip
    YipYip almost 9 years
    You have hard-coded types in that code, so you'll need a reference. The solution should be something that can be put into a NuGet package and installed into any web application (and therefore, you can't use a hard-coded "MyHttpApplication"). My purpose is to create a reusable splash screen that shows app version and title (from AssemblyTitleAttribute).
  • CheapReference
    CheapReference almost 9 years
    As I stated in my answer the question states 'with no reference'. A type name is not a reference, therefore for a lot of people (and as the question is phrased) this is the easiest solution. No where does it mention being installed in any web application or a NuGet package.
  • YipYip
    YipYip almost 9 years
    I think the reason the question asks for "no reference" is because the code must exist in a separate library that must have no compile-time knowledge of the web applications it will be used in (today "MyHttpApplication", tomorrow "AnotherHttpApplication"). If you copy & paste the code directly into the web application (and hard code the type), then of course you have access to the types and you wouldn't need a reference.
  • CarlR
    CarlR over 8 years
    Which assembly contains the Guard,AgainstNullArgument method? It doesn't appear to be a standard one.
  • Jason Duffett
    Jason Duffett over 8 years
    Guard.AgainstNullArgument was a convenience method I was using in that project. It effectively looks like this: if (argument == null) throw new ArgumentNullException("Argument cannot be null");
  • Dave
    Dave over 5 years
    Simplified to:(HttpContext.Current.ApplicationInstance).GetType().BaseT‌​ype.Assembly.GetName‌​.Version.ToString()