Làm cách nào để truy cập phương thức HttpServerUtility.MapPath trong Thread hoặc Timer?


88

Tôi sử dụng một System.Timers.Timertrong ứng dụng Asp.Net của mình và tôi cần sử dụng HttpServerUtility.MapPathphương pháp dường như chỉ có sẵn thông qua HttpContext.Current.Server.MapPath. Vấn đề là đó HttpContext.Currentnullkhi Timer.Elapsedsự kiện cháy.

Có cách nào khác để lấy tham chiếu đến đối tượng HttpServerUtility không? Tôi có thể đưa nó vào hàm tạo của lớp mình. Nó có an toàn không ? Làm cách nào để tôi có thể chắc chắn rằng nó sẽ không được Thu gom rác khi kết thúc yêu cầu hiện tại?

Cảm ơn!

Câu trả lời:


142

Có thể sử dụng HostingEnvironment.MapPath()thay thếHttpContext.Current.Server.MapPath()

Mặc dù vậy, tôi vẫn chưa thử nó trong một chuỗi hoặc sự kiện hẹn giờ.


Một số giải pháp (không khả thi) mà tôi đã xem xét;

  • Phương pháp duy nhất tôi quan tâm HttpServerUtilityMapPath. Vì vậy, để thay thế, tôi có thể sử dụng AppDomain.CurrentDomain.BaseDirectoryvà xây dựng các đường dẫn của mình từ điều này. Nhưng điều này sẽ không thành công nếu ứng dụng của bạn sử dụng thư mục ảo (của tôi thì có).

  • Một cách tiếp cận khác: Thêm tất cả các đường dẫn tôi cần vào Globallớp. Giải quyết các đường dẫn này trong Application_Start.


1
Tuy nhiên, lưu ý rằng những điều trên không hoạt động trong các phiên bản IIS mới hơn. Trong IIS7, phần khởi động ứng dụng có thể được gọi bên ngoài một yêu cầu http. Đó là, ví dụ mã. Tôi chắc chắn rằng HostingEnosystem.MapPath () sẽ vẫn hoạt động như trước đây.
Robba

Nhưng HostingEnosystem.MapPath () sẽ xuất hiện lỗi nếu bạn chuyển nó và chuỗi trống để lấy trực tiếp đường dẫn thư mục ... HttpContext.Current.Server.MapPath (""); -> hoạt động HostingEnosystem.MapPath (""); -> phát sinh lỗi
VSP

14

Tôi không biết liệu điều này có giải quyết được vấn đề thư mục ảo của bạn hay không, nhưng tôi sử dụng điều này cho MapPath:

public static string MapPath(string path)
{
    if (HttpContext.Current != null)
        return HttpContext.Current.Server.MapPath(path);

    return HttpRuntime.AppDomainAppPath + path.Replace("~", string.Empty).Replace('/', '\\');
}

path.Replace ("~", string.Empty) phải là đường dẫn.Replace ('~', '.')
Slava.

13

HostingEnosystem không phải là giải pháp hoàn hảo vì đây là một lớp rất khó để bắt chước (xem Cách đơn vị mã kiểm tra sử dụng HostingEnosystem.MapPath ).

Đối với những người cần khả năng kiểm tra, cách tốt hơn có thể là tạo giao diện trình ánh xạ đường dẫn của riêng bạn như được đề xuất bởi https://stackoverflow.com/a/1231962/85196 , ngoại trừ triển khai nó như

public class ServerPathMapper : IPathMapper { 
 public string MapPath(string relativePath) { 
      return HostingEnvironment.MapPath(relativePath); 
 } 
} 

Kết quả có thể dễ dàng bị chế nhạo, sử dụng HostingEn environment trong nội bộ và thậm chí có thể giải quyết mối quan tâm của ase69s cùng một lúc.


Điều này cho phép tôi cung cấp triển khai giải pháp đường dẫn cho dự án API Web mà không yêu cầu phụ thuộc vào System.Web hoặc System.Net trong thư viện mà nó đang tham chiếu. +1
David Peterson

Đồng ý cho DI và
Khả năng kiểm tra

2

Bạn có thể không gọi hàm MapPath trước khi bắt đầu hẹn giờ và chỉ cần lưu kết quả vào bộ nhớ cache không? Có hoàn toàn cần thiết phải gọi MapPath bên trong sự kiện đánh dấu không?


2

Khi bộ hẹn giờ trôi qua, không có ngữ cảnh HTTP hiện tại. Điều này là do các sự kiện hẹn giờ không liên quan đến một yêu cầu HTTP cụ thể.

Những gì bạn nên làm là sử dụng HttpServerUtility.MapPath nơi có sẵn ngữ cảnh HTTP. Bạn có thể làm điều đó trong một trong các sự kiện đường dẫn yêu cầu (chẳng hạn như Page_Load) hoặc trong một sự kiện Global.asax chẳng hạn như Application_Start.

Gán kết quả MapPath cho một biến có thể truy cập được từ sự kiện Timer.Elapsed, nơi bạn có thể sử dụng Path.Combine để lấy vị trí của một tệp cụ thể mà bạn cần.


0

Tôi nghĩ lý do tại sao nó là null tại thời điểm đó (nếu bạn nghĩ về nó), là sự kiện đã trôi qua của bộ hẹn giờ không xảy ra như một phần của yêu cầu HTTP (do đó không có ngữ cảnh). Nó được gây ra bởi một cái gì đó trên máy chủ của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.