Helpex - Trao đổi & giúp đỡ Đăng nhập
56

Làm cách nào để lấy số phiên bản của ứng dụng web gọi điện trong hội đồng tham chiếu?

Tôi đã thử sử dụng System.Reflection.Assembly.GetCallingAssembly (). GetName () nhưng nó chỉ cung cấp cho tôi hợp ngữ được biên dịch động (trả về số phiên bản là 0.0.0.0).

CẬP NHẬT: Trong trường hợp của tôi, tôi cần một giải pháp không yêu cầu tham chiếu trở lại một lớp trong hội đồng ứng dụng web. Câu trả lời của Jason bên dưới (được đánh dấu là được chấp nhận) đáp ứng yêu cầu này - rất nhiều câu trả lời khác được gửi ở đây thì không.

56 hữu ích 3 bình luận 68k xem chia sẻ
12 trả lời 12
52

Đây là một số mã mà tôi sử dụng để hỗ trợ lấy cụm "chính" của ứng dụng từ ứng dụng Web hoặc không phải web, sau đó bạn có thể sử dụng GetName (). Phiên bản để lấy phiên bản.

Đầu tiên nó thử GetEntryAssembly () cho các ứng dụng không phải web. Điều này trả về null trong ASP.NET. Sau đó, nó sẽ xem xét HttpContext.Current để xác định xem đây có phải là một ứng dụng web hay không. Sau đó, nó sử dụng Kiểu của HttpHandler hiện tại - nhưng hợp ngữ của kiểu này có thể là một hợp ngữ ASP.NET được tạo nếu lệnh gọi được thực hiện từ một trang ASPX, vì vậy nó đi qua chuỗi BaseType của HttpHandler cho đến khi tìm thấy một kiểu không có trong không gian tên mà ASP.NET sử dụng cho các kiểu được tạo của nó ("ASP"). Đây thường sẽ là một kiểu trong assembly chính của bạn (ví dụ: Trang trong tệp mã phía sau của bạn). Sau đó chúng ta có thể sử dụng Assembly của Loại đó. Nếu vẫn thất bại, hãy quay lại GetExecutingAssembly ().

Vẫn có những vấn đề tiềm ẩn với cách tiếp cận này nhưng nó hoạt động trong các ứng dụng của chúng tôi.

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

CẬP NHẬT: Tôi đã cuộn mã này thành một dự án nhỏ trên GitHubNuGet .

52 hữu ích 5 bình luận chia sẻ
43

Tôi thấy rằng cách đơn giản nhất để lấy phiên bản của assembly "chính" của bạn (thay vì động) là:

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

Sử dụng lớp cấp cao nhất của bạn, lớp này sẽ không bao giờ "thay đổi ý nghĩa của nó" hoặc được thay thế như một phần của nỗ lực tái cấu trúc, chẳng hạn như MyMainClass. Bạn biết lớp này được định nghĩa trong hợp ngữ nào và không còn có thể nhầm lẫn về số phiên bản đến từ đâu.

43 hữu ích 2 bình luận chia sẻ
27

Tôi thích Web.Config lưu trữ phiên bản hiện tại của trang web.

Bạn cũng có thể thử tạo tệp AssemblyInfo.cs trong thư mục gốc của ứng dụng web có tệp sau:

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

sau đó truy cập giá trị thông qua mã như sau:

System.Reflection.Assembly.GetExecutingAssembly()

Dưới đây là hơn informaiton trên lớp AssemblyInfo.

27 hữu ích 3 bình luận chia sẻ
14

Để thêm vào những người phản hồi đã đăng. Để có được phiên bản lắp ráp trong ứng dụng web ASP.Net, bạn cần đặt một phương thức trong mã phía sau tệp tương tự như:

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

Trong trang ASPX, bạn muốn hiển thị số phiên bản chỉ cần đặt:

<%= GetApplicationVersion() %>
14 hữu ích 1 bình luận chia sẻ
8

Chỉ trong trường hợp ai đó vẫn còn quan tâm; điều này sẽ làm các trick và phải là một chút an toàn hơn chỉ lấy BaseTypecủa ApplicationInstanceđể có được bàn tay của bạn về việc thực hiện Global.asax.

Global.asax luôn được biên dịch thành một assembly giống như các thuộc tính assembly từ AssemblyInfo.cs, vì vậy điều này sẽ hoạt động đối với tất cả các ứng dụng web định nghĩa Global.asax.

Đối với những người không xác định Global.asax của riêng họ, nó sẽ quay trở lại phiên bản của global_asaxloại được tạo , luôn là 0.0.0.0 và đối với các ứng dụng không phải là ứng dụng web, nó sẽ chỉ trả về không có phiên bản nào cả .

Tặng kem; bằng cách sử dụng BuildManagerlớp không yêu cầu phiên bản hoạt động HttpContext, có nghĩa là bạn cũng có thể sử dụng nó từ mã khởi động ứng dụng.

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 hữu ích 1 bình luận chia sẻ
6

HttpContext.Current.ApplicationInstance có nguồn gốc từ lớp trong global.asax.cs. Bạn có thể làm như sau

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

Nó hoạt động cả trong ASP.NET (ASPX) và ASP.NET MVC

6 hữu ích 0 bình luận chia sẻ
4

Tôi đã gặp sự cố tương tự và nghĩ rằng bạn có thể thấy giải pháp hữu ích.

