ฉันจะรับวัตถุ HttpContext จาก HttpContextBase ใน ASP.NET MVC 1 ได้อย่างไร


155

ฉันทำงานกับเครื่องมือ WebForms / MVC ที่ไม่เชื่อเรื่องพระเจ้าและฉันต้องได้รับตัวอย่างของHttpContextการอ้างอิงถึงHttpContextBaseวัตถุ ฉันไม่สามารถใช้HttpContext.Currentเพราะฉันต้องการให้มันทำงานแบบอะซิงโครนัสได้เช่นกัน ( HttpContext.Currentส่งคืนnullระหว่างการร้องขอแบบอะซิงโครนัส) ฉันรู้HttpContextWrapperแต่ไปในทางที่ผิด

คำตอบ:


250

วิธีที่ง่ายที่สุดคือรับแอปพลิเคชั่ApplicationInstanceนและใช้Contextคุณสมบัติ:

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

(ขอบคุณอิชมาเอลสมีร์โนว์ที่กล่าวถึงเรื่องนี้ในความคิดเห็น)

คำตอบเดิม:

คุณสามารถทำได้โดยเฉพาะอย่างยิ่งถ้าHttpContextBaseอินสแตนซ์ที่คุณถนัดเป็นประเภทHttpContextWrapperเวลาทำงาน ตัวอย่างต่อไปนี้แสดงวิธีการทำสิ่งนี้ มันซึมคุณมีวิธีการที่เรียกFooว่ายอมรับบริบทเป็นHttpContextBaseแต่แล้วความต้องการที่จะเรียกวิธีการในบุคคลที่สามประกอบ (ที่คุณอาจไม่ได้โชคดีที่จะปรับเปลี่ยน) 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) { /* ... */ }

HttpContextBaseมีวิธีการที่เรียกว่าเป็นผลมาจากการสนับสนุนGetService IServiceProviderการGetServiceแทนที่ของHttpContextWrapperผู้รับมอบสิทธิ์ในการGetServiceใช้งานHttpContextอินสแตนซ์ที่ถูกล้อม GetServiceการดำเนินการHttpContextช่วยให้คุณแบบสอบถามสำหรับผู้ต้องสงสัยตามปกติเช่นHttpApplication, HttpRequest, HttpResponseและอื่น ๆ มันก็จึงเกิดขึ้นว่าHttpApplicationมีคุณสมบัติที่เรียกว่าบริบทHttpContextและซึ่งผลตอบแทนตัวอย่างของ ดังนั้นหนึ่งได้รับที่ห่อHttpContextเช่นโดยการถามHttpContextBaseสำหรับการHttpApplicationผ่านทางGetServiceตามด้วยการอ่านContextทรัพย์สินของกลับHttpApplicationอินสแตนซ์

ซึ่งแตกต่างHttpContextBase, GetServiceไม่ปรากฏในฐานะสมาชิกของประชาชนHttpContextแต่เป็นเพราะHttpContextการดำเนินการIServiceProvider.GetServiceอย่างชัดเจนในขณะที่HttpContextBaseไม่ได้

โปรดจำไว้ว่าFooไม่สามารถทดสอบได้อีกต่อไปเพราะอาศัยความสามารถในการแกะต้นแบบHttpContextในระหว่างการทดสอบและเป็นไปไม่ได้ที่จะปลอมแปลง / ต้นขั้วในครั้งแรก จุดของคำตอบนี้ แต่เป็นไปตามที่อยู่คำถามที่ว่า“ฉันจะได้รับวัตถุ HttpContext วิธีจาก HttpContextBase?” อย่างแท้จริง เทคนิคที่แสดงให้เห็นนั้นมีประโยชน์ในสถานการณ์เหล่านั้นที่คุณพบว่าตัวเองถูกคั่นกลางระหว่างส่วนประกอบที่คุณไม่จำเป็นต้องมีความหรูหราในการปรับเปลี่ยน


3
คำตอบที่น่าสนใจมากเพียงใช้ตัวเองใน MVC เพื่อส่งผ่าน HttpContext จากตัวกรองข้อผิดพลาดไปยัง ELMAH สำหรับการบันทึก
Chris Marisic

1
คำตอบที่ดีเดิมพันที่ขุดนิดหน่อย? :)
longhairedsi

คำตอบที่ดี! ฉันใช้สิ่งนั้นโดยเฉพาะอย่างยิ่งใน Elmah ของฉันถึงตัวควบคุม MVC github.com/alexanderbeletsky/elmah.mvc.controller/blob/master/…
Alexander Beletsky

36
ด้วย HttpContextBase คุณเรียกcontext.ApplicationInstance.Contextไม่ได้เหรอ?
Ishmael Smyrnow

@IshmaelSmyrnow ชุนได้ไม่ว่าฉันพลาดในทุกรูปแบบที่ส่งกลับโดยHttp*Base HttpContextBase: P ฉันจะอัปเดตคำตอบ
Atif Aziz

32

คุณสามารถ,

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

16
-1 นี่เป็นวิธีที่ผิดนี่จะให้ฐานเมื่อคุณมีบริบทไม่ใช่วิธีอื่น
Chris Marisic

14

คุณทำไม่ได้

จุดประสงค์ทั้งหมดของHttpContextBaseมันคือการแยกการพึ่งพาในHttpContextระดับที่เป็นรูปธรรมออกไป แม้ว่ามันอาจจะมีรูปธรรมHttpContext (เช่นกรณีhttpContextWrapper) , การใช้งานอื่น ๆ อาจไม่มีอะไรเกี่ยวข้องHttpContextเลย

ตัวเลือกที่ดีที่สุดของคุณคือการกำหนดเองโรงงานบทคัดย่อที่ได้รับHttpContextBaseสำหรับคุณเพราะคุณมักจะสามารถตัดคอนกรีตในHttpContextHttpContextWrapper


13
โดยวิธีนี้ได้ทำอย่างน่ากลัว - ฉันเข้าใจว่าต้องการมีการตั้งค่าสำหรับการทดสอบหน่วยและฉันเข้าใจเลเยอร์ของนามธรรม - แต่ WTH คุณควรทำอย่างไรเมื่อคุณต้องการใช้คลาส ASP.NET ที่มีอยู่ซึ่งคาดว่า HttpContext? (เช่นmsdn.microsoft.com/en-us/library/... )
มาร์ค

ถ้าคุณต้องการทดสอบIHttpHandlerการใช้งานคุณจะต้องวางบทคัดย่อจำนวนหนึ่งไว้ใน (การห่อคำตอบ) สำหรับการทดสอบหน่วยของคุณซึ่งไม่รู้สึกถูกต้อง แต่จบลงด้วยการเป็นตัวเลือกเดียว
Chris S
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.