polterguy / phosphorusfive

A Full Stack RAD Web Application Development Framework
https://gaiasoul.com
GNU General Public License v3.0
178 stars 36 forks source link

Controls are not persisted across postbacks #20

Closed janek-lopez closed 6 years ago

janek-lopez commented 6 years ago

First of all let me tell you i'm really enjoying p5.ajax library, but maybe because i'm still learning i have an issue.

As i understand from the docs if i use CreatePersistentControl the controls should be persisted between postbacks but in my case the controls just dissapear.

In my case using the code below if i click a ocuple of times the "Click me" button and then click the "Postabck!!!" button all inserted elements dissapear.

Demo.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Demo.aspx.cs" Inherits="Phosp5.Demo" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <p5:Literal
                runat="server"
                ID="btnAdd"
                Element="button"
                onclick="add_ctrl">
                Click me!
            </p5:Literal>

            <p5:Container
                runat="server"
                ID="mainCtr"
                Element="ul" />
        </div>

        <asp:Button ID="btnPostback" runat="server" Text="Postback!!" OnClick="btnPostback_Click" />

        <div>
            <asp:Literal ID="txtMsg" runat="server"></asp:Literal>    
        </div>
    </form>
</body>
</html>

Demo.aspx.cs

using System;
using p5.ajax.core;
namespace Phosp5
{
    public partial class Demo : AjaxPage
    {
        [WebMethod]
        protected void add_ctrl(p5.ajax.widgets.Literal sender, EventArgs e)
        {
            sender.innerValue = "Hello World!";
            sender["style"] = "background-color:LightBlue;";

            var lit = mainCtr.CreatePersistentControl<p5.ajax.widgets.Literal>();
            lit.Element = "li";
            lit["class"] = "some-class-value";
            lit.innerValue = "Item no; " + mainCtr.Controls.Count;
        }

        protected void btnPostback_Click(object sender, EventArgs e)
        {

        }
    }
}
polterguy commented 6 years ago

Thank you.

This seems like a bug, let me investigate it a bit, and I'll come back to you.

polterguy commented 6 years ago

PS, out of curiosity, do you really need that postback ...? There's really nothing you can do with a traditional postback, that you can't do with an Ajax callback (I think) ...?

janek-lopez commented 6 years ago

Hi thanks for the fast response.

To be honest i read in the p5.ajax github page the part where you said

This means, that you do not need to re-create its widgets collection upon postbacks or callbacks, since it'll keep track of whatever widgets it contains, at any specific point in time, automatically for you.

and thought, man that will be cool as hell and went straight to test that functionality, just to found that it doesn't work for me.

So apart from that I haven't really thought about a scenario where I'd need a full postback. Maybe soon as i still discovering amazing things to do with this gem.

polterguy commented 6 years ago

You are right, it is a bug indeed. I am not sure I could see a use-case for it though, except when interacting with legacy code though ...

I'll have a look at it today, and come back to you (just gotta finish up something else first)

polterguy commented 6 years ago

I have just checked in new code that fixes this. The "bug" was due to that p5.ajax removes all traces of the ViewState, including the "__VIEWSTATE" HTTP POST parameter, added as a hidden input element by the ASP.NET core WebControls.

When the "__VIEWSTATE" hidden input element is removed, ASP.NET will not even try to wire up events, or serialise its native controls for that matter, hence the bug.

In p5.ajax I remove this hidden input element by default, which is done during rendering of the HTML in the HtmlFilter response filter.

Instead of changing the logic though, I added a property on the "AjaxPage" class, which allows you to override this logic, and avoid having p5.ajax removing the "__VIEWSTATE" input field, to support mixing in traditional WebControls.

I chose this path, since I like the idea of "cleaning up" the HTML, as much as possible, including removing "dead tags", which the "__VIEWSTATE" input element really is, for most cases - Except when the user wants to mix in traditional WebControls - At which point we'll need to support keeping that value around.

Notice, even if you tell p5.ajax to not remove the ViewState through this property, the input element will still never have any value.

This fix will be a part of the next release, which is due in some 1-2 weeks. If you can't wait that long, you can check out the entire diff here, and probably apply it easily to your own code.