使用 HttpApplication 对象

ASP.NET 框架中的许多类都提供了许多很方便的属性可以直接映射到 HttpContext 类中定义的属性。这种交叠有一个很好的例子就是 HttpApplication,它就是全局应用类的基类,在下表中,你可以看到 HttpApplication 类中定义的属性和方法。许多和 HttpContext 中定义的很相似。

表 1 – HttpApplication 类中定义的成员

名称 描述
Application 对应到 HttpContext.Application 属性,通过它可以获取应用层面的状态数据。
CompleteRequest() 终止当前请求的生命周期,直接跳转到 LogRequest 事件。
Context 返回当前请求的 HttpContext 对象。
Init() 每个注册模块上的 Init() 方法调用之后调用。
Modules 返回一个 HttpModuleCollection 对象,当中详细描述了当前应用中的模块。
RegisterModule(type) 注册新模块的静态方法。
Request 返回 HttpContext.Request 值, 但是如果值为 null 的时候会抛出一个 HttpException。
Response 返回 HttpContext.Response 值,但是如果值为 null 的时候会抛出一个 HttpException。
Server 映射到 HttpContext.Server。
Session 返回 HttpContext.Session 值,但是如果值为 null 的时候会抛出一个 HttpException。

大多数的这些成员都是很方便的属性可以映射到 HttpContext 类中的属性,但是有三个值得注意,接下来详细说明。

处理属性异常

Request, Response, Session 和 User 属性返回的是 HttpContext 类中相对应的属性的值,但是,这些属性如果从 HttpContext 上对应的属性中获取的值是 null 就会抛出一个 HttpException。

发生这样的事是因为 HttpApplication 类会为两种不同的生命周期接收通知:应用生命周期和请求生命周期。描述单个请求的对象是不可以在全局应用类中用来处理应用相关的事件,所以如果我们在处理应用层级的通知的时候使用了与请求相关联的属性就会抛出 HttpException 异常。

抛出这样一个异常的策略是非常粗糙的,因为这使得处理未知来源的 HttpApplication 对象非常困难,我们可以看一下下面的代码:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace SimpleApp
{
public class MvcApplication : System.Web.HttpApplication
{
public MvcApplication()
{
PostAcquireRequestState += (src, args) => CreateTimeStamp();
} protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
CreateTimeStamp();
} private void CreateTimeStamp()
{
string stamp = Context.Timestamp.ToLongTimeString();
if (Session != null)
{
Session["request_timestamp"] = stamp;
}
else
{
Application["app_timestamp"] = stamp;
}
}
}
}

现在,我们删除我们之前写的代码,重新定义一个新的方法用来创建时间戳并将其存放在状态数据中。现在,我们不需要对状态数据了解太多,只需要知道 Session 属性会为每一个独立的请求返回状态数据对象。

提示:注意到,我为 PostAcquireRequestState 事件创建了请求时间戳。这是因为模块直到 AcquireRequestState 事件触发之后才会提供状态数据服务。因此,即使全局应用类实例创建出来用来处理请求相关的事件,Session 属性也会返回 null。

这个新方法叫做 CreateTimeStamp,旨在减少代码冗余并为应用层级和请求层级的事件添加事件戳。但是,只要现在应用一启动就会报错,因为在这段代码中,在全局应用类创建出来处理 Application_Start 方法的时候想要尝试读取 Session 属性。

我能够使用 try…catch 代码块,但是这是一个糟糕的实践,因为异常处理不应该用来管理一个应用中可预见的流程。因此,我们应该直接使用 HttpContext 中同等的属性。代码如下:

 private void CreateTimeStamp()
{
string stamp = Context.Timestamp.ToLongTimeString();
if (Context.Session != null)
{
Session["request_timestamp"] = stamp;
}
else
{
Application["app_timestamp"] = stamp;
}
}

注意到,我只是修改了之前对 Session 属性的检查;如果它不为 null,我就可以使用 HttpApplication 类中定义的 Session 属性。Application 属性总是能够返回 HttpApplicationState 对象,状态管理相关的知识我们会在后期讲解到。

我们需要注意这种问题特别是在全局应用类中不与独立请求相关联的对象。ASP.NET 其他地方,特别是在 MVC 框架 controller 类中。我们总是可以使用 context 来表示一个请求。我们可以看一下下面的例子:

 using SimpleApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace SimpleApp.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View(GetTimeStamps());
} [HttpPost]
public ActionResult Index(Color color)
{
Color? oldColor = Session["color"] as Color?;
if (oldColor != null)
{
Votes.ChangeVote(color, (Color)oldColor);
}
else
{
Votes.RecordVote(color);
} ViewBag.SelectedColor = Session["color"] = color;
return View(GetTimeStamps());
} private List<string> GetTimeStamps()
{
return new List<string> { String.Format("App timestamp: {0}", HttpContext.Application["app_timestamp"]),
String.Format("Request timestamp: {0}", Session["request_timestamp"])};
}
}
}

Controller 类是 MVC 框架的基础,当中提供了一个方便的 Session 属性与 HttpContext.Session 相关联(但是我需要使用 HttpContext.Application,因为它并没有相关联的简便的属性)。

你可以在应用启动的时候看到时间戳。因为两个值在起初的时候很可能是相同的,但是如果你重新刷新浏览器窗口的话,你会发现应用时间戳一直不变,而请求时间戳会在每次更新的时候发生改变。

图 1 - 展示应用和请求时间戳

[根据 Adam Freeman – Pro ASP.NET MVC 5 Platform 选译]

