Làm cách nào để tôi có được một đối tượng HttpContext từ HttpContextBase trong ASP.NET MVC 1?


154

Tôi đang làm việc với một số công cụ bất khả tri của WebForms / MVC và tôi cần lấy một thể hiện của HttpContextmột tham chiếu đến một HttpContextBaseđối tượng. Tôi không thể sử dụng HttpContext.Currentvì tôi cũng cần cái này để hoạt động không đồng bộ ( HttpContext.Currenttrả về nulltrong khi yêu cầu không đồng bộ). Tôi biết HttpContextWrapper, nhưng đi sai đường.

Câu trả lời:


249

Cách đơn giản nhất là tải ứng dụng ApplicationInstancevà sử dụng thuộc tính của nó Context:

// httpContextBase is of type HttpContextBase
HttpContext context = httpContextBase.ApplicationInstance.Context;

(cảm ơn Ishmael Smyrnow đã lưu ý điều này trong các bình luận)

Câu trả lời gốc:

Bạn có thể, đặc biệt là nếu HttpContextBasecá thể bạn được trao có loại HttpContextWrappervào thời gian chạy. Ví dụ sau minh họa cách bạn có thể làm điều này. Nó giả sử bạn có một phương thức gọi là Foochấp nhận bối cảnh HttpContextBasenhưng sau đó cần gọi một phương thức trong hội đồng bên thứ ba (rằng bạn có thể không có may mắn sửa đổi) đang mong đợi bối cảnh sẽ được nhập vào HttpContext.

void Foo(HttpContextBase context) 
{
    var app = (HttpApplication) context.GetService(typeof(HttpApplication));
    ThirdParty.Bar.Baz(app.Context);
}

// Somewhere in assembly and namespace ThirdParty,
// in a class called Bar, there is Baz expecting HttpContext:

static void Baz(HttpContext context) { /* ... */ }

HttpContextBasecó một phương pháp được gọi GetServicelà kết quả của hỗ trợ IServiceProvider. Việc GetServiceghi đè các HttpContextWrapperđại biểu để GetServicethực hiện các thể hiện được bao bọc HttpContext. Các GetServicethực hiện HttpContextcho phép bạn truy vấn cho nghi phạm thông thường như HttpApplication, HttpRequest, HttpResponsevà vân vân. Nó chỉ xảy ra HttpApplicationcó một thuộc tính được gọi là Ngữ cảnh và trả về một thể hiện của HttpContext. Vì vậy, ai được vào bọc HttpContextdụ bằng cách hỏi HttpContextBasecho HttpApplicationqua GetServicetiếp bằng cách đọc các Contexttài sản của trở lại HttpApplicationví dụ.

Không giống như HttpContextBase, GetServicekhông xuất hiện với tư cách là thành viên của công chúng HttpContextnhưng đó là vì HttpContextthực hiện tính khám phá IServiceProvider.GetServicetrong khiHttpContextBase không.

Hãy nhớ rằng Fookhông còn có thể kiểm tra được vì nó phụ thuộc vào việc có thể mở khóa cơ bản HttpContexttrong quá trình thử nghiệm và điều này là không thể giả mạo / sơ khai ở nơi đầu tiên. Vấn đề của câu trả lời này, tuy nhiên, là để giải quyết các câu hỏi: “Làm thế nào để tôi nhận được một HttpContext đối tượng từ HttpContextBase?”, Theo nghĩa đen . Kỹ thuật minh họa rất hữu ích trong những tình huống mà bạn thấy mình bị kẹp giữa các thành phần mà bạn không nhất thiết phải có sự sang trọng để sửa đổi.


3
Câu trả lời rất thú vị, chỉ cần sử dụng nó trong MVC để chuyển HTTPContext từ Bộ lọc lỗi sang ELMAH để ghi nhật ký.
Chris Marisic

1
Câu trả lời hay, đặt cược mà mất một chút đào? :)
longhairedsi

câu trả lời chính xác! Tôi đã sử dụng điều đó đặc biệt là trong bộ điều khiển Elmah to MVC của tôi github.com/alexanderbeletsky/elmah.mvc.contler/blob/master/
Kẻ

35
Với một HTTPContextBase, bạn không thể gọi context.ApplicationInstance.Context?
Ishmael Smyrnow

@IshmaelSmyrnow Chết tiệt, đừng bỏ lỡ điều đó trong số tất cả các Http*Basebiến thể được trả về HttpContextBase. : P Tôi sẽ cập nhật câu trả lời.
Atif Aziz

32

Bạn có thể,

var abstractContext = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);

16
-1 đây là cách sai, điều này cung cấp cho bạn Cơ sở khi bạn có Ngữ cảnh chứ không phải cách khác.
Chris Marisic

14

Bạn không thể.

Toàn bộ mục đích HttpContextBaselà để trừu tượng hóa sự phụ thuộc vào HttpContextlớp cụ thể . Mặc dù nó có thể chứa một cụ thể HttpContext (chẳng hạn như trường hợp httpContextWrapper) , các triển khai khác có thể hoàn toàn không có gì để làm với HttpContext.

Tùy chọn tốt nhất của bạn là xác định một Nhà máy Trừu tượng tùy chỉnh có thể nhận được HttpContextBasecho bạn, vì bạn luôn có thể bọc bê tông HttpContexttrong một HttpContextWrapper.


12
Nhân tiện, điều này đã được thực hiện một cách khủng khiếp - Tôi hiểu rằng muốn có một thiết lập cho các bài kiểm tra đơn vị và tôi hiểu các lớp trừu tượng - nhưng bạn có nên làm gì khi bạn muốn sử dụng các lớp ASP.NET hiện có mà mong đợi một HTTPContext không? (như msdn.microsoft.com/en-us/l
Library / Google

Đúng để kiểm tra các IHttpHandlertriển khai mà bạn kết thúc, bạn phải đặt một số lượng trừu tượng trong (trình bao trả lời) chỉ cho các bài kiểm tra đơn vị của bạn, điều này không cảm thấy đúng nhưng cuối cùng chỉ là lựa chọn duy nhất.
Chris S
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.