如何从 ASP.NET 委托中执行 Response.Redirect

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

我尝试了以下典型方法,但无法从异步 ASP.NET 方法进行重定向:

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

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

我也尝试过 Server.Transfer 但由于引用方法(委托)中的页面控件不可用而无法成功。

我已经尝试了一个静态 属性,我在其中填写了委托响应并在客户端使用 ASP.NET SignalR 不断检查它以执行重定向但由于它是静态的 属性,它会将所有用户重定向到我不想这样做的登录页面。

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

当没有可用的控件且不使用任何静态 属性 时,从委托函数执行重定向的替代方法或最佳方法是什么?

Response.Redirect方法使用ThreadAbortException停止当前请求的执行。

当您捕获该异常并吸收它时,请求处理将照常进行并忽略您尝试执行的重定向。

您可以使用变量来标记您希望进行重定向,然后在 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");
  }
}

您无法从 ASP.Net 中的异步操作发出 HTTP 重定向调用,但有可行的替代方法。我将使我的回答通用化,希望能帮助其他读者,但作为 SignalR 用户,您需要查看数字 3。

让我们检查 3 个场景:

  1. 异步操作是从使用 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 的正常 HTTP 请求中开始的,使用到期时间将用户重定向到 next 请求。

  2. 您的客户端通过网络套接字连接,您的服务器端实现使用 Microsoft.WebSockets.dll。与网络服务器的连接升级为全双工套接字连接;它不是页面的 url 而是通信连接,因此没有任何重定向。

    相反,您通过连接发送命令通知客户端代码重定向需要并且您在 JavaScript 中执行重定向。在WebSocketHandler中,用这个例子发送一个字符串命令:

    Send("LOGOFF");

并在 JavaScript ws.onmessage 处理程序中,将消息标识为 "LOGOFF" 并将 window.location.href 更改为目标页面:

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

上面的例子被简化了。我有一个执行此操作的站点,实际上发送了一个 class(JSON 序列化),其中包含命令类型和可选有效负载。

  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 你会像这样发送命令:

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

在您的 SignalR 客户端消息处理程序中查找 LOGOFF 消息,并将 window 位置 href 设置为您的登录页面。

这是我多年前所做的。我将它张贴在这里是为了帮助其他问我的人。

嗯,这显然不能通过异步 ASP.NET 方法(委托)完成。

因此,为了实现所需的功能,我通过在 SignalR 中使用普通广播的方法向客户端传递了一个值。

在客户端,我正在相应地验证和执行操作。我已经使用简单的 JavaScript 更改了 URL。我正在使用最简单的代码来理解使用 SignalR 从 ASP.NET 重定向的核心概念。

代码隐藏

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

    }

};