`

ASP.NET保持用户状态的九种选择

阅读更多

摘要: ASP.NET为保持用户请求之间的数据提供了多种不同的途径。你可以使用Application对象、cookie、hidden fields、Sessions或Cache对象,以及它们的大量的方法。决定什么时候使用它们有时很困难。本文将介绍了上述的技术,给出了什么时候使用它们的一些指导。尽管这些技术中有些在传统ASP中已经存在,但是有了.NET框架组件后该在什么时候使用它们发生了变化。为了在ASP.NET中保持数据,你需要调整从先前的ASP中处理状态中学习到的知识。

  随着Web时代的到来,在无状态的HTTP世界中管理状态成为Web开发者的一个大问题。最近出现了几种存储和检索数据的不同技术。本文我将解释ASP.NET开发者能怎样通过页面请求维护或传递状态。

  在ASP.NET中,有几种保持用户请求间数据的途径--实际上太多了,使没有经验的开发者对在哪个特定的环境下使用哪个对象很困惑。为了回答这个问题,需要考虑下面三个条件:

   .谁需要数据?

   .数据需要保持多长时间?

   .数据集有多大?

  通过回答这些问题,你能决定哪个对象为保持ASP.NET应用程序请求间数据提供了最佳的解决方案。图1列出了不同的状态管理对象并描述了什么时候使用它们。ASP.NET中添加了四个新的对象:Cache、Context、ViewState和Web.Config文件。ASP.NET也支持传统的ASP对象,包括Application、 Cookie、有隐藏字段的 Form Post 、 QueryString和Sessions。注意这五个数据容器的正确使用方法发生了改变,因此有经验的程序员在考虑这些熟悉的对象时也许需要学习一些知识。

保持方法 谁需要数据 保持多长时间 数据量大小
Application 所有用户 整个应用程序生命期 任意大小
Cookie 一个用户 可以很短,如果用户不删除也可以很长 小的、简单数据
Form Post 一个用户 到下一次请求(可以跨越多个请求重复使用) 任意大小
QueryString 一个或一组用户 到下一次请求(可以跨越多个请求重复使用) 小的、简单数据
Sessions 一个用户 用户活动时一直保持+一段时间(一般20分钟) 可以是任何大小,但是因为用户有单独的Sessions 存储,所有它应该最小。
Cache 所有用户或某些用户 根据需要 可大可小、可简单可复杂
Context 一个用户 一个请求 可以保持大对象,但是一般不这样使用
ViewState 一个用户 一个Web窗体 最小
Config file 所有用户 知道配置文件被更新 可以保持大量数据,通常组织小的字符串和XML结构

表1. ASP.NET中的数据容器对象

Application

  让我们通过回答上面的状态问题判定条件来说明该对象。谁需要数据?所有的用户需要访问它。需要保持数据多长时间?永久保持,或在应用程序生存期中保持。数据多大?可以是任何大小--在任何给定的时刻只有数据的一个副本存在。

  在传统ASP中,Application对象提供了一个保存频繁使用但很少改变的数据片的位置,例如菜单内容和参考数据。尽管在ASP.NET 中Application依然作为数据容器存在,但是有其它一些更适合以前保存在传统ASP应用程序的Application集合中的数据的对象。

  在传统的ASP中,如果被保存的数据在应用程序的生存期中根本不会改变(或很少改变,例如只读数据和大多数情况下是读操作的数据),Application对象是理想的选择。连接字符串就是保存在Application变量中的一个最普通的数据片,但是在ASP.NET中类似的配置数据最好保存在Web.config文件中。如果使用Application对象一个需要考虑的问题是任何写操作要么在Application_OnStart事件(global.asax)中,要么在Application.Lock部分中完成。尽管使用Application.Lock来确保写操作正确地执行是必要的,但是它串行化了对Application对象的请求,而这对于应用程序来说是个严重的性能瓶颈。图2演示了怎样使用Application对象,它包括一个Web窗体和它的代码文件。

  Application.aspx

<form id="Application" method="post" runat="server">
<asp:validationsummary id="valSummary" Runat="server">
</asp:validationsummary>
<table>
<tr>
<td colSpan="3">Set Application Variable:</td>
</tr>
<tr>
<td>Name</td>
<td><asp:textbox id="txtName" Runat="server"></asp:textbox>
</td>
<td><asp:requiredfieldvalidator id="nameRequired"
runat="server" Display="Dynamic" ErrorMessage="Name is
required." ControlToValidate="txtName">*
</asp:requiredfieldvalidator></td>
</tr>
<tr>
<td>Value</td>
<td><asp:textbox id="txtValue" Runat="server">
</asp:textbox></td>
<td><asp:requiredfieldvalidator id="valueRequired"
Runat="server" Display="Dynamic" ErrorMessage="Value is
required." ControlToValidate="txtValue">*
</asp:requiredfieldvalidator></td>
</tr>
<tr>
<td colSpan="3"><asp:button id="btnSubmit" Runat="server"
Text="Update Value"></asp:button></td>
</tr>
</table>
<asp:Label ID="lblResult" Runat="server" />
</form>
Application.aspx.cs
private void btnSubmit_Click(object sender, System.EventArgs e)
{
if(IsValid)
{
Application.Lock();
Application[txtName.Text] = txtValue.Text;
Application.UnLock();
lblResult.Text = "The value of <b>" + txtName.Text +
"</b> in the Application object is <b>" +
Application[txtName.Text].ToString() + "</b>";
}
}

代码段1.在ASP.NET中访问Application对象

  它的输出如下图所示:



图1. Application对象的内容

  注意图3中Application对象的内容是追踪输出的显示。追踪是个伟大的调试工具,但是在某个点,被打开的有追踪的页面可能出现在产品环境中。如果出现这种情况,你肯定不希望显示敏感的信息。这就是为什么Application对象从来不是推荐的存放敏感信息(例如连接字符串)的位置的主要原因之一。

 

Cookies

  当特定的用户需要特定的数据片,并且需要把数据在某个可变的时段中保持的时候,cookie就非常方便。它的生命周期可能与浏览器窗体的一样短,也可以长达数月、数年。cookie可以小到只有几个字节的数据,因为它们在每个浏览器请求中传递,它们的内容需要尽可能的小。

  Cookie提供了一条灵活的、强大的维护用户请求间数据的途径,这就是为什么Internet上大多数动态站点使用它们的原因。因为cookie可以存储的数据量很受限制,最好只在cookie中保存键字段,其它的数据保存在数据库或其它的服务器端数据容器中。但是由于不是所有的浏览器都支持cookie,并且它可以被用户禁止或删除,因此它们也不能用于保存关键数据。你应该很好地处理用户的cookie被删除的情况。最后,cookie作为简单的明文文本保存在用户的计算机中,因此在它里面不能保存敏感的、未加密的数据。


图2.单值和多值cookie

  有种特殊的cookie可以保存单个值或名称/值对的集合。图4显示了单个和多个值cookie的示例,通过ASP.NET的内建追踪特性输出。这些值可以在ASP.NET页面中使用Request.Cookies和Response.Cookies集合来维护,这在代码段2中演示。

  Cookies.aspx.cs

//使用HttpCookie类是指cookie的值和/或子值
HttpCookie cookie;
if(Request.Cookies[txtName.Text] == null)
cookie = new HttpCookie(txtName.Text, txtValue.Text);
else
cookie = Request.Cookies[txtName.Text];
if(txtSubValueName.Text.Length > 0)
cookie.Values.Add(txtSubValueName.Text, txtSubValueValue.Text);
cookie.Expires = System.DateTime.Now.AddDays(1); // tomorrow
Response.AppendCookie(cookie);
//检索cookie的值
if(!Request.Cookies[txtName.Text].HasKeys)
lblResult.Text = "The value of the <b>" + txtName.Text + "</b>
cookie is <b>" + Request.Cookies[txtName.Text].Value.ToString() +
"</b>";
else
{
lblResult.Text = "The value of the <b>" + txtName.Text + "</b>
cookie is <b>" + Request.Cookies[txtName.Text].Value.ToString() +
"</b>, with subvalues:<br>";
foreach(string key in Request.Cookies[txtName.Text].Values.Keys)
{
lblResult.Text += "[" + key + " = " +
Request.Cookies[txtName.Text].Values[key].ToString() + "]<br>";
}
}
删除Cookie
// 把的值设置为空并把终止时间设置为过去某个时刻
Response.Cookies[txtName.Text].Value = null;
Response.Cookies[txtName.Text].Expires =
System.DateTime.Now.AddMonths(-1); //上个月

代码段2.Accessing 在ASP.NET中访问Cookies

 

 

Form Post / 隐藏的窗体字段

  特定的用户需要窗体的数据,并且它需要在单个请求到应用程序终止的任何阶段都保持。这些数据事实上可以是任意大小的,它随着每个form post在网络上向前和向后发送。

  在传统的ASP中,这是在应用程序中暴露状态的通常的途径,特别是在多页面窗体应用程序中。但是在ASP.NET中这种技术不太适合了,因为只要你使用postback模型(也就是页面发回给自己),Web控件和ViewState自动处理了这些操作。ViewState是ASP.NET对这种技术的实现,我将在本文的后部分讨论它。访问通过POST发送的窗体值是使用HttpRequest对象的窗体集合完成的。在图6中,一个ASP.NET页面设置了某个用户的ID,在这以后它保持在一个隐藏的窗体字段中。后面的向任何页面的请求保留这个值,直到页面使用Submit按钮链接到其它的用户。

  Form1.aspx

<h1>Form 1</h1>
<form id="Application" method="post" runat="server">
<p>Your username:
<asp:Label ID="lblUsername" Runat="server" />
</p>
<asp:Panel Runat="server" ID="pnlSetValue">
<asp:validationsummary id="valSummary" Runat="server">
</asp:validationsummary>
<TABLE>
<TR>
<TD colSpan="3">Set Hidden Form Username Variable:</TD></TR>
<TR>
<TD>Username</TD>
<TD>
<asp:textbox id="txtName" Runat="server"></asp:textbox></TD>
<TD>
<asp:requiredfieldvalidator id="nameRequired" runat="server"
ControlToValidate="txtName" ErrorMessage="Name is required."
Display="Dynamic">*</asp:requiredfieldvalidator></TD></TR>
<TR>
<TD colSpan="3">
<asp:button id="btnSubmit" Runat="server" Text="Set Value">
</asp:button></TD></TR></TABLE>
</asp:Panel>
<asp:Label ID="lblResult" Runat="server" />
</form>
<form action="form2.aspx" method="post" name="form2" id="form2">
<input type="hidden" name="username" value="<%# username %>" >
<input type="submit" value="Go to Form2.aspx"
</form>
Form1.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack) // 新的请求或者来自form2.aspx的请求
{
// 检查窗体集合
if(Request.Form["username"] == null)
pnlSetValue.Visible = true;
else
{
//需要设置用户名值
pnlSetValue.Visible = false;
username = Request.Form["username"].ToString();
lblUsername.Text = username;
//数据绑定到隐藏的窗体字段值
this.DataBind();
}
}
}

private void btnSubmit_Click(object sender, System.EventArgs e)
{
if(IsValid)
{
//隐藏窗体来设置值
pnlSetValue.Visible = false;
username = txtName.Text;
lblResult.Text = "Username set to " + txtName.Text + ".";
lblUsername.Text = username;
this.DataBind();
}
}
Form2.aspx
<h1>Form 2</h1>
<form id="Application" method="post" runat="server">
<p>Your username: <asp:Label ID="lblUsername" Runat="server" /></p>
</form>
<form action="form1.aspx" method="post" id="form2" name="form2">
<input type="hidden" name="username" value="<%# username %>" >
<input type="submit" value="Go to Form1.aspx"
</form>
Form2.aspx.cs
private void Page_Load(object sender, System.EventArgs e)
{
if(Request.Form["username"] != null)
{
username = Request.Form["username"].ToString();
lblUsername.Text = username;
this.DataBind();
}
}

 

 

Sessions

  Sessions数据对于特定的用户是特定的。它的生存期是用户持续请求的时间加上后来一段时间(一般是20分钟)。Sessions可以保持或大或小的数据量,但是如果应用程序用于成百上千的用户,那么总共的存储应该保持最小。

  不幸的是在传统的ASP中Sessions对象的名声很不好,因为它把应用程序约束到特定的计算机上,阻碍了用户分组和Web范围的可伸缩性。在ASP.NET中几乎没有这些问题,因为改变Sessions保存的位置很简单。在默认情况下(性能最好的情况),Sessions数据仍然保存在本地Web服务器的内存中,但是ASP.NET支持使用外部状态服务器或数据库管理Sessions数据。

  使用Sessions对象很简单,并且它的语法与传统ASP相同。但是Sessions对象是保存用户数据的方法中效率很低的一种,因为即使用户停止使用应用程序后它仍然保持在内存中一段时间。这对于非常繁忙的站点的可伸缩性有严重的影响。其它的选择允许对释放内存的更多的控制,例如Cache对象也许更适合大量的大数据值。并且在默认情况下ASP.NET Sessionss依赖于cookie,因此如果用户禁止或不支持cookie,Sessionss就不能工作,但是可以配置Sessionss支持cookie无关。对于小的数据量,Sessionss对象是保存只需要在用户当前对话中保持的特定数据的极好位置。下面的例子演示了怎样设置和从Sessionss对象中检索值:

private void btnSubmit_Click(object sender, System.EventArgs e)
{
 if(IsValid)
 {
  // 设置Sessions值
  Sessions[txtName.Text] = txtValue.Text;

  //读取和显示刚才的设置
  lblResult.Text = "The value of <b>" + txtName.Text + "</b> in the Sessions object is <b>" + Sessions[txtName.Text].ToString() + "</b>";
 }
}

  该Web窗体与Application对象中使用的几乎相同,当允许页面追踪时Sessions集合的内容也是可见的。
你需要记住的是即使没有使用,Sessionss也会有应用程序开销。把Sessionss状态设置为只读的也可以优化只需要读而不需要写数据的页面。可以使用下面两种途径之一来配置Sessionss:

<%@ Page EnableSessionsstate="false" %>
<%@ Page EnableSessionsstate="readonly" %>

  ASP.NET Sessionss可以在Web.config或Machine.config中的Sessionsstate元素中配置。下面是在 Web.config中的设置的例子:

<Sessionsstate timeout="10" cookieless="false" mode="Inproc" />

 

ASP.NET中的新状态容器

  前面我们提到,ASP.NET为保存用户请求间的数据添加了几种新的途径。这些途径给了你如何保持状态信息更好的控制。这些技术的范围可以窄到只有一个请求那么小(Context对象),也可以宽到整个Web服务器和服务器上的所有应用程序(Machine.config文件)。在多数情况下你有多种保存特定数据片的选择--使用每个方法描述的问题和答案来决定某个对象是否适合你的需要。

  Cache

  Cache对象用于单个用户、一组用户或所有的用户。这种数据为多个请求保持。它可以保持很长时间,但是不能超过应用程序重新启动的时间,并且数据的终止基于时间或者其它的依赖关系。它可以高效率地保持大量或少量地数据。

  Cache 是ASP.NET中最"酷"的对象之一。它提供了难以置信的灵活性、通用性和性能,因此在ASP.NET应用程序中它通常是比Application或Sessions更好的保持数据的对象。本文没有详细介绍Cache对象的使用方法,但是仍然可以说它是一个万能对象。与其它的集合对象相似,它是一个简单的名称-值集合,但是通过使用指定特定用户的键值可以缓存特定用户的值。同样你可以缓存不同的相关数据的多个数据集,例如几个有键(如fordcars 、 chevycars、gmcars)的汽车集合。Cache中的数据可以给定一个绝对的、可变的或基于文件的终止时间。它们也实现了一个回调功能,在被缓存的值从缓存中提取时被调用,这个功能很有用,因为接着你能检查它是否为最新的数据变量,如果不是(或数据源不可用),就重新缓存被终止的值。

  添加和访问缓存中值的语法与先前谈到的相似。但是Cache给访问集合内容的标准索引器方法作了补充,它支持多种方法,允许对被缓存数据的更多的控制。最频繁使用的方法是Insert,它支持几种重载,允许你指定依赖、超时值、优先级和回调。下面是一些简单的例子:

// 给缓存添加项
Cache["myKey"] = myValue;

// 从缓存中读取项
Response.Write(Cache["myKey"]);

// 把CacheDuration增加10秒并把项添加到缓存中
Cache.Insert("myKey",myValue, null, System.DateTime.Now.AddSeconds(10),
System.Web.Caching.Cache.NoSlidingExpiration);

  Cache对象的最强大的特性之一是当缓存中的某个项终止时执行回调的能力。它使用了委托或函数指针,这在本文中没有讨论。幸运的是一旦你有了某些这些技术怎样工作的示例,就能通过简单的剪切和粘贴在应用程序中使用它们,不需要知道委托是怎样工作的复杂过程。有很多使用这种功能的原因,最通常的是在数据终止时用当前数据重新填充缓存,或者如果重新填充缓存的数据源不可用时恢复旧的缓存数据。

  在我的例子中,简单地缓存了当前时间,当缓存超期的时候,我将给缓存中的字符串末尾添加一个星号(*)。在超过时间后,你能通过计算星号的数量来确定缓存超期了多少次。图9演示了回调的重要概念,并且提供了给使用缓存建立更多功能回调程序的好模板。

private void Page_Load(object sender, System.EventArgs e)
{
 string cacheKey = "myKey";
 string data = "";
 // 检查数据是否已经被缓存了
 if(Cache[cacheKey]==null)
 {
  // 因为数据在缓存中,所有读取数据
  data = System.DateTime.Now.ToString();

  //建立回调委托的一个实例
  CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);

  Label1.Text = "Generated: " + data;

  Cache.Insert(cacheKey,data,null,
      System.DateTime.Now.AddSeconds(5),
      System.Web.Caching.Cache.NoSlidingExpiration,
      System.Web.Caching.CacheItemPriority.Default,
      callBack);
 }
 else
 {
  Label1.Text = "Cached: " + Cache[cacheKey].ToString();
 }
}

private void onRemove(string key, object val,CacheItemRemovedReason reason)
{
 //建立回调委托的一个实例
 CacheItemRemovedCallback callBack =new CacheItemRemovedCallback(onRemove);
    Cache.Insert(key,val.ToString() +
    "*",null,System.DateTime.Now.AddSeconds(5),Cache.NoSlidingExpiration,
    System.Web.Caching.CacheItemPriority.Default, callBack);
}

代码段5.缓存回调示例

  注意代码段中一个重要的特性是在Page_Load中使用模式(pattern)来确定是否使用缓存中的数据。当你处理缓存中的项时也可能使用这种模式。使用if语句来检查缓存的当前内容是否为空(因为要多次引用,为缓存键使用了一个变量)。如果是空的,从数据源生成数据并放入缓存中。如果不是空的,从缓存中返回数据。如果数据访问逻辑很复杂,你需要把整个if语句放入一个独立的函数,该函数的任务是检索数据。
Cache对象的功能比先前我们讨论的大多数对象多得多。这也是ASP.NET更强大的功能之一,并且我明确地推荐阅读关于它的更多内容。

 

Context

  Context对象保持单个用户、单个请求的数据,并且数据只在该请求期间保持。Context容器可以保持大量的数据,但是典型的情况下是保存小的数据片,因为它经常通过global.asax中的某个处理方法为每个请求实现。

  Context容器(从Page对象访问或使用System.Web.HttpContext.Current)被提供用于保持需要在不同的HttpModules和HttpHandlers之间传递的值。它也可以用于保持某个完整请求的相应信息。例如,IbuySpy入口在global.asax中的Application_BeginRequest事件过程中给容器填满了许多配置信息。注意这只在当前请求中可用,如果你希望在下一个请求中也能使用,请考虑使用ViewState。

  从Context集合中设置和获取数据使用的语法与前面讨论的其它集合对象(如Application、Sessions和 Cache)的相似。下面是两个简单的例子:

// 给Context添加项
Context.Items["myKey"] = myValue;

// 从Context中读取项
Response.Write(Context["myKey"]);

  ViewState

  ViewState为单个用户保持状态信息,保持期为ASPX页面工作时间。ViewState容器可以保持大量的数据,但是必须小心管理ViewState的大小,因为它增加了每个请求和回应的下载(download)大小。

  ViewState是ASP.NET中的一个新容器,也许你已经使用它了,但是你可能还是不了解它。这是因为所有的内建Web控件都使用ViewState在页面回发(postback)间保持自己的值。但是你必须小心,因为它影响应用程序的性能。影响的大小依赖于回发之间使用ViewState的多少--对大多数Web窗体来说数量非常小。

  确定某个页面上每个控件使用的ViewState的数量最简单的方法是打开页面追踪并检查每个控件负载了多少个ViewState。如果某个特定控件不需要在回发之间保持数据,请通过把EnableViewState设置为false关闭该对象的ViewState。你也可以通过在浏览器中查看的HTML源并检查隐藏窗体字段__VIEWSTATE来确定某个给定的ASP.NET页面ViewState的总共大小。注意这些内容都是使用Base64编码的,用于放置偶然的查看和维护。ViewState也可以通过给@Page指令添加EnableViewState="false"在整个页面中禁止。

  典型的Web窗体不需要直接维护ViewState。但是如果你建立自定义Web控件,就需要了解它是怎样工作的,并为你的控件实现它,这样该控件的工作方式才能与随ASP.NET发布的Web控件同样地工作。向ViewState读取或写入值都可以通过上面讨论地其它集合对象的语法完成:

// 给ViewState添加项
ViewState["myKey"] = myValue;

//从Context读取项
Response.Write(ViewState["myKey"]);

  当建立自定义Web控件时,你也许希望它们有ViewState的好处。这在控件的属性层可以简单实现。代码段6演示了怎样保存一个简单的自定义控件的PersonName属性到ViewState中,并在该控件的Render方法中使用它。

namespace MSDN.StateManagement
{
 public class HelloPerson : System.Web.UI.Control
 {
  public string PersonName
  {
   get
   {
    string s = (string)ViewState["PersonName"];
    return ((s == null) ? "" : s);
   }
   set
   {
    ViewState["PersonName"] = value;
   }
  }
  protected override void Render(System.Web.UI.HtmlTextWriter writer)
  {
   writer.Write("Hello " + PersonName);
  }
 }
}

代码段6.在ViewState中保存数据

 

Web.config和Machine.config文件

  这些文件中的数据对于某个应用程序的所有用户来说都可以使用。Web.config文件中存储的数据可用于应用程序的整个生命周期。这些数据一般很小,该对象一般用于保持文件位置和数据库连接的字符串。大的数据片最好保存在其它位置。

  作为其它多样集合对象的补充,ASP.NET引入了一组XML配置文件用于管理应用程序甚至于整个服务器的很多设置。每个ASP.NET应用程序使用Web.config文件来设置它的许多属性,每个服务器在系统文件夹下有一个作为应用程序基础的Machine.config文件。这些设置都作为默认值使用,除非重载。作为保存配置数据的补充,这些文件可以保存应用程序(或多个应用程序)需要的数据。

  无论什么时候应用程序启动都会读取配置信息,接着这些信息被缓冲。由于被缓冲了,应用程序可以快速读取它们,因此不需要考虑应用程序的瓶颈,因为它经常执行某个文本文件的一些整型信息。此外,某个应用程序的Web.config的改变将导致应用程序重新启动。这确保了对配置文件信息的修改立即反映到应用程序中。

  数据库连接信息,默认图像路径和XML数据文件路径是通常保存在Web.config文件中的数据片。在Web.config文件中保存数据的语法如下,在理想的情况下你也许希望使用集成的SQL身分验证:

<configuration>
<!-应用程序特殊设置 -->
<appSettings>
<add key="connectionString" value="server=myDBServer;
uid=myUID;pwd=myPassword;database=myDB" />
</appSettings>
<system.web>
<!-所有的wsb设置 -->
</system.web>
</configuration>

  为了访问ASP.NET页面中的值,可以使用ConfigurationSettings集合,它在System.Configuration名字空间中。下面的简单例子演示了怎样提取前面的连接字符串到一个本地变量中:

using System.Configuration;
ooo
String strConnString =
ConfigurationSettings.AppSettings["connectionString"];

  给System.Configuration名字空间添加一个引用减少了引用这些值的代码数量。因为对Web.config或 Machine.config的修改将导致应用程序立即重新启动,典型情况下这些值只由服务器系统管理员手动修改。因此你可以认为这些文件是保存只读数据而不是应用程序中修改的数据的好位置。

  结论

  有效的状态管理意味着识别的用户经验、数据错误与快速的页面或事务处理之间的巨大差别。尽管状态管理在ASP 3.0中不太适用,但是ASP.NET把它带到了本文讨论的状态对象的控制之下。小心地使用它们将使你给用户展示最佳的Web经验。

 

 

分享到:
评论

相关推荐

    ASPNET保持用户状态的九种选择

    ASP.NET保持用户状态的九种选择

    asp.net知识库

    使用ASP.NET 2.0 Profile存储用户信息[翻译] Level 200 [ASP.NET 2.0]PageParser.GetCompiledPageInstance中存在一个Bug 如何在DotNet 2的登录组件中检索用户的锁定状态及解锁? ASP.NET 2.0, 想说爱你不容易 ...

    asp.net教学讲义

    第五章:ASP.NET状态管理 80 5.1 状态管理概述 80 5.2 存储状态的位置 80 5.3 Application—管理应用程序状态 80 5.4 应用程序事件 81 5.5 Lock和UnLock方法 81 5.6 添加、更新和移除Application状态项 81 5.7 ...

    asp.net面试题

    八、ASP.NET有多种维护状态的技术,以下哪种是保存在客户端的?( ) A.VIEWSTATEB.SESSIONC.APPLICATIOND.数据CACHE 九、Cookies的默认生命周期有多长? ( ) A.20分钟B.30分钟C. 一天D.随浏览器的关闭而失效 十...

    在ASP.NET 2.0中操作数据之五十九:使用SQL缓存依赖项SqlCacheDependency

    理想的状态是这样的:数据库数据还是应缓存在内存,直到源数据(underlying data)发生改变时才从内存清除。这样的话可以最大化的获取缓存带来的性能上的好处,同时使“过时数据”(stale data)持续的时间最短。然而,...

    基于.net平台的成绩管理系统设计与实现(源码+论文).rar

    2.2.3 本系统的开发采用Asp.Net---- 一种全新的设计模式 7 2.2.4 面向对象的开发过程 8 2.2.5 开发工具的选择 9 2.2.6 数据库系统选择 10 2.2.7 开发方法的选择 11 2.2.8 开发本系统的意义 12 2.2.9 本文档编写目的 ...

    Visual Studio.Net(VS) 源码管理器

    4、 使用"文件"——"新建"——"项目"命令,在项目类型中选择"Visual C#项目",在"模板"中选择"ASP.NET Web应用程序"。在"位置"栏中填写http://localhost/MyWebApp。并选择"添入解决方案"选项。确定。 这样就在...

    在线考试系统源码

    九、系统设置 9.1用户管理:系统提供新建单个用户、新建批量用户、管理用户列表等功能,并支持准考证的打印功能。 9.2部门管理:系统提供新建单个部门、新建批量部门、管理部门信息等多项功能。 9.3职务...

    C#完整教程

    第九章 ASP.Net编程基础知识 167 9.1 网络基础 167 9.2 HTML标记语言 171 9.3 ASP.NET技术基础 181 第十章 Web服务器端控件 188 10.1 常用的ASP.NET服务器端控件 188 10.2 ASP.Net控件数据绑定 192 10.3 数据验证...

    DXBBS论坛程序mssql及ACCESS双版本

    为达到最佳效果,推荐使用九网互联的ASP.net空间,支持ASP.net版本1.1和2.0在线切换、在线脚本映射、ASP.net具体错误信息在线查看。一:DXBBS论坛系统简介DXBBS V8.0 论坛系统为采用最新 asp.net 2.0 C# 技术原创...

    C#微软培训资料

    第九章 面向对象的程序设计 .101 9.1 面向对象的基本概念.101 9.2 对象的模型技术 .103 9.3 面向对象的分析 .105 9.4 面向对象的设计 .107 9.5 小 结 .110 第十章 类 .112 10.1 类 的 声 明 .112 ...

    某教学课程系统

    为达到最佳效果,推荐使用九网互联的ASP.net空间,支持ASP.net版本1.1和2.0在线切换、在线脚本映射、ASP.net具体错误信息在线查看。《谷秋精品课程软件》系统为加快国家精品课程建设步伐,争取有更多的优质课程加入...

    学生管理系统PPT毕业论文答辩

    2.2.3 本系统的开发采用Asp.Net---- 一种全新的设计模式 7 2.2.4 面向对象的开发过程 8 2.2.5 开发工具的选择 9 2.2.6 数据库系统选择 10 2.2.7 开发方法的选择 11 2.2.8 开发本系统的意义 12 2.2.9 本文档编写目的 ...

    BSQL Hacker v0.9.0.9 中文汉化版

    BSQL Hacker v0.9.0.9中文汉化绿色版 ...某时的会话标记或者asp.net状态查看能够绕过通过代理页面等而被单独登陆会话使用。 这个软件仍然是一个试用版,已知问题 1,MySQL自动攻击是实验性的,有时可能不会正常工作。

    行业贸易商务门户网站系统正式版

    asp.net行业电子商务网站系统蓝色版下载,B2B电子商务平台、电子商务网站管理系统,专为各行业门户贸易网站设计的,ASP.NET编程的行业B2B电子商务系统全功能,利用B2B仿阿里巴巴电子商务网上贸易网站管理系统,可在全球...

    B2C模式分销商城系统 标准版.rar

    ● 分销商城系统的框架设计及相关功能介绍(开发语言:ASP.NET) 一、会员管理----会员级别层次化 会员组权限设置,识别各类用户的权限控制,如供应商设置、分销商设置、VIP客户设置等,同时供应商下能同时实现下一...

    韩式服装网店发布系统源码下载

    本版本是asp+mssql版本,如本机调试运行,需要安装IIS和MSSQL数据库,附加数据库并设置,参考解压文件夹里面的,程序相关说明中的,相关安装文档,并更改conn.asp,admin/conn.asp,bbs/conn.asp,bbs/conn2.asp四个文件中的...

    OA系统+手机版源码t源代码

    利用最新的ASP.NET平台、javascript和AJAX、SQLSERVER关系型数据库等技术,结合OA思想的独特设计,建立一个开放的信息资源管理平台。 利用数据库及分布式处理技术、模块化功能设计,构造信息存储与事务处理平台。该...

    JAVA面试题最全集

    选择树的一个节点时,如何得到这个节点? 70.向编辑框中输入字符时,如何控制只输入整数? 71.描述使用JDBC连接数据库的过程 72.EJB分为几类?什么是BMP,CMP? 73.什么是JNDI? 74.ADO是什么?ActiveX数据对象,是...

    PJBLOG3海神扩展增强版3.0.6.170

    点击后打开QQ临时对话窗口,需要发布的QQ显示状态风格改变时,请打开ubbcode.asp文件,查找这样一句代码http://wpa.qq.com/pa?p=1:$1:1修改这句代码中最后冒号后面的数字1为1到13,可改变为13种QQ在线 状态风格 5、...

Global site tag (gtag.js) - Google Analytics