4

我正在制作一个简单的 asp.net 应用程序,它显示可以根据几个不同参数过滤的数据。因此,当前选择的不同过滤器需要保存在某处。我对 .NET 还很陌生,我想知道保存这些信息的最佳方式。我注意到一位同事将 Request.QueryString 与 Sessions 字典结合使用。页面加载时是这样的:

protected void Page_Load(object sender, EventArgs e) 
{
    if (Request.QueryString["Category"] != null &&
        Request.QueryString["Value"] != null)
    {
        string Category = Request.QueryString["Category"];
        string CategoryValue = Request.QueryString["Value"];

        // selectedFacets is the server side dictionary
        selectedFacets.Add(Category, CategoryValue);                    
    }
 }

当用户按下网页上的按钮时,此处的 QueryString 会更改,从而更新 URL。

我的问题是,当我们使用 QueryString 只是为了保存价值服务器端时,为什么还要打扰它呢?不仅使按钮成为 asp 控制器更容易,例如:

protected void exampleCatexampleVal_Button_onClick(object sender, EventArgs e) 
{
     selectedFacets.Add(exampleCat, exampleVal);
}

Sessions 字典也有类似的业务:它只是用来将一堆值保存到服务器上的变量中,那么为什么要首先使用它呢?我相信这是有充分理由的,但现在他们的工作似乎过于复杂。谢谢!

4

4 回答 4

10

根据您的代码示例,我知道您在谈论ASP.NET WebForms。您的用例并不完整,但我将在这里展示一些替代方案来实现您的目标。如果您提供更多信息,我很乐意更新我的答案。

在我们开始之前,让我先澄清一下:HTTP 是无状态的。了解这个基本规则非常重要。这意味着您的服务器将接收请求,将其发送到您的应用程序(和 .NET 进程),获取结果页面(和资产)并将其发送回客户端(主要是浏览器)。故事结局。(几乎)您为响应请求而创建的所有内容都将丢失。这就是为什么我们可以选择跨请求存储对象/值的位置

服务器端会话

这是最简单的选择之一。您只需调用即可this.Session.Add("key", object)。让我们深入研究一下:

  • 它将使用服务器资源。也就是说,您使用会话的次数最多,您的应用程序将消耗的内存(和其他资源,根据需要)最多。
  • 这将更难扩展,因为数据将在您的服务器内存中。根据您的硬件,可以选择垂直缩放,但水平缩放将受到限制。您可以在 SQL Server 数据库上使用会话服务器或存储会话,但它不再那么高效了。
  • 它附加到您的客户端会话。如果用户打开另一个浏览器或将链接发送给他的朋友,它将丢失。
  • 是比较安全的。我说相对是因为下面的选项。至少它是服务器端。

GET 参数(AKA QueryString)

这是另一种选择,你已经知道了。您可以使用查询字符串 ( ) 来回发送数据?that=stuff&on=the&URL=youKnow

  • 它限制2000 个字符,并且必须是可序列化的。这就是为什么您可能不会在其中放置 DataGrid 的原因。
  • 用户可以更改它。意识到!始终清理 QueryString 中的数据。
  • 用户可以自由地为链接添加书签或将其发送给朋友,内容将是相同的。很好,请注意。

视图状态

您可能听说过,它是使 WebForms 如此可爱(又如此可恨)的引擎。默认情况下,您页面上的每个控制器都将其状态序列化为视图状态,这是一个巨大的隐藏字段,在您的页面上包含加密数据。继续,单击“查看源代码”并查找它。请不要尖叫。您可以像 Session 一样向 ViewState 添加任意数据。

  • 它在客户端。不要相信它
  • 它将在每个请求上来回发送,因此会消耗额外的带宽。
  • 对每个请求/响应进行反序列化/序列化都需要时间。
  • 数据必须是可序列化的(你知道我的意思)。

所以,到现在为止,我希望你有足够的信息来做出自己的决定。如果我错过了什么,请告诉我。

于 2013-06-27T17:06:13.467 回答
2

先看看这篇 MSDN 文章。我通读了它,它可能会为您回答您的问题。

http://msdn.microsoft.com/en-us/magazine/cc300437.aspx

您缺少的是 asp.net 页面生命周期的工作方式:

http://msdn.microsoft.com/en-us/library/ms178472(v=vs.100).aspx

问题是,“服务器变量”不会在回发(AFAIK)之间持续存在。它只在那个页面内有用,就在那时。一旦页面在循环结束时被处理,该字典就消失了。因此,如果您以后想使用它,则必须将其存储在某个地方。我引用的文章向您展示了可以存储信息以将其持久化的所有位置,以及存储信息的位置取决于您需要将其持久化多长时间,以及应该有多少用户可以访问它。

现在,当然,如果您不想保留该字典,那么当然,只需将其存储为 page 变量。那很好。没有理由保留您不再需要的数据。

于 2013-06-27T17:04:26.180 回答
1

请记住,从数据库或单独的进程服务 (StateServer) 存储和检索会话状态时,性能会受到轻微影响。如果会话状态存储在内存中,则无法将应用程序扩展到 Web 场,这会浪费 Web 服务器中宝贵的内存。

另一方面,使用查询字符串值不会浪费你的内存和资源,它很快而且你不必考虑管理会话状态。它为 SEO 带来好处并允许添加书签/收藏夹。

但是,您只能使用查询字符串( WWW 常见问题解答:URL 的最大长度是多少)存储有限数量的数据。如果敏感数据被暴露或恶意用户试图在您的代码中找到错误处理 URL 值的错误,它也可能带来安全风险。SQL 注入攻击是一种情况。您可以做的是加密敏感值。

总的来说,这里有很多方面需要考虑。

于 2013-06-27T17:33:05.710 回答
0

使用查询字符串值的好处之一是,如果您需要将书签/收藏夹存储在应用程序中,这将允许用户直接导航到页面并将某些值传递到页面中,而无需内存缓存的帮助。以以下为例:

我有一个产品页面,显示可以按类别名称过滤的产品网格视图。如果我在查询字符串中使用 categoryId 值,那么我可以为此页面制作一个书签,然后单击该书签,该页面将像我之前离开的那样工作。根据内存中的缓存,可能存在也可能不存在,不能保证我的书签每次都能正常工作。

于 2013-06-27T16:34:16.207 回答