2009-09-04 3 views
1

Я разрабатываю приложение asp.net (3.5), и я озадачен поведением postbacks.Почему я теряю ссылки на объекты после обратной передачи?

Рассмотрите следующий сценарий: У меня есть пользовательский элемент управления, который в основном представляет собой форму. Однако каждое поле формы является элементом управления веб-пользователями.

В событии клика кнопки сохранения я повторяю все элементы управления в своей форме и получаю значение поля и имя поля, которое относится к полю базы данных, в котором я сохраняю значение.

Событие click инициирует обратную передачу, и во время обратной передачи я просматриваю элементы управления, и вот что смешно: значение свойства для поля базы данных стало нулевым! Может ли кто-нибудь пролить свет здесь?

Вот некоторые основные код:

[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..."); 
    } 
} 

ответ

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; } 
} 
+0

Я кодирую в .net с самого недавнего времени. Таким образом, я еще не знаю все о структуре. Однако, в отношении вашего ответа, я думал, что это была цель объекта viewstate ... – Pablo

+0

См. Редактировать, как вы должны сохранять элементы для просмотра состояния. –

0

Первое предположение было бы, что BindText() не должно быть в Page_Load, но в Page_Init, поэтому государственный контроль будет сохранен.

0

@David Басараб, это не так AFAIK, и только случай в .NET 1.1, в .Net2 и выше это все обрабатывается в рамках, если вы делаете все волшебное вещество в Init.

+1

Даже в более новых версиях фреймворка я не думаю, что он волшебным образом сохраняет значения свойств. Если это так, я писал больше кода, чем мне нужно :) У вас есть ссылка на это? –

+0

Попробуйте это, добавьте placeholder 'Bla' в веб-форму: protected void Page_Init (отправитель объекта, EventArgs e) { TextBox tb = new TextBox(); Кнопка bt = new Button(); bt.Click + = (s, ev) => bt.Text = tb.Text; Bla.Controls.Add (tb); Bla.Controls.Add (bt); } работает как очарование. –

0

Ваша проблема в том, что 'ProfileField' недоступен в Postback, правильно?

Решение заключается в сохранении значения для него в ViewState (вместо автоматического свойства). Без этого он не будет доступен после обратной передачи.

+0

Код для использования ViewState, проверьте редактирование Дэвида. –