Asp.net 通过查询字符串传递对象

Asp.net 通过查询字符串传递对象,asp.net,vb.net,Asp.net,Vb.net,我有一个对象A,它又有一个类型为对象B的属性 Class A property x as Object B End Class 在我的ASP.NET页面上,当我选择一个映射到类型a的对象的gridview项时,我将该对象序列化到查询字符串上,并将其传递到下一个页面 但是,如果属性x实际上有一些值,我就会遇到问题,因为它看起来超过了4k的查询字符串容量长度(尽管我认为对象没有那么大) 为此,我已经考虑了以下方法 会话变量 未使用该方法,因为我读到这是一种不好的做法。 使用对象的唯一键并

我有一个对象A,它又有一个类型为对象B的属性

Class A

property x as Object B

End Class
在我的ASP.NET页面上,当我选择一个映射到类型a的对象的gridview项时,我将该对象序列化到查询字符串上,并将其传递到下一个页面

但是,如果属性x实际上有一些值,我就会遇到问题,因为它看起来超过了4k的查询字符串容量长度(尽管我认为对象没有那么大)

为此,我已经考虑了以下方法

  • 会话变量
未使用该方法,因为我读到这是一种不好的做法。

  • 使用对象的唯一键并在下一页检索它
方法不使用,因为对象不映射到表中的单个实例,它们由来自不同数据库的数据组成。

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

  • 是否值得使用GKZip进一步压缩查询字符串(这可能吗??)
  • 人们会建议用什么其他方法来做这件事

我不明白您为什么不使用会话状态,但

选项1:视图状态

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

但也要注意,序列化/反序列化时不会返回相同的对象。您将获得一个新对象,该对象使用序列化出来的原始对象的值进行初始化。你会得到两个物体

编辑:可以使用与会话状态相同的语法在viewstate中存储值

ViewState[“key”]=val


但是,该值必须是可序列化的。

缓存可能也不是答案。正如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);
    }
}

如果会话完全超出了问题的范围,那么您必须在另一个页面上重新具体化该对象。只需在querystring中发送唯一标识符,这样您就可以再次将其拉回来。

虽然在会话中存储对象可能被认为是不好的做法,但这比通过序列化querystring传递它们要好几光年

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

避免会话变量还有其他原因,但在您的情况下,我认为这是正确的选择


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

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

您需要以下选项之一:

a) 缓存层。像微软Velocity这样的东西会奏效,但我怀疑你是否需要这样规模的东西


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

如果在浏览器中显示下一页的url无关紧要,则可以使用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
使用它的一个原因是,如果您希望用户相信下一页实际上是第一页的一部分。对他们来说,这似乎只是发生了回发

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


我同意其他人的观点,他们提到querystring上的序列化对象比使用会话状态更糟糕。如果您确实使用会话状态,请记住在使用后立即清除您使用的密钥。

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

以下是我所做的:

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

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" %>

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

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

问题是,大多数内置序列化方法都非常冗长,因此必须求助于自己的方法,可能使用反射

不使用会话的另一个原因仅仅是为了提供更好的用户体验;会话在N分钟后以及服务器重新启动时被清除。好的,在这种情况下,viewstate更可取,但有时不可能使用表单。好的,可以依靠JavaScript进行回发,但这并不总是可能的


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

面对类似的情况,我所做的是用XML序列化对象,并将其作为查询字符串参数传递。这种方法的困难在于,尽管进行了编码,接收表单仍会抛出异常,称为“潜在危险的请求…”。我是怎么得到ar的
If Not Page.PreviousPage is Nothing Then
  Response.write (PreviousPage.ReportParams.Name & " " & PreviousPage.ReportParams.Param)
End If