简体   繁体   中英

How to do a Response.Redirect from a ASP.NET delegate

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?

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.

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");
  }
}

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...

    }

};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM