为什么我无法访问usercontrol中的页面视图状态?

时间:2010-06-11 06:39:28

标签: asp.net

我在Page的viewstate中存储了一个对象。现在,当我在usercontrol上访问相同的viewsate对象时,它显示为null。我甚至尝试在usercontrol和page中创建具有相同名称的相同视图状态。它们具有不同的值。

我知道viewstate是受保护的属性。这个东西如何在上面的场景中实现,或者是否有其他原因导致这种行为。

编辑:

Usercontrol在页面标记中。我没有动态加载它。

我有一个页面EditFacilityworkType.aspx。在页面上,我有一个usercontrol FacilityWorkTypeDetails.aspx(FacilityWorkTypeDetails1)。在这个用户控件中,我有一个用户控件Workflow.aspx(Workflow1)

Page的Page_Load() 我正在页面的page_load()上检索workflowdetails。

 FacilityWorktype facilityWorkType = facilityDetails.GetFacilityWorktypeDetail(SessionHelper.FacilityWorkTypeID);
 ViewState["WorkFlow"] = facilityWorkType.FacilityWorkTypeWorkFlow

在usercontrol内部FacilityWorkTypeDetails.aspx。我有一个属性

 public FacilityWorktype FacilityWorkTypeDetails
{
    get
    {
        #region Fill FacilityWorktype
        return GetEntityFromControl();
        #endregion
    }
    set
    {
        PopulateControls(value);
    }
}

现在我在页面加载页面

中设置此属性
FacilityWorkTypeDetails1.FacilityWorkTypeDetails = facilityWorkType;

在Workflow.aspx内部,我有一个属性

/// <summary>
/// Property to fill entity object from controls on this page
/// </summary>
public WorkFlow WorkFlowDetails
{
    get
    {
        return GetEntityFromControls();
    }
    set
    {            
        BindTranscriptionMethodDDL(ddlTranscMethod);
        PopulateControls(value);
    }
}

现在是FacilityWorkTypeDetails1的PopulateControls(),我正在设置workflow1的属性

private void PopulateControls(FacilityWorktype value)     {

    Workflow1.WorkFlowDetails = value.FacilityWorkTypeWorkFlow;
}

现在我正在从

中检索值
 private WorkFlow GetEntityFromControls()
 {
     WorkFlow workFlow = (ViewState["WorkFlow"] as WorkFlow) ?? new WorkFlow();  
     //workFlow  is null

 }

所以现在在这个函数里面,workFlow为null。我想问一下,当我在页面中设置viewstate时,为什么它为null。

4 个答案:

答案 0 :(得分:37)

Scherand在这里非常正确。我想补充一下他带来的东西。

从System.Web.UI.Control派生的每个控件都具有ViewState属性。 Under-the-hood酒店是StateBag系列。 Control的每个实例都有自己的StateState StateBag,正如Scherand所提到的,ViewState对于控件来说是唯一的。当页面被渲染时,页面的整个控制树被迭代,所有ViewState集合被合并为树状结构,并且最终结构被序列化为字符串并呈现给页面。

由于ViewState属性被标记为受保护,因此无法使用反射从用户控件访问Page的ViewState。

但是,老实说,你应该放弃使用ViewState作为数据存储介质。以下是一些原因:

  1. ViewState被渲染并输出到客户端浏览器。维护集合中的数据对象会使页面的输出膨胀。
  2. 除非您在ViewState上启用了加密,否则呈现给客户端浏览器的编码字符串可以手动解码,只需任何人都可以访问数据对象的内容。这是一个相当重要的安全漏洞。
  3. 听起来您只想在页面和用户控件之间共享数据。在控件之间共享数据的最佳方法是使用“Items”集合(这是HttpContext类的属性)。该集合是一个Hashtable,可以从您的页面和用户控件中访问,如下所示:

    Context.Items["Workflow"] = workflowInstance;
    

    使用此技术的最佳部分是它不会产生任何额外的开销或膨胀页面输出。 Items集合存在于单个HTTP请求的上下文中。这意味着当您的请求完成并且您的Page的输出已呈现给客户端浏览器时,Items集合将从服务器内存中清除。它是ASP.NET中临时数据存储的理想媒介。

    现在,如果您希望数据对象不仅可以访问当前请求,那么最好将对象存储在Session中。

答案 1 :(得分:4)

我仍然不喜欢这里的一切(见上面的评论)。但我很确定你误解了ViewState

ViewState是每个控件,而不是每个请求或会话或其他任何内容。

在您的示例中,考虑一些其他控件(例如标准ASP.NET控件),由于某种原因决定将具有“{1}}”名称的内容放入viewstate中。如果你想要做的事情会起作用,这个对象会覆盖你的对象(或者反过来,你的对象会被另一个覆盖)。

或者我错过了什么?

也许阅读TRULY Understanding ViewState可以帮助您了解viewstate是什么/它是如何工作的(是的,我真的很喜欢这篇文章,这就是我继续发布该链接的原因)。

答案 2 :(得分:1)

在回发上你创建了控件吗?如果后面的代码没有创建ctrl,那么它将不知道它。

仅当这是生成的控件时才适用。您可能需要发布代码和更多信息才能获得适当的答案。

Viewstate是一个怪物,这就是我们很多人去MVC的原因。

答案 3 :(得分:1)

页面视图状态是与viewcontrol可以访问的视图状态不同的状态包。每个控件都有自己的私有视图状态。因此,您无法从usercontrol代码隐藏中直接访问页面视图状态。

您可以使用属性或方法公开viewstate值,然后调用这些属性/方法