Domanda

Sto sviluppando un (3.5) applicazione asp.net e io sono perplesso con il comportamento dei postback.

Si consideri il seguente scenario: Ho un controllo utente Web che è sostanzialmente una forma. Tuttavia ogni campo di modulo è un controllo utente web in sé.

In caso click del pulsante di salvataggio ho scorrere tutti i controlli nella mia forma e recuperare il valore del campo e il nome del campo che si riferisce al campo base di dati che sto salvando il valore.

L'evento click innesca un postback ed è durante il postback che visito i controlli e qui è la cosa divertente: il valore della proprietà per il campo base di dati è diventato nullo! Qualcuno potrebbe gettare una luce qui?

Ecco codice di base:

[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...");
    }
}
È stato utile?

Soluzione

Ricordati di ASP.NET è senza stato. Qualsiasi proprietà create vengono distrutti dopo che la pagina è stata rendere al browser. Quindi, è necessario ricreare gli oggetti su ogni palo o memorizzarli in vista, sessione, o lo stato dell'applicazione.

Quando si esegue una proprietà dovete dire per salvare lo stato di visualizzazione che non lo fa automaticamente. Ecco un esempio di una proprietà dello stato di visualizzazione.

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

Altri suggerimenti

Per prima ipotesi è che BindText () non dovrebbe essere in Page Load, ma in Page_Init, in modo che il controllo statale sarà salvato.

@ Davide Basarab, questo non è vero per quanto ne so, ed è stato solo il caso in .Net 1.1, in .NET2 e questa è tutto gestito dal quadro se si fa tutte le cose magia nel Init.

Il tuo problema è che 'ProfileField' non è disponibile sul postback, giusto?

La soluzione è quella di memorizzare il valore per che nel ViewState (invece di una proprietà auto-implementato). Senza questo, non sarà disponibile sul postback.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top