web-dev-qa-db-fra.com

Utilisation du numéro de version de l'application Web à partir d'un assembly (ASP.NET/C#)

Comment obtenir le numéro de version de l'application Web appelante dans un assembly référencé?

J'ai essayé d'utiliser System.Reflection.Assembly.GetCallingAssembly (). GetName () mais cela me donne juste l'assembly compilé dynamiquement (renvoyant un numéro de version de 0.0.0.0).

MISE À JOUR: Dans mon cas, j'avais besoin d'une solution qui ne nécessitait pas de référence à une classe au sein de l'assembly de l'application Web. La réponse de Jason ci-dessous (marquée comme acceptée) remplit cette exigence - beaucoup d'autres soumises ici ne le font pas .

53
David Duffett

Voici un code que j'utilise qui prend en charge l'obtention de l'assembly "principal" de l'application à partir d'applications Web ou non Web, vous pouvez ensuite utiliser GetName (). Version pour obtenir la version.

Il essaie d'abord GetEntryAssembly () pour les applications non Web. Cela renvoie null sous ASP.NET. Il examine ensuite HttpContext.Current pour déterminer s'il s'agit d'une application Web. Il utilise ensuite le type du HttpHandler actuel - mais l'assembly de ce type peut être un assembly ASP.NET généré si l'appel est effectué à partir d'une page ASPX, il traverse donc la chaîne BaseType du HttpHandler jusqu'à ce qu'il trouve un type qui ne se trouve pas dans l'espace de noms qu'ASP.NET utilise pour ses types générés ("ASP"). Il s'agit généralement d'un type dans votre assembly principal (par exemple, la page dans votre fichier code-behind). Nous pouvons alors utiliser l'assemblage de ce type. Si tout le reste échoue, revenez à GetExecutingAssembly ().

Il y a encore des problèmes potentiels avec cette approche mais elle fonctionne dans nos 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;
    }

MISE À JOUR: J'ai enroulé ce code dans un petit projet sur GitHub et NuGet .

49
Jason Duffett

Je trouve que le moyen le plus simple pour obtenir la version de votre assemblage "principal" (au lieu du dynamique) est:

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

Utilisez votre classe de niveau supérieur, qui ne risque pas de "changer sa signification" ou d'être remplacée dans le cadre d'un effort de refactorisation, comme MyMainClass. Vous savez dans quel assembly cette classe est définie et il ne peut plus y avoir de confusion quant à la provenance du numéro de version.

40
Yodan Tauber

Je préfère le Web.Config pour stocker la version actuelle du site.

Vous pouvez également essayer de créer un fichier AssemblyInfo.cs à la racine de l'application Web qui présente les éléments suivants:

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

puis accédez à la valeur via le code comme ceci:

System.Reflection.Assembly.GetExecutingAssembly()

Voici plus informaiton sur la classe AssemblyInfo.

27
Random Developer

À ajouter aux répondants qui ont déjà posté. Pour obtenir la version Assembly dans une application Web ASP.Net, vous devez placer une méthode dans le code derrière un fichier similaire à:

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

Dans la page ASPX, vous souhaitez afficher le numéro de version, placez simplement:

<%= GetApplicationVersion() %>
14
Amir Khawaja

Juste au cas où quelqu'un serait toujours intéressé; cela devrait faire l'affaire et devrait être un peu plus sûr que de simplement prendre le BaseType de ApplicationInstance pour mettre la main sur l'implémentation de Global.asax.

Global.asax est toujours compilé dans le même assembly que les attributs Assembly de AssemblyInfo.cs, donc cela devrait fonctionner pour toutes les applications Web qui définissent un Global.asax.

Pour ceux qui ne définissent pas leur propre Global.asax, il reviendra à la version du global_asax type, qui est toujours 0.0.0.0, et pour les applications qui ne sont pas des applications Web, il ne renverra simplement aucune version.

Prime; l'utilisation de la classe BuildManager ne pas nécessite une instance HttpContext active, ce qui signifie que vous devriez également pouvoir l'utiliser à partir du code de démarrage de l'application.

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;
  }
}
8
Ron Otten

HttpContext.Current.ApplicationInstance est dérivé de la classe dans le global.asax.cs. Vous pouvez faire ce qui suit

 var instance = HttpContext.Current.ApplicationInstance;
 Assembly asm = instance.GetType().BaseType.Assembly;
 System.Version asmVersion = asm.GetName().Version;

Il fonctionne à la fois dans ASP.NET (ASPX) et ASP.NET MVC

6
Andrei Schneider

J'ai rencontré un problème similaire et j'ai pensé que vous pourriez trouver la solution utile.

