0

I am attempting to redirect a user to a different page when a timer elapsed. My code runs but I get this error on this line

Page.Response.Redirect(myUri, false);

my code looks like this

void dataSyncCheck_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
  Page.Response.Redirect(myUri, false);
}
codemonkeyliketab
  • 320
  • 1
  • 2
  • 17
  • A new thread is started for the Timer and the principal request thread that the `Page.Response` instance is defined on is not accessible. – Max Sorin May 12 '16 at 17:53
  • @MaxSorin how do i execute code on the original thread? – codemonkeyliketab May 12 '16 at 17:54
  • 1
    If you want to automatically redirect the browser after few seconds you need to do it in JavaScript not on the server! – Salah Akbari May 12 '16 at 17:55
  • @S.Akbari then how do i check server data to decide if i want to redirect? I want to redirect if the server data is in a certain state. – codemonkeyliketab May 12 '16 at 17:56
  • 1
    For what purpose does the timer exist? – Max Sorin May 12 '16 at 17:56
  • @MaxSorin After some seconds I want to do a check on the server data, if the check passes then I need to redirect. – codemonkeyliketab May 12 '16 at 17:56
  • Correct me if I'm wrong: Client submits a form => Server Begins to process data, and starts an async process to check for all data processing to complete => async process finds data processing is complete => redirect client to end location. – Max Sorin May 12 '16 at 17:59
  • @MaxSorin The user is not submitting a form. This is a check that is done after our end-user ticket homepage has loaded. After so many seconds I check our database for new tickets. If there are new tickets refresh the homepage. – codemonkeyliketab May 12 '16 at 18:03
  • How are you "redirecting" **after** the homepage has loaded? – Max Sorin May 12 '16 at 18:09
  • @MaxSorin like this http://stackoverflow.com/questions/2240287/refresh-page-c-sharp-asp-net – codemonkeyliketab May 12 '16 at 18:11
  • 1
    Client-side redirect would be a far better solution. You can have an XHR (aka AJAX) call at a set interval in JavaScript to the server, where the server state would be checked. The result of the call (boolean value, for instance) would then be used to redirect or not. – CoolBots May 12 '16 at 18:22
  • 1
    @CoolBots if i use the ajax way like seen here http://stackoverflow.com/a/23781882/5194952 does that mean my method has to be public static? That severely limits what I can do in that method since its a static method and I think i need it to be non-static. – codemonkeyliketab May 12 '16 at 19:26
  • @codemonkeyliketab, No, AJAX and `public static` are not required to be used together. There's no difference in process between an AJAX call and a regular web call - in fact, the server has no idea which is which. The significance of AJAX is getting server-side data into client-side without a full page refresh - that's all. The rest follows standard rules and nature of the Web. – CoolBots May 12 '16 at 19:32
  • @CoolBots so how is this done without a static method and without a full post back? I guess im a noob and I dont know how to start a client side method in this fashion. – codemonkeyliketab May 12 '16 at 19:34
  • @codemonkeyliketab, in that case you should use the built-in WebForms facilities to handle this task, as suggested and explained in my full answer. – CoolBots May 12 '16 at 19:36
  • @CoolBots problem is if the code in page_load gets called i cant do my check which is why i just want to run the specific code. – codemonkeyliketab May 12 '16 at 19:37
  • @codemonkeyliketab, You can check the `IsPostBack` property of `Page` object. I updated my answer to reflect this suggestion. – CoolBots May 12 '16 at 19:42
  • @CoolBots unfortunately i need the page state of the instance of my page class as it was pre-postback. This is why im thinking I dont want to use the .net way but the way you were describing earlier. – codemonkeyliketab May 13 '16 at 13:26
  • @codemonkeyliketab, `Page` object is destroyed once response is sent to the client; you need to save relevant info into database or otherwise persist it. – CoolBots May 13 '16 at 16:11
  • @codemonkeyliketab, I think you're misunderstanding XHR call - it's not a call within your current `Page` context, it's an entirely new web call. You wouldn't be able to access original request's `Page` state that way. – CoolBots May 13 '16 at 16:15
  • @codemonkeyliketab, I also don't understand what can you possibly need from your `Page` state that can't be preserved on postback with a `if(IsPostBack)` checks. – CoolBots May 13 '16 at 16:18
  • @CoolBots instance variables for instance. you said i cant access the original page state which is what i need since i want to compare an instance variable before and after. x and y hold the original data, then i postback, x will continue having the original data y will update to the latest on the server and i compare x and y. – codemonkeyliketab May 13 '16 at 16:26
  • @codemonkeyliketab, Save the variable to database or `Session["VarName"]`. – CoolBots May 13 '16 at 17:01

