I have a website that is running under ASP.Net. It has a number of ascx controls that each represent a different page. The master page would call LoadControl() on the ascx and then add it to a panel. The ascx Page_Load() would then hook up a personal save function to an event on the page so that the "Save" button on the master page would do the right thing. This is all working.
I am now trying to be more dynamic and use jQuery more and do things more on the client side. To that end, I am experimenting with loading the ascx controls dynamically. The goal is to be able to do this with minimal changes to each ascx. I have a page, with the following contents (edited for brevity):
<head>
<script language="javascript" type="text/javascript">
function documentMetadataLoad()
{
jQuery.ajax({
type: "GET", //GET
url: "JQueryHandler.ashx?Operation=LoadPage&Name=/UserControls/DocumentManagment/DocumentMetadata.ascx",
dataType: "html",
cache: false,
success: function (response)
{
$('#property_tab').html(response);
},
error: function ()
{
debugger;
$('#property_tab').html('error');
}
});
</script>
</head>
<body id="mainBody" class="bodyClass">
<form id="form1" runat="server">
<div id="btn_save">
<a href="#" id="btnSave" class="topBtnText">Save</a>
</div>
<div>
<div id="tab1" onclick="documentMetadataLoad(); ">Properties</div>
</div>
<div id="property_tab" style="display: Block;"></div>
</form>
</body>
This page will dynamically load a control called DocumentMetadata.ascx when the user clicks on a tab. (Yes, I am aware that there is probably a gaping security hole when the client passes the path of the control, but this is a proof-of-concept.)
The JQueryHandler will take the given path and generate a page. Its ProcessRequest() looks like this:
public void ProcessRequest(HttpContext context)
{
if (context.Request.QueryString["Operation"] == "LoadPage")
{
String strPath = context.Request.QueryString["Name"];
using (TisPage MyPage = new TisPage())
{
HtmlForm f = new HtmlForm();
f.Action = context.Request.UrlReferrer.AbsolutePath;
UserControl userctrl = MyPage.LoadControl(strPath) as UserControl;
f.Controls.Add(userctrl);
MyPage.Controls.Add(f);
context.Server.Execute(MyPage, context.Response.Output, true);
}
}
}
(Thank you to http://www.infoconcepts.com/rendering-ascx-files-ajax/ for indicating a HtmlForm should wrap the control.) TisPage is a subclass of System.Web.UI.Page, with an added event for saving data, which the ascx expects.
Now, the problem I am having is that I want the DocumentMetadata.ascx to have its save function called when the user presses the #btnSave. This is code behind, and it expects to have its viewstate retained. So I assume I will have to have a postback. I would prefer not to have to rewrite the C# save function to be its own ashx call with passed in parameters; there are a lot of pages like this and it would not be worth the trouble to rewrite them all.
I have the following code in the DocumentMetadata.ascx to setup the button press to do something.
$(document).ready(function ()
{
$("#btnSave").bind("click", Save);
});
function Save()
{
debugger;
__doPostBack('ctl00', null);
}
I experimented by having a call to __doPostBack() in the Javascript, but I then get the error: "Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster." As an experiment, I tried to remove my machine key configuration from my web.config, but that did not seem to help.
Is there a way to use JavaScript to call the code behind of an ascx control that was loaded with jQuery?