Learning While Aging

How to use the ‘Save’ icon in FCKEditor to save FCKEditor content on the server side in ASP.NET

I wrote two posts before regarding the integration and the customization of FCKEditor in ASP.NET and was asked by a reader how to use the “Save” icon  in the FCKEditor’s toolbar set to perform the actual save on the server side. I am sorry for the long delayed answer for that question because I have been tied up with my work and haven’t had much time to look into the problem until recently.

2009-06-02_160117

When the “Save” icon in FCKEditor’s toolbar is clicked, a PostBack is generated. The reason is that it initiates a JavaScript function call to submit the form automatically. The question is how to capture this PostBack? The intuitive place to check is Page_Load event handler:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
                            Handles Me.Load
    If Not IsPostBack Then
        'Set up FCKEditor's BasePath
        Me.fckEditorNote.BasePath = Request.ApplicationPath & "/Common/fckeditor/"

        'Perform Page Load tasks, if any

    Else
        'Capture PostBack and then save data here

    End If

End Sub

This will work if you don’t have any other server control that cause PostBack. However, the more common scenario is you have some other server controls that also cause PostBack, such as Button, LinkButton, HyperLink, ImageButton, etc., then the above code will not be able to tell which PostBack was caused by the “Save” icon and which was caused by the other server controls. The good news is that ASP.NET injects two famous hidden fields when a page is rendered: “__EVENTTARGET” and “__EVENTARGUMENT”. “__EVENTTARGET” stores the control that causes the PostBack and “__EVENTARGUMENT” stores the argument of the PostBack, and they are populated only when a PostBack is generated by server control. It means that if the “Save” icon is clicked, then “__EVENTTARGET” field will have an empty value upon PostBack, so it tells us that the PostBack is caused by the “Save” icon, not a server control. The above code can be modified as follows:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
                        Handles Me.Load
        If Not IsPostBack Then
            'Set up FCKEditor's BasePath
            Me.fckEditorNote.BasePath = Request.ApplicationPath & "/Common/fckeditor/"

            'Perform Page Load tasks, if any

        Else
            'Capture PostBack here
            Dim ctrlPostback As String = Request.Params.Get("__EVENTTARGET")
            If (ctrlPostback = "") Then
                'Save icon clicked?
                'Save data here
                Me.SaveRecords()
            End If

        End If
    End Sub

The above code works fine until you have Button control and ImageButton control on your page because when a Button (or ImageButton) control is clicked, __EVENTTARGET is not populated and the above code will still think the PostBack is coming from the “Save” icon. The reason that __EVENTTARGET is not populated is that those controls are rendered as <input type=”submit”>, which will just submit the form. So if there is any server control on the page that will be rendered as <input type=”submit”>, the above code will not work as expected.

So what are we gonna do then? What we can do is to use another hidden field to store the source of the PostBack (from client or server), then in the code behind we first check “__EVENTTARGET”, if it is empty, then we check this hidden field to see where the PostBack came from. If it came from client, then we know the PostBack was caused by the “Save” icon, otherwise, it was caused by a server control, then we can skip it to let the control’s event handler to take over the process.

Here is the hidden field:

<asp:HiddenField ID="hdnPostBackSource" runat="server" Value="Client" />

The Page_Load is modified as follows:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
                        Handles Me.Load
        If Not IsPostBack Then
            'Set up FCKEditor's BasePath
            Me.fckEditorNote.BasePath = Request.ApplicationPath & "/Common/fckeditor/"

            'Perform Page Load tasks, if any

        Else
            'Capture PostBack here
            Dim ctrlPostback As String = Request.Params.Get("__EVENTTARGET")
            If (ctrlPostback = "" AndAlso Me.hdnPostBackSource.Value = "Client") Then
                'Save icon is clicked
                'Save data here
                Me.SaveRecords() 'This is just a function to save content in FCKEditor
            End If

        End If
    End Sub

Now the question is: if a Button control is clicked, how do we change this hidden field before Page_Load gets fired. The answer is to use JavaScript to change the value of hdnPostBackSource:

<script type="text/javascript">
    function setPostBackSource()
    {
        var ctrl = document.getElementById('<%=hdnPostBackSource.ClientID() %>');
        ctrl.value="Server";
    }
</script>

And set the Button control’s OnClientClick=”setPostBackSource()”:

<asp:Button ID="btnSave" runat="server" Text="Save" OnClientClick="setPostBackSource()" />

Remember, for any server control that will not populate __EVENTTARGET field upon PostBack, you will need to add OnClientClick=”setPostBackSource()”.

Here is the complete code snippet of the code behind:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
                    Handles Me.Load
    If Not IsPostBack Then
        'Set up FCKEditor's BasePath
        Me.fckEditorNote.BasePath = Request.ApplicationPath & "/Common/fckeditor/"

        'Perform Page Load tasks, if any

    Else
        'Capture PostBack here
        Dim ctrlPostback As String = Request.Params.Get("__EVENTTARGET")
        If (ctrlPostback = "" AndAlso Me.hdnPostBackSource.Value = "Client") Then
            'Save icon is clicked
            'Save data here
            Page.Validate() 'Must call this first before Page.IsValid
            If (Page.IsValid()) Then
                Me.SaveRecords() 'This is just a function to save content in FCKEditor
            End If
        End If

        End If
End Sub

Protected Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
                    Handles btnSave.Click
    If (Page.IsValid) Then
        Me.SaveRecords()
        'Remember to reset the hidden field
        Me.hdnPostBackSource.Value = "Client"

        'Perform additional tasks if needed

    End If
End Sub

Protected Sub SaveRecords()
    Me.lblResults.Text = Me.fckEditorNote.Value
End Sub

I hope this will help someone and appreciate any comment on this post.