2 Answers2

0
            var tasks = new Task[2]
            {
                Task.Factory.StartNew(() => {
                   //Process Data
                }),

                Task.Factory.StartNew(() => {
                    //Sleep while not sync.
                })
            };

            Task.WaitAll(tasks);

Page.Response does not exist after the client has finished loading the page. Therefore cannot be used to redirect after the fact.

You can do the above and force the page load to wait for the "sync check" to complete before returning a response to the client, or you can use a client side ajax request to request a status update from the server after the page is loaded essentially moving the timer from your server to the client.

Max Sorin
  • 1,042
  • 6
  • 14
  • This code has the same problem as mine. I have no where I can put the WaitAll(tasks) such that after I wait I can redirect the page to myUri without a response is not available error. – codemonkeyliketab May 12 '16 at 18:15
0

I think the direct answer to your question is it can't be done server-side once the initial page is loaded - that is, response is sent to the client, and server-side code is out of the picture, until the next request. Such is the nature of the web.

My recommendation is to move this functionality client-side. You'll need an XmlHttpRequest (XHR, aka AJAX) call to the server (think API call, just to your own server) to determine whether or not a redirect is necessary based on your specific rules/logic. The response to such XHR call can be as simple as a boolean, or can include the URL of the redirect.

If you want to take advantage of built-in WebForms facilities to handle a client-side redirection, you can use Web.UI.Timer instead, along with a ScriptManager control:

In ASPX code:

<asp:ScriptManager ID="scriptManager" runat="server"></asp:ScriptManager>
<asp:Timer runat="server" ID="redirectTimer" Interval="5000" OnTick="redirectTimer_Tick" Enabled="true" />

In code-behind:

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            //Handle initial page load
        }
    }

    protected void redirectTimer_Tick(object sender, EventArgs e)
    {
        if(someConditionIsSatisfied)
        {
            Response.Redirect(myUri, false);
        }
    }

Keep in mind, the Timer.Tick event in the above code will cause a full post-back - that is, your page will fully re-load. You can use other mechanisms, such as an update panel, to "hide" the reload from the client, but any code in your Page_Load() event handler will run on every timer tick; just be aware of that. You can ensure your Page_Load() code executes only once by checking the Page.IsPostBack property.

Bottom line, you're trying to accomplish your task in the wrong context - this is a job for the client, not the server, to handle.

CoolBots
  • 4,770
  • 2
  • 16
  • 30
  • I think you and I are saying the same thing, aren't we? – Max Sorin May 12 '16 at 18:37
  • @Max Sorin, as far as client-side redirect for handling the job, yes. I don't fully follow your suggestion with the Task though - wouldn't you have to delay response to the client (meaning, lag the response until the desired state is reached) for that to work? – CoolBots May 12 '16 at 18:47
  • Yes, that was the idea... I mean that was what he was trying to achieve as far as I can understand. – Max Sorin May 12 '16 at 18:50
  • I think the OP is trying to use the timer to check for a certain condition server-side *while the user is viewing the page* and redirect, without further action from the user, based on such condition. To that end, it is not possible to achieve server-side. – CoolBots May 12 '16 at 18:52