3

If I alter the html on a page using JavaScript, how can I access those changes in my ASP.NET code behind?

I found some dhtml "drag and drop" code online (http://www.dhtmlgoodies.com/scripts/drag-drop-nodes/drag-drop-nodes-demo2.html), but after moving list items from one control to another, I don't know how to "access" each control in the code behind so I can save the list items in each control.

I tried using the HTML Agility pack, but it seems like I'm only able to access the unaltered html - meaning all the controls are empty.

Any help/suggestions are appreciated. Or any suggestions as to a better way of accomplishing this are welcome (jQuery? Ajax Toolkit?).

EDIT: Here's some code. I'm able to populate an ASP Label control (_saveContent), from the JavaScript function saveDragDropNodes, with the "ul" ID and the corresponding "li" controls that I've dragged and dropped. When clicking the save button however, my Label control no longer contains any Text...

function saveDragDropNodes() {
        var saveString = "";
        var uls = dragDropTopContainer.getElementsByTagName('UL');
        for (var no = 1; no < uls.length; no++) {   // LOoping through all <ul>
            var lis = uls[no].getElementsByTagName('LI');
            for (var no2 = 0; no2 < lis.length; no2++) {
                if (saveString.length > 0) saveString = saveString + ";";
                saveString = saveString + uls[no].id + '|' + lis[no2].id;
            }
        }
        document.getElementById("<%=_saveContent.ClientID %>").innerHTML = saveString.replace(/;/g, ';<br>');
    }
  <div id="dhtmlgoodies_dragDropContainer">
    <div id="dhtmlgoodies_listOfItems">
        <div>
            <p>
                Available Items</p>
            <ul id="allItems" runat="server">
            </ul>
        </div>
    </div>
    <div id="dhtmlgoodies_mainContainer">
        <div>
            <p>
                Group 1</p>
            <ul id="_ul1">
            </ul>
        </div>
        <div>
            <p>
                Group 2</p>
            <ul id="_ul2">
            </ul>
        </div>
    </div>
    <asp:Label ID="_lSave" runat="server" ForeColor="Red" EnableViewState="false" />
</div>
<div id="footer">
<span onmouseover="saveDragDropNodes()">
    <asp:Button ID="_btnSave" runat="server" Text="Save Groups" OnClick="_btnSave_OnClick" /></span>
</div>
<ul id="dragContent">
</ul>
<div id="dragDropIndicator"></div>
<asp:Label ID="_saveContent" runat="server" />

Code Behind:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
        GetItems()
    End If
End Sub
Private Sub GetItems()
    Dim dt As DataTable = DbHelper.GetDataTableForSP("GetListOptions")
    Dim index As Integer = 1
    For Each _row As DataRow In dt.Rows
        Dim _li As New HtmlGenericControl("li")
        _li.ID = _row("ClassId")
        _li.Attributes.Add("runat", "server")
        _li.InnerHtml = String.Format("{0}) {1} {2}", index, _row("ClassId"), _row("ClassDescription1"))
        allItems.Controls.Add(_li)
        index += 1
    Next
End Sub
Private Sub SaveGroups()

    Dim str As String = _saveContent.Text /*No text here */
    _lSave.Text = "Groups Saved!"
    GetItems()
End Sub
Mark B
  • 1,166
  • 1
  • 19
  • 31
  • Are you saying that you need to edit the html on the client and then want to send it back to the server? – frosty Sep 27 '11 at 16:05
  • @aaronfrost yes. I'm editing the html via JavaScript, and I'm hoping to then save the edited html from the server side code. – Mark B Sep 27 '11 at 16:16
  • On a button click event? Or what do you want to trigger the save to the server? – frosty Sep 27 '11 at 16:19
  • @aaronfrost. I'm hoping to save on a button click, after the user has moved all their items to the correct
      – Mark B Sep 27 '11 at 16:29
    • I edited my answer to include a button click event handler. – frosty Sep 27 '11 at 16:36

    4 Answers4

    2

    The only content posted back to the server are values from form fields. See: Form submission.

    You have two options:

    1. Make use of ajax to pass the HTML from the client to the server.
    2. Use a hidden input field to store the HTML just before the page posts back.

    Here is an example of the latter:

    Markup

    <div id="content"></div>
    <asp:HiddenField ID="hiddenContentField" runat="server" />
    <asp:Button ID="button1" runat="server" Text="Post back" OnClick="button1_Click" OnClientClick="storeContent();" />
    

    Script

    function storeContent() {
        $('#<%= hiddenContentField.ClientID %>').val($('#content').html());
    }
    

    Any changes made in the content element will then be stored in the hidden input element and sent up to the server on postback.

    Then in the code behind you can access the HTML passed up like so:

    protected void button1_Click(object sender, EventArgs e)
    {
        string html = hiddenContentField.Value;
    }
    

    Hope this helps.

    jdavies
    • 12,784
    • 3
    • 33
    • 33
    • That did it, thanks! I had to set validateRequest="false" in the web.config though... I don't think it liked the "<" characters. – Mark B Sep 27 '11 at 18:38
    • It may result in security issue. Someone can post the JavaScript along with your html hidden field. While you try to render the posted html in webpage, hackers JavaScript can start executing on your page. :( – Bharath Sep 29 '11 at 05:33
    • @Bharath - This is a good point. The threat could be reduced through the use of an MVC esque antiforgerytoken. See: [Generating AntiForgeryToken in WebForms](http://stackoverflow.com/questions/1321508/generating-antiforgerytoken-in-webforms) – jdavies Sep 29 '11 at 07:43
    1

    First of all, HTML code changes will not posted to Server by default. To achieve the drag-n-drop element, please follow the steps below

    1. Uniquely name(id) the Container panels and child elements in it.
    2. Using jQuery/JavaScript track the child element movements from on container panel to another and store the id of element's old parent panel and new parent in json/dictionary object.
    3. While clicking on save button post the tracked dictionary object to server.
    4. On server-side, get the posted json object using Page.Request.
    5. Using the id's stored in json object, Save the list items.

    Hope this will helps.

    Bharath
    • 797
    • 6
    • 14
    0

    Specify runat="server" on the controls you need to access from code-behind. Also, remember to use ClientID to reference server controls in JavaSript:

    var el = document.getElementById("<%=MyElement.ClientID%>");
    
    James Johnson
    • 45,496
    • 8
    • 73
    • 110
    • Thanks, I tried that but the dhtml in that sample code doesn't work when I add runat="server" to the
        and
      • html controls. I'm hoping there's a way I can access the html from the server side... if that's possible.
      – Mark B Sep 27 '11 at 16:18
    • You should definitely be able to get it working with `runat="server"`. Do you have any Javascript? If so, you'll need to use `ClientID` to reference the controls in JavaScript. Can you post the code? – James Johnson Sep 27 '11 at 16:24
    • Thanks James, your post gave me another idea though. rather than adding runat="server" to the controls, I'm trying to populate an ASP Label control with all the li controls. I updated my post to include some code, which is "almost" working. – Mark B Sep 27 '11 at 18:13
    0

    First, add the jQuery lib to your page header. Add it from the Google CDN, as most of your users should have it cached.

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
    

    Then, after the JS has modified the HTML, call sendToServer and it will post the html you select to the servlet you enter.

    function sendToServer(){
        var myhtml = document.getElementById('theIdOfTheContainer').innerHTML;
        $.post("http://yoururlhere.com",myhtml,function(responseFromServer){
            //some code to handle the response from the server on the client.
        });
    }
    $('#buttonid').click(sendToServer);
    

    I am having you use jQuery for this, as it is a very powerful AJAX library. jQuery does three things extremely well, and one of them is AJAX. Inside the post method, the third parameter is an anonymous function. That is the function that gets called once the data has successfully been sent to the server. So, yeah. Try it out, let me know.

    frosty
    • 21,036
    • 7
    • 52
    • 74