通过QueryString传递对象

时间:2008-10-01 13:11:00

标签: asp.net vb.net

我有对象A,而对象A又具有Object B类型的属性

Class A

property x as Object B

End Class

在我的ASP.NET页面上,当我选择一个映射到A类型对象的gridview项时,我将该对象序列化到QueryString并将其传递给下一页。

但是,如果属性x实际上有一些值,我会遇到问题,因为它看起来我超过了QueryString容量长度4k(虽然我不认为对象那么大)

我已经考虑过以下方法来做到这一点

  • 会话变量

没有使用的方法,因为我读过这是不好的做法。

  • 使用对象的唯一键并在下一页上检索它。

未用作对象的方法不会映射到表中的单个实例,它们由来自不同数据库的数据组成。

所以我想我的问题是双重的

  • 是否值得使用GKZip进一步压缩查询字符串(这可能吗?)
  • 人们会建议采取哪些其他方法?

9 个答案:

答案 0 :(得分:4)

如果在浏览器中显示下一页的网址无关紧要,可以使用context.items集合。

context.items.add("keyA", objectA)
server.transfer("nextPage.aspx")

然后在下一页:

public sub page_load(...)
    dim objectA as A = ctype(context.items("keyA"), objectA)
    dim objectB as B = objectA.B
end sub

使用此功能的一个原因是,您希望用户相信下一页真的是第一页的一部分。对他们而言,它似乎只是发生了PostBack。

此外,如果您使用“下一页”的唯一方法是首次来自“第一页”,那么您并不需要使用此方法的唯一键。上下文项集合的范围仅适用于此特定请求。

我同意其他提到查询字符串上的序列化对象比使用会话状态更糟糕的海报。如果您确实使用会话状态,请记住在使用后立即清除您使用的密钥。

答案 1 :(得分:2)

我不明白为什么你不会使用会话状态但是......

选项1:Viewstate

选项2:表单参数而不是查询字符串

但是请注意,在序列化/反序列化时,您不会获得相同的对象。您将获得一个新对象,该对象使用序列化的原始值进行初始化。你将最终得到两个对象。

编辑:您可以使用与会话状态

相同的语法在viewstate中存储值

ViewState [“key”] = val;

该值必须可序列化。

答案 2 :(得分:2)

虽然在会话中存储对象可能被认为是不好的做法,但它比通过序列化的查询字符串传递它们更好。

回到经典的asp,在会话中存储对象被认为是不好的做法,因为你创建了线程关联,并且你也限制了你通过添加其他web服务器来扩展网站的能力。这不再是asp.net的问题(只要你使用外部状态服务器)。

还有其他原因可以避免会话变量,但在您的情况下,我认为这是可行的方法。

另一种选择是将需要访问此对象的2个页面组合到一个页面中,使用面板隐藏和显示所需的“子页面”,并使用viewstate存储对象。

答案 3 :(得分:2)

我不认为在查询字符串中传递它或将其存储在会话中是个好主意。

您需要以下其中一项:

a)缓存层。像Microsoft Velocity这样的东西会起作用,但我怀疑你需要那种规模的东西。

b)将密钥放在查询字符串中所需的数据库中的每个对象上,并在下次检索它们时检索它们。 (例如myurl.com/mypage.aspx?db1objectkey=123&db2objectkey=345&db3objectkey=456)

答案 4 :(得分:2)

使用会话状态似乎是最实用的方法,它正是它的设计目的。

答案 5 :(得分:1)

缓存可能也不是这里的答案。正如Telos所说,我不确定你为什么不考虑会议。

如果您的页面依赖于可用的数据,那么您只需在页面加载中抛出一个guard子句......

public void Page_Load()
{

    if(!IsPostBack)
    {   
        const string key = "FunkyObject";
        if(Session[key] == null)
            Response.Redirect("firstStep.aspx");

        var obj = (FunkyObject)Session[key];
        DoSomething(obj);
    }
}

如果会话绝对不在问题中,那么您将不得不在另一页上重新实现此对象。只需在查询字符串中发送唯一标识符,以便再次将其拉回。

答案 6 :(得分:0)

以下是我的工作:

Page1.aspx - 添加我的对象实例的公共属性。添加一个按钮(Button1),将PostBackURL属性设置为〜/ Page2.aspx

Private _RP as ReportParameters
Public ReadOnly Property ReportParams() as ReportParameters
  Get
    Return _RP
  End Get
End Property

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
  _RP = New ReportParameters       
  _RP.Name = "Report 1"
  _RP.Param = "42"    
End Sub

现在,在第二页上,Page2.aspx将以下内容添加到第一个指令下页面顶部的标记处:

<%@ PreviousPageType VirtualPath="~/Default.aspx" %>

然后对于Page2.aspx后面代码中的Page_Load,添加以下内容

If Not Page.PreviousPage is Nothing Then
  Response.write (PreviousPage.ReportParams.Name & " " & PreviousPage.ReportParams.Param)
End If

答案 7 :(得分:0)

会话并非始终可用。例如,当IE上的XSS(跨站点脚本)安全设置阻止存储第三方cookie时。如果您的站点是在非DNS域的站点的IFrame中调用的,则默认情况下将阻止您的cookie。没有cookies =没有会话。

另一个示例是您必须将控制权传递给另一个网站,该网站将回调您的网站作为纯网址,而不是帖子。在这种情况下,您必须将会话参数存储在querystring参数中,考虑到4k大小约束和URL编码,更难以做到这一点,更不用说加密等了。

问题在于大多数内置序列化方法都非常冗长,因此必须采用自己动手操作的方法,可能使用反射。

不使用会话的另一个原因是提供更好的用户体验;会话在N分钟后以及服务器重新启动时清除。好的,在这种情况下,视图状态是可取的,但有时候不可能使用表单。好的,人们可以依靠JavaScript来做回发,但同样,这并不总是可行的。

这些是我目前正在编码的问题。

答案 8 :(得分:0)

面对我所做的类似情况,XML是序列化对象并将其作为查询字符串参数传递。这种方法的困难在于,尽管编码,接收形式抛出异常说“有潜在危险的请求......”。我的方法是加密序列化对象然后编码以传递它作为查询字符串参数。这反过来使查询字符串防篡改(奖励徘徊到HMAC领域)!

FormA XML序列化对象&gt;加密序列化字符串&gt;编码&gt;作为查询字符串传递给FormB FormB解密查询参数值(也作为request.querystring解码)&gt;使用XmlSerializer将生成的XML字符串反序列化为对象。

我可以根据请求分享我的VB.NET代码到howIdidit-at-applecart-dot-net