Modal RadWindow not closing in Chrome - c#

I have a main "Report" page that has some actions the user can take that will open a modal RadWindow, let the user take actions, then click Save and the modal window will close and the main grid refreshes.
This works fine in both IE and Firefox, but Chrome does all the "work" but the modal page stays open. This is only true if I hit the Save button; the Cancel button and the close button on the top of the form still work correctly.
This is the JavaScript from the child window:
<script type="text/javascript">
function GetRadWindow() {
var oWindow = null;
if (window.radWindow)
oWindow = window.radWindow;
else if (window.frameElement.radWindow)
oWindow = window.frameElement.radWindow;
return oWindow;
}
function CloseRadWindow() {
var oWnd = GetRadWindow()
oWnd.SetUrl("");
oWnd.close();
}
function CloseAndRebind(args) {
var oWnd = GetRadWindow()
oWnd.BrowserWindow.refreshGrid(args);
oWnd.SetUrl("");
oWnd.close();
}
</script>
This is the parent's refreshgrid function:
<script type="text/javascript">
function refreshGrid(arg) {
if (!arg) {
$find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>").ajaxRequest("Rebind");
}
else {
$find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>").ajaxRequest("RebindAndNavigate");
}
}
</script>
The parent loads the modal window by running:
protected void btnSplitInvoice_Click(object sender, EventArgs e)
{
var btn = sender as Button;
var item = (GridDataItem)btn.Parent.Parent;
long id = long.Parse(item["Id"].Text);
var itemType = this.TabStrip1.SelectedIndex == 0 ? "TransferOrderInvoice" : "EquipmentInvoice";
string scriptstring = "var oWindow=radopen('../Misc/SplitInvoice.aspx?id=" + id + "&type=" + itemType + "','SplitInvoice');oWindow.SetModal(true);";
ScriptManager.RegisterStartupScript(this, this.GetType(), "openwindow", scriptstring, true);
}
The child's save button has a lot of work done in the code behind and then finishes with this:
ScriptManager.RegisterClientScriptBlock(this.Page, this.GetType(), "mykey", "CloseAndRebind('navigateToInserted');", true);
The cancel button is set up as this:
<button type="button" class="CancelBtn" value="" onclick="CloseRadWindow()">
</button>
I found one entry from awhile back that suggested adding window.open('', '_self', ''); to the close, but that didn't seem applicable (and also didn't work when I tested it for the heck of it).
EDIT: When running Chrome with the Console open, I do see that I'm getting an error on the main page when refreshgrid is running:
Cannot call method 'ajaxRequest' of null
But not sure if that's what's causing the problem or not. Looking into it more now.
EDIT2: So the issue does seem to be that when using Chrome, the RadAjaxManager from the Master page does not seem to be found by the time refreshGrid runs, which is the reason for the null error above. I was able to "fix" the problem by replacing the guts of the refreshGrid function with document.location.reload(); and it does fine. I'd rather not reload the whole page if I can help it, though, so wondering if there's a way to fix this, still. And I'm curious why IE and Firefox seem to handle this when Chrome doesn't?
More information that may be useful: The main page's Page_Load event:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
this.Session["AllUserLocationValue"] = string.Empty;
this.InitializeThePage();
}
RadAjaxManager manager = RadAjaxManager.GetCurrent(this.Page);
manager.AjaxRequest += this.manager_AjaxRequest;
manager.AjaxSettings.AddAjaxSetting(manager, this.pnlHeading, this.RadAjaxLoadingPanel1);
manager.AjaxSettings.AddAjaxSetting(manager, this.RadCodeBlock1, this.RadAjaxLoadingPanel1);
}

Remove the call to SetUrl("") because it starts disposing the current page and if the browser is fast enough it will not get to the call to close().
if you need to navigate the RadWindow away you can use one of these three options
set its ReloadOnShow property to true. Usually together with ShowContentDuringLoad=false
set DestroyOnClose to true. Use with caution and add a timeout before close()
use the OnClientClose event to set the url to a blank page

