The solution that I've implemented (very recently) to overcome the problem is a little complicated, but let me try to explain:
Essentially - On the page with the iFrame, you're going to track (in Session) the save event and expose the results through a WebMethod that the CRM page will call (using the jquery .ajax() functionality)
Best way to explain is with sample code (Just create a new Website Project with Default.aspx & IFramePage.aspx):
IFramePage.aspx ->
<script type="text/javascript">
SaveStuff = function() {
__doPostBack('SaveButton', '');
}
</script>
Hello - I am an iFrame!<br />
<asp:linkbutton id="SaveButton" runat="server" style="display:none;" onclick="SaveButton_Click" text="Save" />
<asp:hiddenfield id="RandomGuidHiddenField" runat="server" />
</div>
IFramePage.aspx.cs ->
public static object locker = new object();
/// <summary>
/// Gets the statuses.
/// </summary>
/// <value>The statuses.</value>
public static Dictionary<Guid, bool> Statuses
{
get
{
lock (locker)
{
if (HttpContext.Current.Session["RandomGuid"] == null)
{
HttpContext.Current.Session["RandomGuid"] = new Dictionary<Guid, bool>();
}
return (Dictionary<Guid, bool>) HttpContext.Current.Session["RandomGuid"];
}
}
}
[WebMethod]
public static bool CheckSaveComplete(string randomGuid)
{
var currentGuid = new Guid(randomGuid);
var originalTime = DateTime.Now;
if (!Statuses.ContainsKey(currentGuid))
{
Statuses.Add(currentGuid, false);
}
while (!Statuses[currentGuid])
{
if (DateTime.Now.Subtract(originalTime) > new TimeSpan(0, 0, 0, 1))
{
return false;
}
Thread.Sleep(1000);
}
return true;
}
/// <summary>
/// Handles the Load event of the Page control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.RandomGuidHiddenField.Value = Guid.NewGuid().ToString();
}
}
/// <summary>
/// Handles the Click event of the SaveButton control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void SaveButton_Click(object sender, EventArgs e)
{
var randomGuid = new Guid(this.RandomGuidHiddenField.Value);
if (!Statuses.ContainsKey(randomGuid))
{
Statuses.Add(randomGuid, false);
}
Thread.Sleep(10000);
Statuses[randomGuid] = true;
}
In my Default.aspx page (to simulate the CRM Form Entity page) ->
<script type="text/javascript">
function OnSave() {
var saveResult = false;
var randomGuid = window.frames[$("#daIframe")[0].id].$("input[id$=RandomGuidHiddenField]").val();
window.frames[$("#daIframe")[0].id].SaveStuff();
$.ajax(
{
async: false,
type: "POST",
url: "IFramePage.aspx/CheckSaveComplete",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: '{"randomGuid" : "' + randomGuid + '"}',
success: function(response) {
if (response.d === true) {
alert(response.d);
saveResult = true;
}
}
}
);
if (saveResult !== true) {
alert("Oh No!");
}
else {
alert("way to go!");
}
}
</script>
<iframe name="daIframe" id="daIframe" src="IFramePage.aspx"></iframe>
<asp:textbox id="lsc_paymentinfo" runat="server" text="1000" /><br />
<input type="button" value="Save" onclick="OnSave();" />
Let me know if you have any questions!