2009-04-28 32 views
7

Thuộc tính HttpContext.Current.Request.ApplicationPath đại diện cho thư mục ảo trong IIS hoặc WebDev.WebServer.Tôi có thể truy cập tên thư mục ảo trong global.asax.cs không?

HttpContext.Current.Request.ApplicationPath evaluates to "/virtualdirectory" 

này có thể được sử dụng kết hợp với VirtualPathUtility để thực hiện một gốc đường dẫn tương đối:

VirtualPathUtility.ToAbsolute("~/images/cat.jpg", 
           HttpContext.Current.Request.ApplicationPath) 

// (this evaluates to "/virtualdirectory/images/cat.jpg") 

Trong IIS6 và WebDev.WebServer Yêu cầu đối tượng sẵn trong global.asax.cs, nhưng IIS7 than phiền rằng nó là 'không có sẵn trong ngữ cảnh hiện tại'. Do đó dòng thứ hai của mã ở trên hoạt động nhưng không phải trong IIS7.

Vấn đề là tôi cần truy cập tên trực tiếp ảo trong phạm vi global.asax.cs. Tôi cần nó để xây dựng một số đường dẫn được sử dụng trong CSS được tạo động. Có cách nào khác để truy cập giá trị này không?

Edit: Đây là lỗi mà bạn nhận được trong IIS 7 để gọi HttpContext.Current.Request trong global.asax.cs dưới Application_Start:

HttpException (0x80004005): Request is not available in this context] 
    System.Web.HttpContext.get_Request() +8789264 
+0

Tôi không hiểu câu hỏi, HttpContext.Current có sẵn trong global.asax, bạn có hỏi sự kiện nào không? –

+0

@deviant - HttpContext.Current có sẵn, nhưng HttpContext.Current.Request thì không. Tôi đã chỉnh sửa bài đăng để bao gồm lỗi –

Trả lời

13

Cuối cùng tìm thấy câu trả lời đơn giản!

HttpRuntime.AppDomainAppVirtualPath 

sẵn ngay trong Application_Start

này có dạng /myapplication bao gồm tiền tố /.

+0

Làm thế nào để có được tên thư mục đầy đủ? –

+1

OK! HttpRuntime.AppDomainAppPath –

+1

Bạn thưa ngài, ông Simon Weaver, bạn đã hiểu rồi. – Jimbo

0

Bạn có thể sử dụng ResolveUrl ("~/images/cat.jpg") để xây dựng con đường của bạn?

Edit: ResolveUrl là một phương pháp kiểm soát, không chỉ là trang đẳng cấp, vì vậy bạn có thể làm theo cách này thay vì (bit xấu xí có thể):

System.Web.UI.Control c = new Control(); 
String s = c.ResolveUrl(@"~/images/cat.jpg"); 
+0

không vì không có trường hợp nào của Page –

0

Hmmm ... Tôi đã không nhận thức được sự thay đổi IIS7. Tôi tự hỏi nếu nó sẽ không đơn giản hơn để trì hoãn hoạt động này cho đến khi bạn có một trang. Ví dụ: bạn có thể thử đặt một thứ "chỉ một lần" trong Application_BeginRequest hoặc Session_Start?

Hoặc (hoàn toàn chưa được kiểm tra) cho một cái móc tự hủy đăng ký:

public override void Init() { 
     base.Init(); 
     EventHandler handler = null; 
     handler = delegate { 
      // do stuff, once only 
      this.BeginRequest -= handler; 
     }; 
     this.BeginRequest += handler; 
    } 

Bí quyết là làm việc đó một lần duy nhất (nếu nhiều yêu cầu đến cùng một lúc); có lẽ một ctor tĩnh? Ví dụ, tôi nghĩ rằng đây bắn một lần duy nhất, và chỉ khi có một trang có sẵn trong bối cảnh:

static class DelayedLoader { 
     static DelayedLoader() { 
      string s = VirtualPathUtility.ToAbsolute("~/images/cat.jpg", 
          HttpContext.Current.Request.ApplicationPath); 
     } 
     [MethodImpl(MethodImplOptions.NoInlining)] 
     public static void Init() { } 
    } 
    public override void Init() { 
     base.Init(); 
     EventHandler handler = null; 
     handler = delegate { 
      DelayedLoader.Init(); 
      this.BeginRequest -= handler; 
     }; 
     this.BeginRequest += handler; 
    } 
+0

Application_BeginRequest có lẽ là an toàn nhất. Tôi không chắc về vòng đời của Session_Start, nhưng khi tôi cố gắng sử dụng nó, đầu ra trang bị hỏng - tôi nghĩ nó xung đột với việc nén của tôi - điều này rất kỳ quặc nhưng tôi sẽ gắn bó với Begin_Request bây giờ –

0

Đây là tốt nhất mà tôi đã đưa ra: Application_BeginRequest (thông qua dấu)

tôi sử dụng tuyến Asax nên hiếm khi tôi đã tạm quên bạn có những sự kiện khác với nó. Cho đến bây giờ tôi đã tạo các CSS sprites trong Application_Start. Di chuyển nó đến BeginRequest là điều tốt nhất tôi có thể nghĩ ra.

Một kiểm tra boolean cho mọi yêu cầu là không đáng kể, nhưng sẽ tốt hơn nếu có cách khác.

protected void Application_Start() 
    { 
     RegisterRoutes(RouteTable.Routes); 
    } 

    protected void Application_BeginRequest() 
    { 
     if (!_initialized) 
     { 
      lock (thisLock) 
      { 
       _initialized = true; 
       GenerateCSSSprites(); 
      } 
     } 
    } 
+0

Lưu ý rằng nó dường như về lý thuyết có thể chạy 'GenerateCSSSprites' hai lần nếu hai yêu cầu đến đủ gần. Không chắc chắn, nhưng ... bạn có thể muốn sử dụng khóa đã kiểm tra kép (ví dụ: kiểm tra _initialized bên trong khóa), hoặc cách tiếp cận khác (chẳng hạn như lừa ctor tĩnh). –

+0

oops. cảm ơn. tôi đã cố gắng để tránh khóa trên mọi yêu cầu và quản lý để bỏ lỡ điều đó. quan trọng của nó kể từ khi chạy GenerateCSSSprites hai lần thực sự sẽ gây ra một ngoại lệ vì nó thêm các mục vào một từ điển toàn cầu và than phiền nếu điều này được thực hiện hai lần. cảm ơn –

+0

nó thực sự DID chạy hai lần khi tôi ban đầu đã thử: GenerateCSSSprites(); _initialized = true. đây là một chút khủng khiếp vì tôi là người duy nhất nhấn trang và mặc dù tôi đang truy cập một số tài nguyên trên máy chủ đó mà trình duyệt không thể yêu cầu chúng cho đến khi yêu cầu đầu tiên được hiển thị - vì vậy IIS7 phải tạo nhiều hơn một 'pseudo 'yêu cầu một yêu cầu thực sự của tôi. wierd –

Các vấn đề liên quan