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

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

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

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

Ответы [ 11 ]

48 голосов
/ 26 января 2011

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

Сначала он пытается использовать GetEntryAssembly () для не-веб-приложений. Это возвращает ноль в 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 .

40 голосов
/ 02 ноября 2010

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

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

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

27 голосов
/ 16 апреля 2009

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

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

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

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

System.Reflection.Assembly.GetExecutingAssembly()

Вот еще информация в классе AssemblyInfo.

14 голосов
/ 08 января 2010

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

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

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

<%= GetApplicationVersion() %>
8 голосов
/ 28 августа 2012

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

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

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

Бонус; использование 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 голосов
/ 24 января 2012

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

4 голосов
/ 18 октября 2010

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

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

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

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

Имея ссылку на сборку, вы можете перейти к версии через ее название:

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

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

Удачного кодирования!

2 голосов
/ 25 августа 2010
Version version = new Version(Application.ProductVersion);
string message = version.ToString();
1 голос
/ 04 января 2012

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

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

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

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

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

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

Хватит голосовать за меня за этот ответ:)

1 голос
/ 25 сентября 2009

Если вы ищете это из веб-элемента управления, один из способов - найти тип страницы с выделенным кодом (т. Е. Класс, который наследуется от 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;

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

...