OK, I found that Chrome does consistently "lose" the report page's master page reference, or at least the RadAjaxManager there while Firefox and IE do not (I can trace through and watch $find work for both of them).
What I did find, however, is that Chrome (and the other two) can consistently find the main grid of the report (which is what refreshGrid was ultimately looking for). So I was able to replace the guts of refreshGrid with:
function refreshGrid(arg) {
var radgridNotApproved = $find("<%= rgNotApproved.ClientID %>").get_masterTableView();
radgridNotApproved.rebind();
}
and get the behavior I was looking for. It's cleaner as well; the original version of refreshGrid looks like it might have originally been intended to do more than just rebind the grid, but by the time I was looking at it, that's all it was really doing.

Related

ASP.NET How to open a second popup on close() event of first

I want to open a popup window with some parameters inside and then open a new one (or even more than one) with different parameters, after the user closes the first.
It should be like a foreach loop where it waits for the closing event before opening a new window.
I'm using .NET Framework v3.5.
foreach (object o in ObjectsList)
{
// Do some stuff...
// Set query string for popup
string queryString = string.Format("Page.aspx?doc={0}, o.ID);
string urlDownload = Page.ResolveClientUrl(string.Format("~/Path/To/Folder/{0}", queryString));
string script = string.Format("loadDownload('{0}','_blank',600,600);", urlDownload);
// Open popup window
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "DocID" + o.ID, script, true);
// Wait for popup close event before proceeding...
}
These links might be of good use to you.
http://aspdotnetcodebook.blogspot.com.au/2009/03/how-to-open-modalpopup-inside.html
http://www.codeproject.com/Articles/546817/ASP-NET-Popup-Control-Displaying-as-multiple-neste
I would have registered to the Closed/disposed event and handle all there, that means
ObjectsList
will be an instance of your class, where you have an indexer, let say i which tells you in which you are:
int i
void frm_disposed(object sender, EventArgs e)
{
showFrm(ObjectsList[++i];
}

Page_Load fires infinity times

I have problem with my iframe asp.net page.
Browser url containst parameter which I need to use in my iframe page.
Obviously I can't get access via .NET so I came up with the idea that at the end of the Page_Load method add sth like that :
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bool isReloaded = Request.QueryString.GetValue<bool>("reloaded");
ContentId = Request.QueryString.GetValue<int>("contentId"); //I need this value
if (!isReloaded)
{
StringBuilder js = new StringBuilder("<script language='javascript'>");
js.Append("var last = window.top.location.href.substring(window.top.location.href.lastIndexOf('/') + 1, window.top.location.href.length); ");
js.Append("window.location.href = window.location.href + '?reloaded=true&contentId=' + last;");
js.Append("if(window.location.href.indexOf('reloaded=true') == -1) window.location.reload();");
js.Append("<" + "/script>");
Response.Write(js.ToString());
}
}
}
In shortcut I use Javascript to get value I need and fire reload() but with changed QueryString.
Page_Load is firing again and now I have bool isReloaded filled with true.
The condition (!isReloaded) blocks that this time javascript will not be added to Response.
I don't know why, but Page_Load fires again, this time without added parameters so it's the same situation as at the beginning and again is adding JS etc.
Result is that Page_load fires endlessly.
What did I do wrong ? What is the reason ?
if you have a look at your code, you have this line:
js.Append("if(window.location.href.indexOf('reloaded=true') == -1) window.location.reload();");
you are checking the location.href for the 'reloaded' var, but note that your page is reloaded as soon as you change the location, and your script keeps executing before it is done, so it results in reloading of the page over an over again without the query string.
remove this line and it should work fine.
another thing though, i changed your code a little bit to register the script on page instead of response.write it,
it shouldnt make any difference, but if your code still doesnt work then try my version:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bool isReloaded;
int ContentId;
bool.TryParse(Request.QueryString["reloaded"],out isReloaded);
int.TryParse(Request.QueryString["contentId"],out ContentId); //I need this value
if (!isReloaded)
{
StringBuilder js = new StringBuilder();
js.Append("var last = window.top.location.href.substring(window.top.location.href.lastIndexOf('/') + 1, window.top.location.href.length); ");
js.Append("window.location.href = window.location.href + '?reloaded=true&contentId=' + last;");
ExecScript(js.ToString());
}
}
}
void ExecScript(string script)
{
Page page = HttpContext.Current.CurrentHandler as Page;
if (page != null && !page.ClientScript.IsClientScriptBlockRegistered("AttachedScript"))
{
page.ClientScript.RegisterClientScriptBlock(page.GetType(), "AttachedScript", script, true);
}
}
Thanks for help.
Now I have sth like that and it's ok.
StringBuilder js = new StringBuilder("<script language='javascript'>");
js.Append("var last = window.top.location.href.substring(window.top.location.href.lastIndexOf('/') + 1, window.top.location.href.length); ");
js.Append("if(window.location.href.indexOf('reloaded=true') == -1) window.location.href = window.location.href + '?reloaded=true&contentId=' + last;");
js.Append("<" + "/script>");
I didn't know that editing location executes reload automatically ;)
Thanks again