Tôi cần báo cáo phiên bản ứng dụng hiện tại (của một dự án ứng dụng web) từ điều khiển máy chủ tùy chỉnh, trong đó điều khiển máy chủ được chứa trong một thư viện khác. Vấn đề là các bộ lắp ráp "dễ nhất" đã không cung cấp bộ lắp ráp phù hợp.

  • Assembly.GetExecutingAssembly()trả về assembly chứa điều khiển; không phải là tập hợp ứng dụng.
  • Assembly.GetCallingAssembly()trả lại các tập hợp khác nhau tùy thuộc vào vị trí của tôi trong cây cuộc gọi; thường là System.Web, và đôi khi là assembly chứa điều khiển.
  • Assembly.GetEntryAssembly()đã trả lại null.
  • new StackTrace().GetFrames()[idx].GetMethod().DeclaringType.Assemblytruy xuất tập hợp của một khung trong dấu vết ngăn xếp tại chỉ mục idx; tuy nhiên, bên cạnh việc không phù hợp, đắt tiền và dễ bị tính toán sai chỉ số khung, có thể dấu vết ngăn xếp không chứa bất kỳ lệnh gọi nào đến hợp ngữ ứng dụng.
  • Assembly.GetAssembly(Page.GetType())cho tôi điểm App_Web_@#$@#$%@lắp ráp có chứa trang được tạo động. Tất nhiên, trang động kế thừa một lớp từ hợp ngữ ứng dụng của tôi, do đó, điều đó dẫn đến giải pháp cuối cùng:

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

Với tài liệu tham khảo lắp ráp trong tay, bạn có thể đi sâu vào phiên bản thông qua tên của nó:

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

Bây giờ, giải pháp này hoạt động vì tôi đã có tham chiếu đến một kiểu từ hợp ngữ ứng dụng. Chúng tôi không sử dụng bất kỳ trang nào không kế thừa từ mã phía sau, vì vậy nó sẽ có hiệu quả đối với chúng tôi, nhưng số dặm của bạn có thể thay đổi nếu thực tiễn mã hóa của tổ chức của bạn khác.

Chúc bạn viết mã vui vẻ!

4 hữu ích 1 bình luận chia sẻ
2
Version version = new Version(Application.ProductVersion);
string message = version.ToString();
2 hữu ích 1 bình luận chia sẻ
1

Một số thông tin ở đây: http://www.velocityreviews.com/forums/showpost.php?p=487050&postcount=8

trong asp.net 2.0, mỗi trang được tích hợp vào assembly riêng của nó, vì vậy chỉ có dll AssemblyInfo.cs được tích hợp mới trả về câu trả lời chính xác. chỉ cần thêm một phương thức tĩnh vào AssemblyInfo.cs để trả về thông tin phiên bản và gọi phương thức này từ các trang khác của bạn.

- bruce (sqlwork.com)

Nhưng tôi đã viết một phương pháp đơn giản để làm điều đó:

    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 hữu ích 0 bình luận chia sẻ
1

Nếu bạn đang tìm kiếm điều này từ một điều khiển web, một bí quyết là tìm loại Trang mã phía sau (tức là lớp kế thừa từ System.Web.UI.Page). Điều này thường có trong trang web của người tiêu dùng.

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

Tôi hy vọng có một cách tốt hơn.

1 hữu ích 0 bình luận chia sẻ
1

Câu hỏi nêu không có tham chiếu (các trường hợp) mà nó không (ban đầu) nói là không có kiến ​​thức về các loại ứng dụng web.

CHỈNH SỬA OP đã làm rõ để nói rằng có, họ thực sự không yêu cầu kiến ​​thức về các loại trong hội đồng web đang gọi, vì vậy câu trả lời là phù hợp. Tuy nhiên, tôi sẽ nghiêm túc xem xét việc cấu trúc lại một giải pháp sao cho phiên bản này được chuyển vào lắp ráp khác.

Đối với hầu hết mọi người trong trường hợp này nếu bạn biết loại HttpApplication tùy chỉnh:

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

và nếu bạn chỉ có một loại được tạo động:

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

Dừng bỏ phiếu cho tôi cho câu trả lời này :)

1 hữu ích 3 bình luận chia sẻ
0

Vì vậy, tôi phải lấy Assembly từ một dll được tham chiếu.

Trong thế giới asp.NET MVC / WebAPI, sẽ luôn có ít nhất một lớp kế thừa từ đó System.Web.HttpWebApplication. Việc triển khai bên dưới tìm kiếm lớp đó.

using System;
using System.Linq;

static Assembly GetWebAssembly() => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetExportedTypes().Any(t => t.BaseType?.FullName == "System.Web.HttpApplication"));

Ở trên sử dụng System.Linqđể tìm mối quan hệ đó, nhưng điều này cũng có thể được thực hiện mà không có.

Đầu tiên, chúng tôi nhận được tất cả các cụm đã tải

AppDomain.CurrentDomain.GetAssemblies()

Sau đó, liệt kê thông qua IEnumerable<Assembly>và lấy tất cả các loại nằm trực tiếp trong assembly.

a.GetExportedTypes()

Sau đó, hãy xem liệu có bất kỳ kiểu nào kế thừa từ System.Web.HttpWebApplication

t.BaseType?.FullName == "System.Web.HttpApplication"

Trong quá trình triển khai của mình, tôi đã đảm bảo rằng mã này sẽ chỉ được gọi một lần, nhưng nếu điều đó không được đảm bảo, tôi rất muốn gói nó trong một Lazy<T>hoặc triển khai tải chậm được lưu trong bộ nhớ cache vì sẽ khá tốn kém khi tiếp tục thực hiện tìm kiếm mù.

using System;
using System.Linq;

// original method
private static Assembly GetWebAssembly() => AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetExportedTypes().Any(t => t.BaseType?.FullName == "System.Web.HttpApplication"));

// lazy load implementation
private static Lazy<Assembly> _webAssembly = new Lazy<Assembly>(GetWebAssembly);
public static Assembly WebAssembly { get => _webAssembly.Value; }
0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ c# .net asp.net reflection assemblies , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading