Avatar billede davidfossil Nybegynder
21. marts 2006 - 15:43 Der er 11 kommentarer og
2 løsninger

ViewState forsvinder ved 2. postback

Jeg har et virkelig drilsk problem med ViewState i en custom control. Min kontrol overskriver SaveViewState() og LoadViewState() og alt fungerer fint ved første postback. Ved andet postback går der dog noget galt og det jeg har gemt i ViewState bliver væk.

Følgende er et stærkt simplificeret eksempel hvor problemet opstår. Først en custom control i C# og så en test page.

Håber at nogen kan knække den, for jeg er vist selv ved at have stirret mig helt blind.

----------------------------------

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace MyNamespace
{
    public class MyControl : System.Web.UI.WebControls.WebControl
    {
        public MyControl()
        {
        }

        private MenuItem _item = new MenuItem();
        public MenuItem Item
        {
            get
            {
                if (this.IsTrackingViewState)
                {
                    ((IStateManager)_item).TrackViewState();
                }
                return _item;
            }
        }

        protected override void RenderContents(HtmlTextWriter writer)
        {
            writer.Write(_item.Text);
        }

        protected override object SaveViewState()
        {
            object[] obj = new object[2];
            obj[0] = base.SaveViewState();
            obj[1] = ((IStateManager)_item).SaveViewState();
            return obj;
        }

        protected override void LoadViewState(object savedState)
        {
            object[] obj = (object[])savedState;
            ((IStateManager)_item).LoadViewState(obj[1]);
            base.LoadViewState(obj[0]);
        }
    }
}

----------------------------------

<%@ Page Language="C#" %>
<%@ Register Namespace="MyNamespace" TagPrefix="test" %>

<script runat="server">
void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        ctrl.Item.Text = "Jubii";
    }
}
</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <test:MyControl ID="ctrl" runat="server" />
            <asp:Button Text="postback" runat="server" />
        </div>
    </form>
</body>
</html>
Avatar billede snepnet Nybegynder
21. marts 2006 - 17:19 #1
hej david - kan du udvide dit eksempel med en illustration af hvad et MenuItem er, således at vi kan se hvad der et for properties du vil gemme i viewstate.... umiddelbart vil jeg gætte på at du kommer til at slette din custom viewstatehåndtering fremfor at udvide den.
bruger du for øvrigt asp.net 2.0 - eller 1.1?
mvh
Avatar billede davidfossil Nybegynder
21. marts 2006 - 18:45 #2
Vi er i .NET 2.0 og objektet som jeg gerne vil gemme bor her:
System.Web.UI.WebControls.MenuItem
Avatar billede snepnet Nybegynder
21. marts 2006 - 19:37 #3
HAHA :oD - ak ja ... fair nok... Overvejede ikke lige at det kunne være noget indbygget :o)

Men altså ... Jeg forstår ikke hvad det er du gerne vil.... Det eksempel du har sendt synes jeg ikke illustrerer det, da du ikke får gemt en reel værdi i dit viewstate med den kode (kun null'er).
Et MenuItem vedligeholder som udgangspunkt selv sit viewstate, og det virker udfra det du skriver til sidst, som om du er interesseret i at gemme et objekt af typen MenuItem i ViewState, og det ville være en meget speciel (og uhendsigtsmæssig løsning)...

Såhh.... Jeg er bange for at jeg har brug for lidt mere hjælp - sorry.

Mvh
Avatar billede davidfossil Nybegynder
21. marts 2006 - 22:00 #4
Helt i orden - det kan godt være at det er mig der ikke helt er klar over hvordan det er meningen jeg skal bruge ViewState begrebet. Jeg prøver lige at forklare mit scenarie:

Jeg sidder og roder med en custom control som skal udgøre et alternativ til den i .NET 2.0 indbyggede Menu webcontrol. Min kontrol holder en samling af den allerede eksisterende MenuItem i en hierakisk struktur. Hele min webcontrol virker som den skal (rendering, databinding etc.) - pånær lige postbacks. I første omgang forsvandt alle menupunkter ved første postback, men efter at have overskrevet SaveViewState og LoadViewState er det lykkedes at få dem til at overleve første postback, for så at forsvinde ved det næste. Idéen til at overskrive disse to metoder er opstået gennem reflection på System.Web.UI.WebControls.Menu.

Hjalp det på vej? :)
Avatar billede snepnet Nybegynder
22. marts 2006 - 23:29 #5
mmm... tjo lidt, men ikke rigtig noget der kan gøre at jeg kan give dig et bud.
du skal være meget velkommen til at lægge nogle kontaktoplysninger herud - så skal jeg nok skrive til dig, og du kan så sende projektet til mig... så kigger jeg på det.
mvh
Avatar billede davidfossil Nybegynder
24. marts 2006 - 16:49 #6
Jeg er nået en smule videre nu tror jeg. Det er lykkedes at gemme et MenuItem i sidens viewstate, på tværs af første, andet og alle andres postbacks. Desværre er jeg allerede rendt ind i det næste problem:

ctrl.Item.Text = "Bum";
ctrl.Item.ChildItems.Add(new MenuItem("hej"));

Teksten "Bum" bliver gemt og loadet igen uden problemer, men ChildItems bliver desværre tømt ved postback. Hvorfor s**an bliver den nu ikke gemt med?

Jeg har nu uploadet de tre filer projektet består af til en webserver, så du (og andre) kan snuppe det og forsøge at finde min fejl: http://hman.dk/menutest.zip
Avatar billede snepnet Nybegynder
24. marts 2006 - 18:00 #7
kontroller bliver ikke gemt i viewstate.
din root bliver fordi den er indsat deklarativt, hvorimod dynamisk tilføjede childs ikke vil blive hængende....
det er som det altid har været. vil du indsætte kontrollerne dynamisk, skal du gøre det hver gang.
mvh
Avatar billede davidfossil Nybegynder
24. marts 2006 - 19:22 #8
Hov hov, nu læser du ikke hvad jeg skriver ;)

