[ASP.NET] 使用 Request 傳遞參數

ASP.NET 的 Request 物件的生命週期很短,只會出現在一個 Http Request,當需要跨物件傳遞資料時,比如 HttpModule、HttpHandler、Page 、Controller,可以善用 Request 物件來存放短暫的狀態。

既然可以傳遞物件,那麼我們也可以在 Request 初始化的時候,將所需要的物件注入至 Request 裡面,然後再到到 Page / Controller 取出來用;在不同的專案範本可以使用的 Request 物件都不太一樣,接下來分享我已經知道的寫法。

開發環境

  • VS IDE 2019
  • IIS Host ASP.NET 4.8 WebForm / MVC5 / Web API
  • OWIN Host Web API
  • ASP.NET Core 3.1

存放狀態的方式是 key-value,型別為 IDictionary or IDictionary<string,object>

System.Web.HttpContext.Items

 

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

public class Global : HttpApplication
{
    protected void Application_BeginRequest()
    {
        var member = new Member {Id = Guid.NewGuid(), Name = Name.FullName()};
        var key    = member.GetType().FullName;
        HttpContext.Current.Items[key] = member;
    }
}

 

在 Default.aspx.cs 取出,這裡我用了 HttpContextWrapperHttpContext 轉成 HttpContextBase

public partial class Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (this.IsPostBack)
        {
            return;
        }
 
        var httpContext = new HttpContextWrapper(HttpContext.Current);
        var key            = typeof(Member).FullName;
        var member         = httpContext.Items[key] as Member;
        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

public class InjectionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //初始化物件
        var member = new Member {Id = Guid.NewGuid(), Name =Faker.Name.FullName()};
        var key    = member.GetType().FullName;

        //注入到 HttpContextBase
        filterContext.RequestContext.HttpContext.Items[key] = member;
    }
}

 

在 Controller 取出 Member 物件

public class HomeController : Controller
{
    // GET: Default
    public ActionResult Index()
    {
        var key = typeof(Member).FullName;
        var member = this.HttpContext.Items[key];   
        return View(member);
    }
}

 

System.Net.Http.HttpRequestMessage.Properties

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

public class InjectionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext filterContext)
    {
        //初始化物件
        var member = new Member {Id = Guid.NewGuid(), Name = Faker.Name.FullName()};
        var key    = member.GetType().FullName;
 
        //注入到 HttpRequestMessage
        filterContext.Request.Properties[key] = member;
    }
}


在 ApiController 取出 Member 物件

public class DefaultController : ApiController
{
    // GET: api/Default
    public IHttpActionResult Get()
    {
        var key    = typeof(Member).FullName;
        var member = this.Request.Properties[key] as Member;
        return this.Ok(member);
    }
}

 

Microsoft.Owin.IOwinContext.Environment

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

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();

        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute("DefaultApi",
                                   "api/{controller}/{id}",
                                   new {id = RouteParameter.Optional}
                                  );
        app.Use(async (owinContext, next) =>
                {
                    var member = new Member
                    {
                        Id   = Guid.NewGuid(),
                        Name = Name.FullName()
                    };
                    
                    //owinContext.Set(member.GetType().FullName, member);

                    owinContext.Environment[member.GetType().FullName] = member;
                    await next();
                });
        app.UseErrorPage()
           .UseWebApi(config);
    }
}

 

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

public class DefaultController : ApiController
{
    // GET: api/Default
    public IHttpActionResult Get()
    {
        var key    = typeof(Member).FullName;
        var member = this.Request.GetOwinContext().Get<Member>(key);
        return this.Ok(member);
    }
}

 

Microsoft.AspNetCore.Http.HttpContext.Items

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

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        this.Configuration = configuration;
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.Use(async (owinContext, next) =>
                {
                    var member = new Member
                    {
                        Id   = Guid.NewGuid(),
                        Name = Faker.Name.FullName()
                    };
                    var key = member.GetType().FullName;
                    owinContext.Items[key] = member;
                    await next();
                });
        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
    }
}

 

在 Controller 用 HttpContext.Items 取出 Member

[ApiController]
[Route("api/[controller]")]
public class DefaultController : ControllerBase
{
    [HttpGet]
    public async Task<ActionResult<Member>> Get()
    {
        var key = typeof(Member).FullName;
        var member = this.HttpContext.Items[key] as Member; 
        return this.Ok(member);
    }
}

 

範例位置

https://github.com/yaochangyu/sample.dotblog/tree/master/Lab.AspNetPassParameter

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo