1

我正在开发一个 asp.net (3.5) 应用程序,我对回发的行为感到困惑。

考虑以下场景:我有一个基本上是表单的 Web 用户控件。然而,每个表单域本身就是一个 Web 用户控件。

在保存按钮的单击事件中,我遍历表单中的所有控件,并检索字段值和引用我将值保存到的数据库字段的字段名称。

点击事件触发回发,在回发期间我访问了控件,有趣的是:数据库字段的属性值变为空!任何人都可以在这里阐明一下吗?

这是一些基本代码:

[Serializable]
public partial class UserProfileForm : CustomIntranetWebappUserControl
{
    protected override void OnInit(EventArgs e)
    {
        //AutoEventWireup is set to false
        Load += Page_Load;
        CancelLinkButton.Click += CancelButtonClickEvent;
        SaveLinkButton.Click += SaveButtonClickEvent;
        base.OnInit(e);
    }

    private void SaveButtonClickEvent(object sender, EventArgs e)
    {
        VisitFormFields();
    }

    private void VisitFormFields()
    {
        var userProfileVisitor = new UserProfileVisitor();

        foreach (var control in Controls)
        {
            if (control is FormFieldUserControl)
            {
                var formField = (FormFieldUserControl) control;
                formField.Visit(userProfileVisitor);
            }
        }
        userProfileVisitor.Save();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindText();
        }
    }

    private void BindText()
    {
        LastNameFormLine.LabelText = string.Format("{0}:", HomePage.Localize("Last Name"));
        LastNameFormLine.InputValue = UserProfile.LastName;
        LastNameFormLine.IsMandatoryField = true;
        LastNameFormLine.IsMultilineField = false;
        LastNameFormLine.ProfileField = "UserProfile.LastName";
        //... the rest of this method is exactly like the 4 lines above.
    }
}

[Serializable]
public abstract class FormFieldUserControl : CustomIntranetWebappUserControl
{
    public string ProfileField { get; set; }
    public abstract void Visit(UserProfileVisitor userProfileVisitor);
}


[Serializable]
public partial class FormLineTextBox : FormFieldUserControl
{
//...  irrelevant code removed... 

    public override void Visit(UserProfileVisitor userProfileVisitor)
    {
        if (userProfileVisitor == null)
        {
            Log.Error("UserProfileVisitor not defined for the field: " + ProfileField);
            return;
        }
        userProfileVisitor.Visit(this);
    }
}

[Serializable]
public class UserProfileVisitor
{

    public void Visit(FormLineTextBox formLine)
    {
        // The value of formLine.ProfileField is null!!!
        Log.Debug(string.Format("Saving form field type {1} with profile field [{0}] and value {2}", formLine.ProfileField, formLine.GetType().Name, formLine.InputValue));
    }

    // ... removing irrelevant code... 

    public void Save()
    {
        Log.Debug("Triggering the save operation...");
    }
}
4

4 回答 4

7

记住 ASP.NET 是无状态的。在页面呈现给浏览器后,创建的任何属性都会被销毁。因此,您必须在每次回发时重新创建对象,或者将它们存储在视图、会话或应用程序状态中。

当您执行一个属性时,您必须告诉它保存视图状态,它不会自动执行此操作。这是视图状态属性的示例。

public string SomePropertyAsString
{
    get
    {
        if (this.ViewState["SomePropertyAsString"] == null)
            return string.Empty;

        return (string)this.ViewState["SomePropertyAsString"];
    }
    set { this.ViewState["SomePropertyAsString"] = value; }
}

public MyCustomType ObjectProperty
{
    get
    {
        if (this.ViewState["ObjectProperty"] == null)
            return null;

        return (MyCustomType)this.ViewState["ObjectProperty"];
    }
    set { this.ViewState["ObjectProperty"] = value; }
}
于 2009-09-04T12:35:45.780 回答
0

首先猜测是BindText()不应该在Page_Load中,而是在Page_Init中,所以控件状态会被保存。

于 2009-09-04T12:35:30.270 回答
0

@David Basarab,这不是真正的afaik,仅在.Net 1.1、.Net2 及更高版本中都是如此,如果您在Init 中执行所有魔术操作,这一切都由框架处理。

于 2009-09-04T12:38:54.250 回答
0

您的问题是回发中没有“ProfileField”,对吗?

解决方案是将其值存储在 ViewState 中(而不是自动实现的属性)。没有它,它在回发时将不可用。

于 2009-09-04T12:42:50.693 回答