0

I have tried the following typical approaches but couldn't able to do a redirect from an asynchronous ASP.NET method:

Response.Redirect("~/Login.aspx");

HttpContext.Current.Response.Redirect("~/Login.aspx");

I have also tried Server.Transfer but couldn't get success due to the unavailability of the page controls inside a reference method(delegate).

I have already tried a static property which I filled in delegate response and continuously checking it on client side using ASP.NET SignalR to perform a redirect but as it a static property, it redirects all the user to the login page which I don't want to do it.

private void Response_Recieved(Message objMessage)
{
    try
    {
        if (objMessage.OperationType == Operation.Data)
        {
            NotificationMessage  objNotifications = new DataProcess().Deserialize_Messages(objMessage);
            _jsonData = JsonConvert.SerializeObject(objNotifications);
        }
        else if (objMessage.OperationType == Operation.ServerAbnormalDisconnect)
        {
            // I want to redirect a user to login page whenever server disconnects
            HttpContext.Current.Response.Redirect("~/Login.aspx");
            //Response.Redirect("~/Login.aspx");
        }

    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

What would be the alternative or best approach to perform a redirect from a delegate function when there is no control available also without using any static property?

Suhaib Janjua
  • 3,538
  • 16
  • 59
  • 73
  • If I understand you correctly, you want to redirect the user whose call to the web server initiated an asynchronous call to some delegate when something has gone wrong inside that delegate? – Stephen Kennedy Jun 16 '15 at 17:06
  • Almost it. Well the scenario is like I don't have any access to the database directly, it is on other server machine. I can only connects it with Asp.net SignalR(underlayer websockets) and receives data from the server through this delegate which I registered. So everything is working fine. The only thing on which I'm stuck is that when the server machine goes down with abnormal disconnect event I WANT THAT THE USER SHOULD BE LOGGED OUT. – Suhaib Janjua Jun 17 '15 at 05:49
  • As it is an async method so it doesn't allow me to Redirect the user from its body as the HTTP context is not available in this context. So what could be best option in this kind of scenario ? – Suhaib Janjua Jun 17 '15 at 05:52

3 Answers3

1

You can't issue a HTTP redirect call from an asynchronous operation in ASP.Net but there are viable alternatives. I will make my answer generic to hopefully help other readers but as a SignalR user you need to look at number 3.

Let's examine 3 scenarios:

  1. An async operation is commenced from within a normal HTTP request using HostingEnvironment.QueueBackgroundWorkItem (.NET 4.5.2 onwards).

    The resource requested is (where applicable) processed/rendered, and returned. The request is completed. There is no longer any request to redirect. In this scenario, you could perhaps store a value in the Application cache with an expiry time to redirect the user on the next request.

  2. Your clients are connected by way of web socket and your server side implementation uses Microsoft.WebSockets.dll. The connection to the web server is upgraded to a full-duplex socket connection; it is not the url for the page but a comms connection so there is nothing to redirect.

    Instead, you send a command over the connection informing the client side code that a redirect is needed and you perform the redirect in JavaScript. In the WebSocketHandler, with this example sending a string command:

    Send("LOGOFF");

and in the JavaScript ws.onmessage handler, identify the message as "LOGOFF" and change the window.location.href to the target page:

    ws.onmessage = function (message) {
        switch (message.data) {
            case "LOGOFF":
                location.href = "Login.aspx";
        }
    };

The above example is simplified. I have a site which does this and actually send a class (JSON serialised) with a command type and optional payload.

  1. SignalR has the same issues as #2 and I would propose a similar solution. I've not worked with SignalR yet but according to a comment on this answer you would send the command like so:

    GlobalHost.ConnectionManager.GetHubContext<Chat>().Clients.Client(connectionId)‌​.addMessage("LOGOFF");

Look out for the LOGOFF message in your SignalR client-side message handler and set the window location href to your login page.

Community
  • 1
  • 1
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
0

The Response.Redirect method uses a ThreadAbortException to stop the execution of the current request.

As you are catching that exception and just absorbing it, the request handling will just go on as usual and ignore the redirect that you tried to do.

You can use a variable to flag your desire to do the redirect, and then perform it outside the try...catch:

private void Response_Recieved(Message objMessage) {
  bool doRedirect = false;
  try {
    if (objMessage.OperationType == Operation.Message_Response) {
      NotificationMessage  objNotifications = new DataProcess().Deserialize_Messages(objMessage);
      _jsonData = JsonConvert.SerializeObject(objNotifications);
    } else if (objMessageBo.OperationType == Operation.ServerAbnormalDisconnect) {
      // I want to redirect a user to login page whenever server disconnects
      doRedirect = true;
    }
  } catch (Exception ex) {
    Logger.WriteException(ex);
  }
  if (doRedirect) {
    HttpContext.Current.Response.Redirect("~/Login.aspx");
  }
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • It didn't work for me. As I told you in detail that my delegate function have no access on the HTTPContext in its body. So when it executes it has nothing to do with the server controls. I have already rephrased my scenario above in comments. – Suhaib Janjua Jun 17 '15 at 11:20
  • 1
    @Joker: Oh, the method is executed asynchronously? That's not obvious from using a delegate, as that is just a method reference. In that case you can't do a redirect at all from that thread, you have to communicate back to the thread that handles the request that it should do a redirect. – Guffa Jun 17 '15 at 13:03
0

Here is what I had done years back. I am posting it here to help others who are asking me.

Well it is clearly can't be done from an asynchronous ASP.NET method(delegate).

So to achieve the desire functionality I passed a value to the client side from the method using normal broadcasting in SignalR.

And on client side, I am validating and performing actions accordingly. I have changed the URL using simple JavaScript. I am putting a simplest code to understand the core concept of redirection from ASP.NET using SignalR.

Code Behind

[HubMethodName("getSessionState")] 
public string GetSessionState(string status) {

    return Clients.Caller.UpdatedState(status);

}

private void Response_Recieved(Message objMessage)
{
    try
    {
        if (objMessage.OperationType == Operation.Data)
        {
            NotificationMessage  objNotifications = new DataProcess().Deserialize_Messages(objMessage);
            _jsonData = JsonConvert.SerializeObject(objNotifications);

            SendNotifications(_jsonData);
        }
        else if (objMessage.OperationType == Operation.ServerAbnormalDisconnect)
        {
            GetSessionState("false");   //<--- Disconnecting session by passing false for sessionstate
        }

    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
} 


var notifications = $.connection.notificationsHub;

notifications.client.updatedState = function (status) {

    if (status === "false") {

        window.alert("Server is disconnected. Forced logout!");

        window.location.href = "/logout.aspx"
    }
    else {

        // Doing my stuff here...

    }

};
Suhaib Janjua
  • 3,538
  • 16
  • 59
  • 73