[译] ASP.NET 生命周期 – ASP.NET 上下文对象(六)的更多相关文章

  1. [译] ASP.NET 生命周期 – ASP.NET 应用生命周期(一)

    概述 ASP.NET 平台定义了两个非常重要的生命周期.第一个是 应用生命周期  (application life cycle),用来追踪应用从启动的那一刻到终止的那一刻.另一个就是 请求生命周期 ...

  2. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(五)

    ASP.NET 上下文对象 ASP.NET 提供了一系列对象用来给当前请求,将要返回到客户端的响应,以及 Web 应用本身提供上下文信息.间接的,这些上下文对象也可以用来回去核心 ASP.NET 框架 ...

  3. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(七)

    使用 HttpRequest 对象 HttpRequest 对象描述的是一个正在被处理的 HTTP 请求.下表列举了 HttpRequest 中的属性,它们提供了当前请求的相关信息(HttpReque ...

  4. [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(三)

    使用特殊方法处理请求生命周期事件 为了在全局应用类中处理这些事件,我们会创建一个名称以 Application_ 开头,以事件名称结尾的方法,比如 Application_BeginRequest.举 ...

  5. [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(四)

    不使用特殊方法来处理请求生命周期事件 HttpApplication 类是全局应用类的基类,定义了可以直接使用的一般 C# 事件.那么使用标准 C# 事件还是特殊方法那就是个人偏好的问题了,如果喜欢, ...

  6. [译] ASP.NET 生命周期 – ASP.NET 请求生命周期(二)

    ASP.NET 请求生命周期 全局应用类也可以用来跟踪每个独立请求的生命周期,包括请求从 ASP.NET 平台传递到 MVC 框架.ASP.NET 框架会创建一个定义在 Global.asax 文件中 ...

  7. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(八)

    使用 HttpResponse 对象 HttpResponse 对象是与 HttpRequest 对象相对应的,用来表示构建中的响应.它当中提供了方法和属性可供我们自定义响应,有一些在使用 MVC 视 ...

  8. Asp.net生命周期与Http协议

    Http协议,底层的东西还是不是特别熟悉,感觉要经过沉淀之后才能理解这些东西吧 1.Asp.net生命周期 Asp.net生命周期: 从发起请求开始,到IIS进行处理的全部过程,然后再到获取结果 当请 ...

  9. Git使用总结 Asp.net生命周期与Http协议 托管代码与非托管代码的区别 通过IEnumerable接口遍历数据 依赖注入与控制反转 C#多线程——优先级 AutoFac容器初步 C#特性详解 C#特性详解 WPF 可触摸移动的ScrollViewer控件 .NET(C#)能开发出什么样的APP?盘点那些通过Smobiler开发的移动应用

    一,原理 首先,我们要明白Git是什么,它是一个管理工具或软件,用来管理什么的呢?当然是在软件开发过程中管理软件或者文件的不同版本的工具,一些作家也可以用这个管理自己创作的文本文件,由Linus开发的 ...

随机推荐

  1. 深入理解计算机系统第二版习题解答CSAPP 2.20

    T2Uw(w)=x, x≥0时 T2Uw(w)=x+2w, x<0时 利用上面的公式,重新计算2.19的问题.

  2. 显示创建一个表的SQL语句

    显示创建数据库中包的语句,从而可以方便的对表的结构进行修改和复制(当然还有其他的方式) 显示表结构: 显示创建表语句: show create table tablename;

  3. js验证 button 提交

    <form class="form-horizontal" role="form" action="member_add" metho ...

  4. OpenShare vs Sharepoint

    光合信息Openshare是基于SharePoint,Exchange等开发的企业协同门户产品,许多朋友问为什么不直接就用Sharepoint建立企业门户解决方案,而要建议用OpenShare来进行? ...

  5. HTML5和Web Apps框架和方法

    单页: 1jQuery Mobile 该框架以其基于AJAX的导航系统和可使用主题的ThemeRoller设计而闻名.支持Android,ios,Windows Phone,webOs等.编程模式为C ...

  6. Slickflow.NET 开源工作流引擎基础介绍(三) -- 基于HTML5/Bootstrap的Web流程设计器

    1. Slickflow Designer 技术优势 1) 基于HTML5技术,兼容常见浏览器; 2) 纯Javascript / JsPlumb 脚本实现SVG图形化显示; JsPlumb允许您使用 ...

  7. JQGrid各种参数详解API(转载)

    下面是转自其他人blog的一个学习资料,与其说是学习资料,说成查询帮助文档更加合适. jqGrid学习之 ------------- 安装 jqGrid安装很简单,只需把相应的css.js文件加入到页 ...

  8. 转 Android中this、super的区别

    在Java中,this通常指当前对象,super则指父类的.当你想要引用当前对象的某种东西,比如当前对象的某个方法,或当前对象的某个成员,你便可以利用this来实现这个目 的,当然,this的另一个用 ...

  9. ubuntu下使用vi是方向键变乱码 退格键不能使用的解决方法

    ubuntu下使用vi是方向键变乱码 退格键不能使用的解决方法 转载:http://blog.csdn.net/yao_qinwei/article/details/8761777 在插入模式下,按删 ...

  10. HTML+CSS学习笔记 (7) - CSS样式基本知识

    HTML+CSS学习笔记 (7) - CSS样式基本知识 内联式css样式,直接写在现有的HTML标签中 CSS样式可以写在哪些地方呢?从CSS 样式代码插入的形式来看基本可以分为以下3种:内联式.嵌 ...