How to detect page refresh in .net

I have a Button_click event. While refreshing the page the previous Postback event is triggering again. How do I identify the page refresh event to prevent the Postback action?
I tried the below code to solve it. Actually, I am adding a visual webpart in a SharePoint page. Adding webpart is a post back event so !postback is always false each time I'm adding the webpart to page, and I'm getting an error at the else loop because the object reference is null.
if (!IsPostBack){
ViewState["postids"] = System.Guid.NewGuid().ToString();
Cache["postid"] = ViewState["postids"].ToString();
}
else{
if (ViewState["postids"].ToString() != Cache["postid"].ToString()){
IsPageRefresh = true;
}
Cache["postid"] = System.Guid.NewGuid().ToString();
ViewState["postids"] = Cache["postid"].ToString();
}
How do I solve this problem?
using the viewstate worked a lot better for me as detailed here. Basically:
bool IsPageRefresh = false;
//this section of code checks if the page postback is due to genuine submit by user or by pressing "refresh"
if (!IsPostBack)
{
ViewState["ViewStateId"] = System.Guid.NewGuid().ToString();
Session["SessionId"] = ViewState["ViewStateId"].ToString();
}
else
{
if (ViewState["ViewStateId"].ToString() != Session["SessionId"].ToString())
{
IsPageRefresh = true;
}
Session["SessionId"] = System.Guid.NewGuid().ToString();
ViewState["ViewStateId"] = Session["SessionId"].ToString();
}
This article could be of help to you
http://www.codeproject.com/Articles/68371/Detecting-Refresh-or-Postback-in-ASP-NET
you are adding a Guid to your view state to uniquely identify each page. This mechanism works fine when you are in the Page class itself. If you need to identify requests before you reach the page handler, you need to use a different mechanism (since view state is not yet restored).
The Page.LoadComplete event is a reasonable place to check if a Guid is associated with the page, and if not, create one.
check this
http://shawpnendu.blogspot.in/2009/12/how-to-detect-page-refresh-using-aspnet.html
This worked fine for me..
bool isPageRefreshed = false;
protected void Page_Load(object sender, EventArgs args)
{
if (!IsPostBack)
{
ViewState["ViewStateId"] = System.Guid.NewGuid().ToString();
Session["SessionId"] = ViewState["ViewStateId"].ToString();
}
else
{
if (ViewState["ViewStateId"].ToString() != Session["SessionId"].ToString())
{
isPageRefreshed = true;
}
Session["SessionId"] = System.Guid.NewGuid().ToString();
ViewState["ViewStateId"] = Session["SessionId"].ToString();
}
}
Simple Solution
Thought I'd post this simple 3 line solution in case it helps someone. On post the session and viewstate IsPageRefresh values will be equal, but they become out of sync on a page refresh. And that triggers a redirect which resets the page. You'll need to modify the redirect slightly if you want to keep query string parameters.
protected void Page_Load(object sender, EventArgs e)
{
var id = "IsPageRefresh";
if (IsPostBack && (Guid)ViewState[id] != (Guid)Session[id]) Response.Redirect(HttpContext.Current.Request.Url.AbsolutePath);
Session[id] = ViewState[id] = Guid.NewGuid();
// do something
}
If you want to detect a refresh on an HTTP GET rather than only POSTs, here's a hacky work-around that, in modern browsers, mostly works.
Javascript:
window.onload = function () {
// regex for finding "loaded" query string parameter
var qsRegex = /^(\?|.+&)loaded=\d/ig;
if (!qsRegex.test(location.search)) {
var loc = window.location.href + (window.location.search.length ? '&' : '?') + 'loaded=1';
window.history.replaceState(null, document.title, loc);
}
};
C#:
public bool IsPageRefresh
{
get
{
return !string.IsNullOrEmpty(Request.QueryString["loaded"]);
}
}
When the page loads, it will change add a QueryString parameter of loaded=1 without reloading the page (again, this--window.history.replaceState--only works in post-archaic browsers). Then, when the user refreshes the page, the server can check for the presence of the loaded parameter of the query string.
Caveat: mostly works
The case where this doesn't work is when the user clicks the Address Bar and presses enter. That is, the server will produce a false-positive, detecting a refresh, when odds are, the user actually meant to reload the page fresh.
Depending on your purposes, maybe this is desirable, but as a user, it would drive me crazy if I expected it to reset the page.
I haven't put too much thought into it, but it might be possible to write some magic in order to distinguish a refresh from a reset via the address bar using any/all of:
SessionState (assuming SessionState is enabled) and the value of the loaded QueryString parameter
the window.onbeforeunload event listener
keyboard events (detecting F5 and Ctrl + R to quickly change the URL back to removing the loaded QueryString parameter--though this would have a false-negative for clicking the browser's refresh button)
cookies
If someone does come up with a solution, I'd love to hear it.
Another way to check page refresh. I have written custom code without java script or any client side.
Not sure, it's the best way but I feel good work around.
protected void Page_Load(object sender, EventArgs e)
{
if ((Boolean)Session["CheckRefresh"] is true)
{
Session["CheckRefresh"] = null;
Response.Write("Page was refreshed");
}
else
{ }
}
protected void Page_PreInit(object sender, EventArgs e)
{
Session["CheckRefresh"] = Session["CheckRefresh"] is null ? false : true;
}

.net 4.0 webpage button click event firing twice

I have a 4.0 webpage with a button click that runs a server side process that takes about 5-10 seconds to run. I thought I’d be smart and search for some code that made the button hide and showed an animated gif image while the process was running. I got this working but started to notice “file being used by another process” errors being thrown server side (part of the process is deleting a directory). I debugged through and started to see what appeared to be a second button event click being fired at the same time. Turns out that the piece of Js code I added to refresh the page to allow the animated gif to run seems to be firing the server click event a second time. I had to call the Js SetTimeOut() method to get the gif image running, it's this that is appearing to cause the problem.
I did a bit of searching to try to find a different approach to getting the animated gif to run, but couldn’t find one, so I went for the ambulance at the bottom of the cliff approach and decided to add a server side timestamp into session and only proceed with my code if it is more than 20 seconds since session was last set.
I’ve had some very erratic results with this approach and any input would be appreciated.
Is there a better way I can get the gif running?
Has anyone else come across this issue of the event firing twice?
Why should my lock not work first time through?
Any suggestion of a better approach to do this is appreciated, Thanks!
Logging results:
First time through (no session existing)
2011-06-21 11:46:14.8968|DEBUG|FileViewer.copyfiles|Count = 1 & Locked = False
2011-06-21 11:46:14.8968|DEBUG|FileViewer.copyfiles|Count = 2 & Locked = True
2011-06-21 11:46:19.0619|DEBUG|FileViewer.copyfiles|Count = 1 & Locked = False
2011-06-21 11:46:19.0619|DEBUG|FileViewer.copyfiles|Count = 2 & Locked = True
2011-06-21 11:46:23.1959|DEBUG|FileViewer.copyfiles|Count = 3 & Locked = True
2011-06-21 11:46:28.8119|DEBUG|FileViewer.copyfiles|Count = 3 & Locked = True
Run again:
2011-06-21 11:49:47.7798|DEBUG|FileViewer.copyfiles|Count = 1 & Locked = False
2011-06-21 11:49:47.7798|DEBUG|FileViewer.copyfiles|Count = 2 & Locked = True
2011-06-21 11:49:55.9697|DEBUG|FileViewer.copyfiles|Count = 3 & Locked = True
2011-06-21 11:49:59.8697|DEBUG|FileViewer.copyfiles|Count = 1 & Locked = True
2011-06-21 11:49:59.8697|DEBUG|FileViewer.copyfiles|Count = 3 & Locked = True
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
PostBackOptions optionsSubmit = new PostBackOptions(btnGo);
btnGo.OnClientClick = "HideControlOnClick(this);";
btnGo.OnClientClick += ClientScript.GetPostBackEventReference(optionsSubmit);
}
}
protected void btnGo_Click(object sender, EventArgs e)
{
bool locked = true;
if (Session["ClickTime"] == null || (DateTime)Session["ClickTime"] < DateTime.Now.AddSeconds(-20))
{
Session["ClickTime"] = DateTime.Now;
locked = false;
}
WriteToLog(1, locked);
if (Page.IsValid && !locked)
{
locked = true;
WriteToLog(2, locked);
// Do all my processing
}
WriteToLog(3, locked);
}
<script language="javascript" type="text/javascript">
function HideControlOnClick(btnGo)
{
// IE uses className for the css property.
btnGo.setAttribute('className', 'hide');
document.getElementById('MainContent_imgWait').setAttribute('className', 'show');
setTimeout("UpdateImg('MainContent_imgWait','Images/loading.gif');",50);
}
function UpdateImg(ctrl, imgsrc)
{
var img = document.getElementById(ctrl);
img.src = imgsrc;
}
</script>
I think its better use some web debugger tools to track the request. I suggest use the Fiddler
I suspect that issue here is probably nothing to do with animated gif but button being pressed twice (i.e. two clicks getting registered instead one). You can try disabling the button to supress the second click (yet another way is to have flag at button level) - for example,
btnGo.OnClientClick = "return HideControlOnClick(this);";
function HideControlOnClick(btnGo)
{
if (btnGo["My_Is_Clicked"]) {
// already clicked, ignore
return false;
}
btnGo["My_Is_Clicked"] = true;
...
return true;
}
I've solved the issue by dropping all of the relevant controls into an update pannel, this seems to allow the animated gif to run without calling the setTimeout("UpdateImg('MainContent_imgWait','Images/loading.gif');",50); JS method. Working fine now with the server event only firing once.
The issue is most likely that you're using a server side button control (since you're referencing it server side), and those fire a postback when they're clicked typically (hard to say without knowing the exact object you're using). Use an HTML input to fire your client side event, do your work, and then perform the postback from your JS code (with an appropriate ID to catch on the server side).
Something like this server side:
/// <summary>
/// Page init event, setup the core of the page.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected override void Page_Init(object sender, EventArgs e)
{
try
{
// See if we're in a postback.
if (IsPostBack)
{
// If we have a target...
if (Request.Params["__EVENTTARGET"] != null)
{
// See what the target is.
switch (Request.Params["__EVENTTARGET"])
{
case "btnGo":
// Maybe make this a parameterless method rather than an event handler to avoid parameters that you don't need.
btnGo_Click(null, null);
break;
}
}
}
}
}
And client side:
function Go() {
// Show loading...
// Call server.
__doPostBack("btnGo", "My Args");
}
EDIT: As an alternative I think you can also add "return false;" after the client side event, such as:
btnGo.OnClientClick = "HideControlOnClick(this); return false;";
and that should stop the postback as well.