Je devais signaler la version actuelle de l'application (d'un projet d'application Web) à partir d'un contrôle serveur personnalisé, où le contrôle serveur était contenu dans une bibliothèque différente. Le problème était que les accesseurs "les plus faciles" de l'Assemblée ne fournissaient pas la bonne Assemblée.

  • Assembly.GetExecutingAssembly() a retourné l'assembly contenant le contrôle; pas l'Assemblée d'application.
  • Assembly.GetCallingAssembly() a retourné différents assemblys en fonction de ma position dans l'arborescence des appels; généralement System.Web, et parfois l'assembly contenant le contrôle.
  • Assembly.GetEntryAssembly() a renvoyé null.
  • new StackTrace().GetFrames()[idx].GetMethod().DeclaringType.Assembly récupère l'assemblage d'un cadre dans la trace de pile à l'index idx; cependant, en plus d'être inélégant, coûteux et sujet à des erreurs de calcul sur l'index de trame, il est possible que la trace de pile ne contienne pas tout appel à l'assembly d'application.
  • Assembly.GetAssembly(Page.GetType()) m'a marqué le App_Web_@#$@#$%@ Assemblage contenant la page générée dynamiquement. Bien sûr, la page dynamique hérite d'une classe de mon application Assembly, ce qui a conduit à la solution finale:

Assembly.GetAssembly(Page.GetType().BaseType)

Avec la référence d'assemblage en main, vous pouvez explorer la version par son nom:

var version = Assembly.GetAssembly(Page.GetType().BaseType)
                      .GetName()
                      .Version;

Maintenant, cette solution fonctionne parce que j'avais une référence à un type de l'assembly d'application. Nous n'utilisons pas de pages qui pas héritent d'un code derrière, donc cela s'avère efficace pour nous, mais votre kilométrage peut varier si les pratiques de codage de votre organisation sont différentes.

Bon codage!

4
kbrimington
Version version = new Version(Application.ProductVersion);
string message = version.ToString();
2
noname

Quelques informations ici: http://www.velocityreviews.com/forums/showpost.php?p=487050&postcount=8

dans asp.net 2.0, chaque page est intégrée à son propre assembly, donc seule la DLL dans laquelle AssemblyInfo.cs est intégré renverra la bonne réponse. ajoutez simplement une méthode statique à AssemblyInfo.cs qui renvoie les informations de version et appelez cette méthode à partir de vos autres pages.

- bruce (sqlwork.com)

Mais j'ai écrit une méthode simple pour ce faire:

    public static string GetSystemVersion(HttpServerUtility server)
    {
        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
        doc.Load(server.MapPath("~/web.config"));
        System.Xml.XmlNamespaceManager ns = new System.Xml.XmlNamespaceManager(doc.NameTable);
        ns.AddNamespace("bla", "http://schemas.Microsoft.com/.NetConfiguration/v2.0");

        System.Xml.XmlNode node = doc.SelectSingleNode("/bla:configuration/bla:system.web/bla:authentication/bla:forms[@name]", ns);

        string projectName = "";
        if (node != null && node.Attributes != null && node.Attributes.GetNamedItem("name") != null)
            projectName = node.Attributes.GetNamedItem("name").Value; //in my case, that value is identical to the project name (projetname.dll)
        else
            return "";

        Assembly assembly = Assembly.Load(projectName);
        return Assembly.GetName().Version.ToString();
    }
1
Seiti

La question indique sans référence (instances), il n'a pas (à l'origine) dit sans connaissance des types d'applications Web.

MODIFIER l'OP a été clarifié pour indiquer que oui, ils ne nécessitent vraiment aucune connaissance des types au sein de l'assembly Web appelant, donc la réponse est appropriée. Cependant, j’envisagerais sérieusement de remanier une telle solution de sorte que la version soit transmise à l’autre Assemblée.

Pour la plupart des personnes dans ce scénario si vous connaissez le type HttpApplication personnalisé:

 typeof(MyHttpApplication).Assembly.GetName().Version

et si vous n'avez qu'un type généré dynamiquement:

 typeof(DynamiclyGeneratedTypeFromWebApp).BaseType.Assembly.GetName().Version

Arrêtez de me voter pour cette réponse :)

1
Tom Deloford

Si vous recherchez cela à partir d'un contrôle Web, un hack consiste à trouver le type de la page code-behind (c'est-à-dire la classe qui hérite de System.Web.UI.Page). C'est normalement dans l'assemblage Web du consommateur.

Type current, last;
current = Page.GetType();
do
{
    last = current;
    current = current.BaseType;
} while (current != null && current != typeof(System.Web.UI.Page));
return last;

J'espère qu'il y a une meilleure façon.

1
Matt Woodard