ASP.NET 的Request 物件的生命周期很短,只会出现在一个Http Request,当需要跨物件传递资料时,比如HttpModule、HttpHandler、Page 、Controller,可以善用Request 物件来存放短暂的状态。

既然可以传递物件,那么我们也可以在Request 初始化的时候,将所需要的物件注入至Request 里面,然后再到到Page / Controller 取出来用;在不同的专案范本可以使用的Request 物件都不太一样,接下来分享我已经知道的写法。

开发环境

VS IDE 2019

IIS主机ASP.NET 4.8 WebForm / MVC5 / Web API

OWIN主机Web API

ASP.NET Core 3.1

存放状态的方式是key-value,型别为IDictionary or IDictionary<string,object>

System.Web.HttpContext.Items

.NET 2.0的时代用HttpContext.Items (IDictionary Type),到了.NET 3.5之后可以改用HttpContextBase.Items。

HttpContextWrapper则是用来把HttpContext变成HttpContextBase。

HttpContextBase是一个抽象,可以让我们更好测试 [Unit Test]使用HttpContextBase取代HttpContext.Current,提高可测试性

HttpContext.Items 是IDictionary型别,Key对应Object。

适用ASP.NET WebForm、ASP.NET MVC。

从Global.asax注入Member物件至 HttpContext.Items

publicclassGlobal:HttpApplication{protectedvoidApplication_BeginRequest(){varmember=newMember{Id=Guid.NewGuid(),Name=Name.FullName()};varkey=member.GetType().FullName;HttpContext.Current.Items[key]=member;}}

在Default.aspx.cs取出,这里我用了HttpContextWrapper把HttpContext转成HttpContextBase

publicpartialclassDefault:Page{protectedvoidPage_Load(objectsender,EventArgse){if(this.IsPostBack){return;}varhttpContext=newHttpContextWrapper(HttpContext.Current);varkey=typeof(Member).FullName;varmember=httpContext.Items[key]asMember;this.Id_Label.Text=member.Id.ToString();this.Name_Label.Text=member.Name;}}

System.Web.HttpContextBase.Items

Controller 依赖HttpContextBase 非HttpContext

适用ASP.NET MVC5

在 ActionFilterAttribute 注入 Member 物件至 HttpContextBase.Items

publicclassInjectionAttribute:ActionFilterAttribute{publicoverridevoidOnActionExecuting(ActionExecutingContextfilterContext){//初始化物件varmember=newMember{Id=Guid.NewGuid(),Name=Faker.Name.FullName()};varkey=member.GetType().FullName;//注入到HttpContextBasefilterContext.RequestContext.HttpContext.Items[key]=member;}}

在 Controller 取出 Member 物件

publicclassHomeController:Controller{//GET:DefaultpublicActionResultIndex(){varkey=typeof(Member).FullName;varmember=this.HttpContext.Items[key];returnView(member);}}

System.Net.Http.HttpRequestMessage.Properties

HttpRequestMessage.Properties [“ key”] 是IDictionary <string,object>型别

适用的ASP.NET Web API / ASP.NET Core Web API

在 ActionFilterAttribute 注入 Member 物件至 HttpRequestMessage.Properties["key"]

publicclassInjectionAttribute:ActionFilterAttribute{publicoverridevoidOnActionExecuting(HttpActionContextfilterContext){//初始化物件varmember=newMember{Id=Guid.NewGuid(),Name=Faker.Name.FullName()};varkey=member.GetType().FullName;//注入到HttpRequestMessagefilterContext.Request.Properties[key]=member;}}

在 ApiController 取出 Member 物件

publicclassDefaultController:ApiController{//GET:api/DefaultpublicIHttpActionResultGet(){varkey=typeof(Member).FullName;varmember=this.Request.Properties[key]asMember;returnthis.Ok(member);}}

Microsoft.Owin.IOwinContext.Environment

IOwinContext.Environment 是IDictionary<string,object>型别

IOwinContext.Set/Get骨子里面是控制IOwinContext.Environment

适用OWIN

app.Use Middleware 注入 Member 物件至 IOwinContext.Environment["key"]

publicclassStartup{publicvoidConfiguration(IAppBuilderapp){varconfig=newHttpConfiguration();//WebAPIconfigurationandservices//WebAPIroutesconfig.MapHttpAttributeRoutes();config.Routes.MapHttpRoute("DefaultApi","api/{controller}/{id}",new{id=RouteParameter.Optional});app.Use(async(owinContext,next)=>{varmember=newMember{Id=Guid.NewGuid(),Name=Name.FullName()};//owinContext.Set(member.GetType().FullName,member);owinContext.Environment[member.GetType().FullName]=member;awaitnext();});app.UseErrorPage().UseWebApi(config);}}

在 ApiController ,用 IOwinContext.Get 取出 Member 物件

publicclassDefaultController:ApiController{//GET:api/DefaultpublicIHttpActionResultGet(){varkey=typeof(Member).FullName;varmember=this.Request.GetOwinContext().Get<Member>(key);returnthis.Ok(member);}}

Microsoft.AspNetCore.Http.HttpContext.Items

HttpContext.Items 是IDictionary<object,object>型别

适用ASP.NET Core

app.Use Middleware 注入 Member 物件至 HttpContext.Items

publicclassStartup{publicIConfigurationConfiguration{get;}publicStartup(IConfigurationconfiguration){this.Configuration=configuration;}//Thismethodgetscalledbytheruntime.UsethismethodtoconfiguretheHTTPrequestpipeline.publicvoidConfigure(IApplicationBuilderapp,IWebHostEnvironmentenv){if(env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Use(async(owinContext,next)=>{varmember=newMember{Id=Guid.NewGuid(),Name=Faker.Name.FullName()};varkey=member.GetType().FullName;owinContext.Items[key]=member;awaitnext();});app.UseHttpsRedirection();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints=>{endpoints.MapControllers();});}//Thismethodgetscalledbytheruntime.Usethismethodtoaddservicestothecontainer.publicvoidConfigureServices(IServiceCollectionservices){services.AddControllers();}}

在 Controller 用 HttpContext.Items 取出 Member

[ApiController][Route("api/[controller]")]publicclassDefaultController:ControllerBase{[HttpGet]publicasyncTask<ActionResult<Member>>Get(){varkey=typeof(Member).FullName;varmember=this.HttpContext.Items[key]asMember;returnthis.Ok(member);}}