频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

ASP.NET可交互式位图窗体设计(9)

来源: 作者: 出处:巧巧读书 2006-10-15 进入讨论组
 在页面和请求之间传递状态
    为使应用程序能够工作,它需要能够维护请求之间的状态并将状态传递给绘图页面(如下所示)。
  
    维护和传递状态有多种方式。如果应用程序是严格的单页面应用程序(和以前的应用程序一样),则可以使用视图状态,其中数据被编码存储在 Web 页的隐藏输入字段中。
  
    但是我们的图像控件是在单独的页面中进行绘图的,因此需要某些更灵活的东西。最好的选择就是 cookie 和会话状态。会话状态非常灵活,但要求使用服务器资源。浏览器可以保留 cookie,但其大小非常有限。
  
    Page_Load
    Page_Load 是在创建页面对象之后以及在运行所有事件处理程序之前被调用的。因此 Page_Load 方法是加载永久数据的理想所在。如果找不到数据,就创建新的数据。以下是相关代码:
  
  
  Private Sub Page_Load(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) _
  Handles MyBase.Load
  randomGen = ViewState("randomGen")
  If randomGen Is Nothing Then randomGen = New Random()
  ' 选项之一:使用会话状态获得绘图列表
  '(保存在 Page_Unload 中)
  '(注意:要求服务器上的状态存储)
  drawingList = Session("drawingList")
  If drawingList Is Nothing Then drawingList = New DShapeList()
  ' 选择之二:从用户浏览器上的 cookie 中
  ' 检索绘图状态
  '(注意:不需要服务器存储,但有些用户会禁用 cookie)
  '(注意之二:cookie 不会自动反序列化!:( )
  ' 注意之三:使用 cookie 将限制能够绘制的形状数量
  'Dim drawingListCookie As HttpCookie
  'drawingListCookie = Request.Cookies("drawingList")
  'If drawingListCookie Is Nothing Then
  ' drawingList = New DShapeList()
  'Else
  ' drawingList = _
  ' SerialHelper.DeserializeFromBase64String( _
  ' drawingListCookie.Value)
  'End If
  End Sub
  
    首先,我们尝试从视图状态加载随机数发生器状态。如果存在,则使用存储的值。如果不存在,则创建一个新的 Random 对象。
  
    接下来,我们尝试从会话状态加载绘图列表。同样,如果不存在绘图列表,则创建一个新的空列表。
  
    如果需要,视图状态和会话状态都会自动序列化我们的对象。视图状态始终被序列化,因此可以表示为浏览器隐藏输入字段中的编码的字符串。会话状态当存储在数据库中或者在服务器间进行传递时被序列化,但是如果应用程序运行在单个服务器上(例如在开发机器上进行测试时),则不会将其序列化。
  
    被注释的代码试图从 cookie 加载绘图列表。请注意,处理 cookie 要比处理视图或会话状态复杂得多。首先就是不能自动序列化。为序列化为一个字符串,我们在一个新类当中编写了 helper 函数,如下所示:
  
  
  Public Shared Function DeserializeFromBase64String( _
  ByVal base64String As String) As Object
  Dim formatter As New BinaryFormatter()
  Dim bytes() As Byte = Convert.FromBase64String(base64String)
  Dim serialMemoryStream As New MemoryStream(bytes)
  Return formatter.Deserialize(serialMemoryStream)
  End Function
  
  
    Dr. GUI 使用了二进制格式化程序并转换为可打印的 base 64 字符串,因为无论是 SOAP 还是 XML 格式化程序都不适用于此应用程序。我们必须从纯二进制表示转换为 base 64 字符串,以避免因简单复制字节而产生字符串中控制字符的潜在问题。base 64 字符串使用一个字符 A-Z、a-z、0-9、+ 或 /(共 64 个或 2^6 个字符)来表示二进制字符串中的每六位,因此四个字符表示三个字节 -- 第一个字符表示第一个字节中的六位,第二个字符表示第一个字节的末两位和第二个字节的前四位,以此类推。同样,使用 base 64 字符串关键在于可以将字符串限制为可打印字符,这样就避免了任何控制字符出现潜在问题。
  
    XML 格式化程序不会序列化私有数据 -- 而 Dr. GUI 也不打算为绘图列表中的私有数据添加公开访问权限。SOAP 格式化程序不存在这种限制,但它不会序列化空列表以便进行反序列化。相反,它不为空列表向数据流写入任何东西,这样当尝试反序列化时就会引发一个异常。(Dr. GUI 认为这是一个错误。)
  
    Dr. GUI 更喜欢以可读的 XML 格式进行序列化,但由于两种 XML 序列化格式化程序都无法完成此项工作,所以最终选择了二进制格式化程序并转换为 base 64 字符串。
  
    Page_Unload
    Page_Unload 是在破坏页面对象(包括任何所包含的数据)之前被调用的,因此是永久放置重要数据的理想位置,这样我们便可以在将来从 Page_Load(或者从图像的 Page_Load)中取出这些数据。
  
    因此,我们将数据保存在 Page_Unload 中,并从 Page_Load 中检索数据。虽然这有些奇怪,但却是正确的。
  
    以下是 Page_Unload 的代码:
  
  Private Sub Page_Unload(ByVal sender As Object, _
  ByVal e As System.EventArgs) _
  Handles MyBase.PreRender
  ViewState("randomGen") = randomGen
  ' 选项之一:编写会话状态
  Session("drawingList") = drawingList
  
  ' 选项之二:编写一个 cookie。必须编写代码进行序列化。
  ' 注意:使用 cookie 将限制能够绘制的形状数量!
  'Dim drawingListString As String =
  ' SerialHelper.SerializeToBase64String(drawingList)
  'Response.Cookies.Add(New HttpCookie("drawingList", _
  ' drawingListString))
  End Sub
  
  
  
    此代码稍微有些简单,因为我们不必查看状态是否已经存在于视图或会话状态对象中,而只需将其无条件写出。
  
    同样,视图状态和会话状态可以自动对自身进行序列化,而 cookie 则不能,因此我们需要亲自执行。Dr. GUI 编写了下面的 helper 函数(在单独的类中),代码如下所示:
  
  
  Public Shared Function SerializeToBase64String(ByVal o As Object) _
  As String
  Dim formatter As New BinaryFormatter()
  Dim serialMemoryStream As New MemoryStream()
  formatter.Serialize(serialMemoryStream, o)
  Dim bytes() As Byte = serialMemoryStream.ToArray()
  Return Convert.ToBase64String(bytes)
  End Function
  
    在单独的页面中绘图
    正如前面提到的,绘图是在单独的页面中进行的。以下是该页面的代码:
  
  
  Private Sub Page_Load(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load
  Dim drawingList As DShapeList
  ' 获取绘图列表选项之一:使用会话状态...
  drawingList = Session("drawingList")
  If drawingList Is Nothing Then drawingList = New DShapeList()
  
  ' 获取绘图列表选项之二:使用 cookie...
  '(请查看主页代码以了解更多注释)
  'Dim drawingListCookie As HttpCookie
  'drawingListCookie = Request.Cookies("drawingList")
  'If drawingListCookie Is Nothing Then
  'drawingList = New DShapeList()
  'Else
  ' drawingList = _
  ' SerialHelper.DeserializeFromBase64String( _
  ' drawingListCookie.Value)
  'End If
  
  Response.ContentType = "image/gif"
  Dim bitMap As New Bitmap(368, 376)
  Dim g As Graphics = Graphics.FromImage(bitMap)
  Try
  g.Clear(Color.White)
  drawingList.DrawList(g)
  bitMap.Save(Response.OutputStream, ImageFormat.Gif)
  Finally
 &n保留:: http://www.qqread.com/aspdotnet/n222414.html 更多文章 更多内容请看.NET移动与嵌入式技术.NET开发手册ASP.NET教程专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
最新论坛文章
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章