ctrl.Item.ChildItems.Add(new MenuItem("hej"));

Jeg tilføjer IKKE en ny kontrol til Control collection, men derimod et child til den MenuItem som deklerativt bliver gemt. Tilsyneladende findes der dog en lignende begrænsning her da mit root MenuItem gemmes fint, men børnene droppes. I en af mine tidligere forsøg lykkedes det dog også at få børnene gemt - i det tilfælde havde jeg dog problemet med at alt forsvandt ved 2. postback.
Avatar billede davidfossil Nybegynder
24. marts 2006 - 19:30 #9
Jeg forstår nu hvad der gik galt tidligere. Problemer var at når jeg loade mit item tilbage fra den serialiserede viewstate glemte jeg at kalde TrackViewState() på det gendannede objekt. Derfor gik den fint igennem første postback, men blev slet ikke gemt ved andet postback.

Nu er jeg så bare forvirret over hvordan jeg tidligere har kunne få sub items til at blive gemt, når dette tilsyneladende ikke længere vil lade sig gøre. Jeg må forsøge at genskabe det kode jeg havde gang i i går for at kunne se nærmere på forskellene. Sig endelig til hvis du kan hitte på noget :)
Avatar billede snepnet Nybegynder
24. marts 2006 - 21:14 #10
jepjep - jeg er med på hvad du gør, men det viser sig ved fintælling at menu/menuitem's er en lidt speciel kontruktion.
MenuItem er overhovedet ikke kontroller - og bliver rent faktisk hængende i menuen pr. default... meget specielt - kode som dette går altså godt (som du jo så også har opdaget):

<asp:Button Text="postback" runat="server" ID="btn" OnClick="btn_Click" />
<br />
<asp:Menu ID="menu" runat="server"></asp:Menu>

// og handleren
protected void btn_Click(object sender, EventArgs e)
{
    menu.Items.Add(new MenuItem("blah"));
}

det er jo sådan set en konstruktion der normalt ikke går godt i asp.net sammenhæng, men menuen understøtter det, så det er jo sådan set interessant nok.
men... jeg er lidt usikker på hvad det egentlig er du gerne vil frem til.... Hvad er det du ikke kan med den medfølgende menu?

det er en lidt atypisk kontrol - og nok ikke noget super-udgangspunkt for at komme igang med custom controls (hvis det er det der er planen).

og et lille spørgsmål ... er der en speciel årsag til at du ikke har baseret din egen kontrol på den eksisterende menu?

mvh
Avatar billede davidfossil Nybegynder
24. marts 2006 - 22:09 #11
Well, det er sådan at jeg har implementeret min egen Menu kontrol idet jeg er temmelig utilfreds med det markup den indbyggede Menu producerer. For at slippe for at opfinde den dybe tallerken har jeg dog gjort brug af de allerede eksisterende klasser MenuItem og MenuItemCollection. Alt har virket helt som det skulle, og jeg bruger allerede kontrollen flere steder. Problemet opstår så (som så mange gange før) når jeg forsøger at lave et postback til en side med min custom menu på. Resten af historien kender du.

Du spørger om jeg ikke kunne have nedarvet fra den eksisterende Menu, og jo det kunne jeg givetvis godt, men så ville jeg stå med 1000 public properties relateret til menuens tabel markup som jeg ikke kan bruge til noget. For at holde alt pænt og rent valgte jeg derfor oprindeligt at lade min kontrol arve direkte fra WebControl.

Tilbage til sagen: Jeg kommer nærmere og nærmere kernen tror jeg. Det er nu lykkedes mig at lave en menu hvor alt overlever første postback, men kun første lag af menuen overlever de efterfølgende. Problemet er lokaliseret: Den MenuItemCollection som jeg har som public property i min menu får ved oprettelsen kaldt TrackViewState(). Denne metode kaldes nu (jf min forrige kommentar her) også når jeg gendanner objektet fra den gemte ViewState. Problemet er så bare at TrackViewState() ikke automatisk bliver kaldt for de underliggende MenuItems. Om jeg fatter hvorfor? Nej, men nu er jeg fast besluttet på at jeg bliver nødt til at fatte det inden aftenen er omme :-)
Avatar billede davidfossil Nybegynder
24. marts 2006 - 23:58 #12
Yes, jeg nåede det! 10 minutter før midnat :D

Dvs. jeg har måske ikke helt forstået det endnu, men jeg har løst problemet. Efter en smule reflection over System.Web.UI.WebControls.Menu forsøge jeg et nyt setup, hvor jeg i stedet for at kalde TrackViewState() på mit root MenuItem kalder samme metode på mitRootItem.ChildItems. Som sagt har jeg endnu ikke helt fattet hvorfor dette gør en forskel (den første kalder alligevel den anden), men det ser ud til at have løst alle problemer med postback.

Hvis du nu smider et svar så kan du da lige få en del af de udlovede points. Jeg har jo sådan set løst problemet selv, men jeg er ikke sikker på at jeg ville have fået nosset mig sammen til det hvis ikke du havde skubbet til mig gennem denne tråd en gang imellem ;)
Avatar billede snepnet Nybegynder
26. marts 2006 - 20:32 #13
hehe ... cool - tillykke med et :o)... det er sjældent trivielt at få den slags til at virke, og så er det tilsyneladende et lidt speciel type du sidder med der :o)
mvh
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester