views:

61

answers:

3

Hi Guys,

My page has a submit button on it (server-side button).

Here's my code for the click event:

protected void SubmitButton_Click(object sender, EventArgs e)
{
    db.SaveSomething();
    Page.ClientScript.RegisterStartupScript("someScriptWhichReliesOnServerData");
    Response.Redirect("SomeOtherPage.aspx");
}

Now, the problem is, i register the JavaScript using Page.ClientScript.RegisterStartupScript, but this will have no effect as the page is not being re-rendered on postback (which is where the script WOULD be executed), because instead a Response.Redirect happens.

The only solution i can think is to make the page i redirect to "aware" that im trying to execute some JavaScript, be it QueryString, HttpContext.Current.Items, or (gulp) Session.

  • QueryString - not an option, as it's JavaScript im trying to execute.
  • HttpContext.Current.Items - also not an option because im doing a Response.Redirect (which loses the request-level data, and i also cannot use Server.Transfer because this doesn't play nice with URL Rewriting).
  • Session - of course, but not ideal.

Any other ideas/suggestions?

EDIT for Clarification:

The JavaScript im executing is a call to a Facebook client-side API to publish to the user's wall. It has to be done client-side. I pass to the script things like "title", "message", "action links", etc. Basically a bunch of JSON. But the key here is that this data is created on postback, so i cant just execute this function on client-side click.

So what im trying to accomplish is on submit button click, execute some javascript and do a redirect (does not have to be in that order, just both need to happen).

A: 

If you use Response.Redirect, the java script you registered at the previous line will not executed. I think what you want to do after clicking the submit button is:

  1. Save something
  2. Execute javascript
  3. Redirect to another page

Here you can use:

protected void SubmitButton_Click(object sender, EventArgs e)
{
    db.SaveSomething();
    Page.ClientScript.RegisterStartupScript("someScriptWhichReliesOnServerData");
    Page.ClientScript.RegisterStartupScript("window.location.href=XXXXXX");
}

That is, using javascript to redirect the page instead of Response.Redirect.

Danny Chen
I thought of that, but that would re-render the page, then do a redirect after the page has loaded. Not good UX IMO
RPM1984
When you click the submit button, of course it will refresh the page. So you want no refreshing?
Danny Chen
@Danny - you're not understanding. On Submit button click of the first page, this posts back to the server, which then does a Response.Redirect - so the SECOND page is rendered. So it doesnt refresh the same page (which would happen by default, if i did not a Response.Redirect), it renders the second page. Know what i mean?
RPM1984
so you want the javascript to be executed in the second page, not the first one? You are finding a way to TELL the second page to execute the js?
Danny Chen
@Danny - thats right. I just need to execute some javascript on postback of Page1 and redirect to Page2. As my question states, i cannot register the script on postback of Page1, as the Response.Redirect will ignore that. Therefore i have to somehow execute it on Page2. The question is how to give Page2 enough info to do this.
RPM1984
A: 

Could you run the JavaScript on the second page?

Other than that, your options are somewhat limited. You could use AJAX to get the data you need from the server and then redirect. That would improve the UX since at the very least you wouldn't have extra page loads to run your intermediary JavaScript.


Another option would be to use Server.Transfer(...), which works similarly to Response.Redirect, but it doesn't send a redirect header to the client. It simply tells the server "stop running the current page and start executing a new page". Context.Items will remain in scope between the 2 classes because you're only transferring the responsibility of responding to the request, not the entire context of the request.


You could also combine these 2 solutions. Use Server.Transfer to keep Context.Items values in scope and then render the JS on the second page using whatever values you kept from the first page.

Dan Herbert
@Dan thanks. I've tried Server.Transfer and HttpCOntext.Current.items (as my question stated), but i ran into problems with URL rewriting (Server.Transfer wouldnt work with "~/somecleanurl", it had to be "~/pages/somepage.aspx". But i didnt think of AJAX, might give that a go.
RPM1984
+3  A: 

I think what you are experiencing is the unfortunate clashing of two different paradigms here. On the one side you have an AJAX style API you want to take advantage of, and on the other side you have the ASP.Net page postback model.

Now, while these two are not mutually exclusive, it can present some challenges. I agree with Dan that your best bet is to bend a little more towards the AJAX approach instead of the other way around.

A nice feature in ASP.Net is the ability to turn a single static method in your page into a pseudo web service. You can then use the ScriptManager to generate client-side proxy classes to call that method for you, but you can use whatever client side library you want.

A very simple example:

In your codebehind for you Page

[WebMethod]
public static Person GetPerson(Int32 id, String lastName)
{
    return DataAccess.GetPerson(id, lastName);
}

If you were using the ASP.Net AJAX library to handle this for you, then you would need to enable page methods to generate the client-side proxies.

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
</asp:ScriptManager>

Then you could call that from client-side script like so:

function CallGetPerson() 
{
     var id = $get("txtPersonId").value;
     var lastName = $get("txtLastName").value;
     // PageMethods is a class that is part of the ASP.Net AJAX
     // client-side libraries and will contain your auto-generated
     // proxy methods for making XHR requests.
     PageMethods.GetPerson(id, lastName, OnGetPersonComplete);
}

function OnGetPersonComplete(result)
{
    faceBookApi.DoSomeStuffWithJson(result);
    window.location = "NewPage.aspx";
}

Now again, this is a contrived example, and what you are posting to the server may be very complicated, but you get the general idea of what can be accomplished using the built in framework components.

I hope this helps.

Josh
+1 nice answer!
Danny Chen
@Josh, thanks. Yeah i know how to use ajax page methods, but the problem is, the form is quite complicated (a lot of fields, a lot of other logic). I would have to encapsulate all of this logic in the web method - not ideal. What im leaning towards at the moment is wrapping the form in an UpdatePanel, and doing it that way (old school ajax, vs the proper way, which is what you've stated). That being said, this is a nice answer (which the upvotes show), so ill give the answer to you.
RPM1984
I feared that the form was perhaps too complicated for this, but perhaps that is good motivation to do some refactoring. Using partial page postbacks is a low friction way of doing this, but be advised you will need to use ScriptManager.RegisterStartupScript as Page.ClientScript will not work during a partial postback since only the update panel contents get refreshed.
Josh