Подтвердить что ты не робот

Использование номера версии веб-приложения из сборки (ASP.NET/C#)

Как получить номер версии вызывающего веб-приложения в ссылочной сборке?

Я попытался использовать System.Reflection.Assembly.GetCallingAssembly(). GetName(), но он просто дает мне динамически скомпилированную сборку (возвращает номер версии 0.0.0.0).

ОБНОВЛЕНИЕ: В моем случае мне понадобилось решение, которое не требовало ссылки на класс в сборке веб-приложений. Ответ Джейсона ниже (отмеченный как принятый) выполняет это требование - многие другие, представленные здесь, не делают.

4b9b3361

Ответ 1

Вот некоторый код, который я использую, который поддерживает получение "основной" сборки приложения из веб-приложений или приложений, отличных от веб-сайтов, затем вы можете использовать GetName(). Версия для получения версии.

Сначала он пытается GetEntryAssembly() для не-веб-приложений. Это возвращает значение null в ASP.NET. Затем он просматривает HttpContext.Current, чтобы определить, является ли это веб-приложением. Затем он использует тип текущего HttpHandler, но сборка этого типа может быть сгенерированной сборкой ASP.NET, если вызов выполняется с помощью страницы ASPX, поэтому она пересекает цепочку BaseType HttpHandler, пока не найдет тип, который не находится в пространство имен, которое ASP.NET использует для своих сгенерированных типов ( "ASP" ). Обычно это будет тип вашей основной сборки (например, Страница в вашем файле с кодом). Затем мы можем использовать Собрание этого типа. Если все остальное не удается, вернитесь к GetExecutingAssembly().

По-прежнему существуют потенциальные проблемы с этим подходом, но он работает в наших приложениях.

    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: Я перевел этот код в небольшой проект GitHub и NuGet.

Ответ 2

Я нахожу, что самый простой однострочный способ получить версию вашей "основной" сборки (вместо динамической):

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

Используйте свой класс верхнего уровня, который вряд ли когда-либо "изменит его значение" или будет заменен как часть усилий по рефакторингу, как MyMainClass. Вы знаете, в какой сборке этот самый класс определен, и больше не может быть путаницы относительно того, откуда приходит номер версии.

Ответ 3

Я предпочитаю, чтобы Web.Config сохранял текущую версию сайта.

Вы также можете попробовать создать файл AssemblyInfo.cs в корневом веб-приложении, который имеет следующее:

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

затем получите доступ к этому значению с помощью кода:

System.Reflection.Assembly.GetExecutingAssembly()

Подробнее informaiton в классе AssemblyInfo.

Ответ 4

Чтобы добавить к респондентам, которые уже опубликовали. Чтобы получить версию сборки в веб-приложении ASP.Net, вам нужно поместить метод в код за файлом, похожий на:

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

На странице ASPX вы хотите отобразить номер версии просто:

<%= GetApplicationVersion() %>

Ответ 5

На всякий случай кого-то все еще интересует; это должно сделать трюк и должно быть чуть безопаснее, чем просто взять BaseType of ApplicationInstance, чтобы получить доступ к реализации Global.asax.

Global.asax всегда компилируется в ту же сборку, что и атрибуты сборки из AssemblyInfo.cs, поэтому это должно работать для всех веб-приложений, которые определяют Global.asax.

Для тех, кто не определяет свой собственный Global.asax, он вернется к версии сгенерированного типа global_asax, который всегда 0.0.0.0, а для приложений, которые не являются веб-приложениями, он будет просто не возвращайте версию вообще.

Bonus; использование класса BuildManager не требует активного экземпляра HttpContext, что означает, что вы также должны использовать его из кода запуска приложения.

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;
  }
}

Ответ 6

HttpContext.Current.ApplicationInstance выводится из класса в global.asax.cs. Вы можете сделать следующее

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

Он работает как в ASP.NET(ASPX), так и в ASP.NET MVC

Ответ 7

Я столкнулся с подобной проблемой и подумал, что вы можете найти полезное решение.

Мне нужно было сообщить текущую версию приложения (проекта веб-приложения) из настраиваемого серверного элемента управления, где серверный элемент управления содержался в другой библиотеке. Проблема заключалась в том, что "самые простые" сборщики сборки не обеспечивали правильную сборку.

  • Assembly.GetExecutingAssembly() возвращает сборку, содержащую элемент управления; а не сборку приложений.
  • Assembly.GetCallingAssembly() возвратили разные сборки в зависимости от того, где я находился в дереве вызовов; обычно System.Web, а иногда и сборку, содержащую элемент управления.
  • Assembly.GetEntryAssembly() возвращен null.
  • new StackTrace().GetFrames()[idx].GetMethod().DeclaringType.Assembly извлекает сборку кадра в трассировке стека по индексу idx; однако, помимо того, что он нечеткий, дорогой и склонный к просчету по индексу кадра, трассировка стека может не содержать вызовов в сборке приложений.
  • Assembly.GetAssembly(Page.GetType()) зачислил мне сборку [email protected]#[email protected]#$%@, содержащую динамически сгенерированную страницу. Конечно, динамическая страница наследует класс из моей сборки приложения, поэтому это привело к окончательному решению:

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

С помощью ссылки на сборку вы можете сверлить версию с помощью ее имени:

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

Теперь это решение работает, потому что у меня есть ссылка на тип из сборки приложения. Мы не используем страницы, которые не наследуются от кода позади, поэтому для нас это эффективно, но ваш пробег может отличаться, если ваши методы кодирования в организации отличаются.

Счастливое кодирование!

Ответ 8

Version version = new Version(Application.ProductVersion);
string message = version.ToString();

Ответ 9

Информация здесь: http://www.velocityreviews.com/forums/showpost.php?p=487050&postcount=8

в asp.net 2.0 каждая страница встроена в свою собственную сборку, поэтому только dll AssemblyInfo.cs встроена в завещание верните правильный ответ. просто добавьте статический метод для AssemblyInfo.cs, который возвращает информацию о версии и вызывает этот метод из ваших других страниц.

- bruce (sqlwork.com)

Но я написал простой способ сделать это:

    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();
    }

Ответ 10

Если вы ищете это из веб-элемента управления, один взлом - это поиск типа страницы с кодом (например, класс, который наследуется от System.Web.UI.Page). Обычно это происходит в пользовательской веб-сборке.

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

Я надеюсь, что есть лучший способ.

Ответ 11

В вопросе говорится, что без ссылки (экземпляры) он не сказал (изначально), не зная о типах веб-приложений.

РЕДАКТИРОВАТЬ ОП разъяснил, что да, они действительно не требуют знания типов внутри вызывающей веб-сборки, поэтому ответ уместен. Однако я бы серьезно подумал о реорганизации такого решения, чтобы версия передавалась в другую сборку.

Для большинства людей в этом сценарии, если вы знаете пользовательский тип HttpApplication:

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

и если у вас есть только динамический сгенерированный тип:

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

Прекратите голосовать за этот ответ:)