Callback function?

I need to callback Javascript function in my code, but not firing. I am providing details what I am doing?.
I have input button in the page that calling javascript function. There I am loading another ProfilePic.aspx page. ProfilePic.aspx has FileUpload, OK and cancle button
<input type=button value="Change Image" onclick="javascript:SelectUserImage()" />
Javascript functions are
<script type="text/javascript">
function SelectUserImageCallback(ret) {
var imgId = 'ctl00_PlaceHolderMain_prof_imgUser';
var clearId = 'ctl00_PlaceHolderMain_prof_hidImageURL';
if (ret) {
if (ret == '__RESET__') {
document.getElementById(imgId).src = '\u002f_layouts\u002fimages\u002fno_pic.gif';
document.getElementById('ctl00_PlaceHolderMain_prof_hidImageURL').value = '';
document.getElementById(clearId).style.display = 'none';
}
else {
document.getElementById(imgId).onload = 'imgResizeMax(\'ctl00_PlaceHolderMain_prof_imgUser\', 100);imgResizeTbl(\'ctl00_PlaceHolderMain_prof_imgUser\');';
document.getElementById(imgId).src = ret;
document.getElementById('ctl00_PlaceHolderMain_prof_hidImageURL').value = ret;
setTimeout('imgResizeMax(\'ctl00_PlaceHolderMain_prof_imgUser\', 100);imgResizeTbl(\'ctl00_PlaceHolderMain_prof_imgUser\');', 1);
setTimeout('imgResizeMax(\'ctl00_PlaceHolderMain_prof_imgUser\', 100);imgResizeTbl(\'ctl00_PlaceHolderMain_prof_imgUser\');', 100);
document.getElementById(clearId).style.display = '';
}
}
}
function SelectUserImage() {
var href = '\u002f_layouts\u002fProfilePic.aspx';
var features = 'resizable: yes; status: no; scroll: no; help: no; center: yes; dialogWidth: 460px; dialogHeight: 140px; width:460;height:240;menubar:no;directories:no;location:no;';
commonShowModalDialog(href, features, SelectUserImageCallback, null);
}
In the ProfilePic.aspx page once user click OK buttong. I am upload his pic with some logic then I am closing window with javascript
protected void btnOK_Click(Object sender, EventArgs e)
{
try
{
// My logic Here
Debug.WriteLine("Shared Pictures Save Ends: " + DateTime.Now);
Response.Write ("<script language =javascript>close();</script>");
Response.End();
}
catch (Exception exception)
{
LogMessage(exception.Message, EventLogEntryType.Error);
if (exception.Message.ToLower().Contains("blocked"))
errorDisplay.Text = "* This type of file has been blocked by the administrator, please try a different file.";
else
{
errorDisplay.Text = exception.Message;
}
}
}
My Question: I am able to close the window but, What ever I need to call callback function `SelectUserImageCallback' not firing. I need to call this method after OK button part execution done.
Are you closing the window before the callback executes? I've done that before. As an experiment, try commenting out the code that closes the window.
You may have to restructure your code so that the callback function closes the window when it's finished whatever it's doing.
Update: Sorry, I misunderstood the question. There was a lot of code and I didn't read it all. I thought the call back was in the dialog page, but it looks like it's in the main page. I'm not familiar with commonShowModalDialog(), but it looks like it may have something to do with SharePoint. Do you have any documentation on that method? I found this discussion that makes it look like there's a special way to return a value from the dialog box. It may be that your callback isn't being called because you're not closing the window the right way. (That's a total guess on my part.)
Good luck.

Categories