我正在开发一个asp.net(3.5)应用程序,我对回发的行为感到困惑。
考虑以下场景:我有一个基本上是表单的Web用户控件。但是,每个表单字段本身都是Web用户控件。
在保存按钮的click事件中,我遍历表单中的所有控件,并检索字段值和引用我将值保存到的数据库字段的字段名称。
click事件触发回发,并且在回访期间我访问控件,这是有趣的事情:数据库字段的属性值变为null!谁能在这里曝光?
以下是一些基本代码:
[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...");
}
}
答案 0 :(得分: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; }
}
答案 1 :(得分:0)
首先猜测BindText()不应该在Page_Load中,而应该在Page_Init中,因此控制状态将被保存。
答案 2 :(得分:0)
@David Basarab,这不是真的afaik,只是.Net 1.1中的情况,在.Net2及以上这个都是由框架处理的,如果你在Init中做了所有神奇的东西。
答案 3 :(得分:0)
你的问题是在Postback上没有“ProfileField”,对吗?
解决方案是在ViewState中存储该值(而不是自动实现的属性)。没有它,它将不会在回发中提供。