简体   繁体   English

“发送HTTP标头后无法重定向”,但是如果删除RedirectToAction,Response.Redirect将不起作用

[英]“Cannot redirect after http headers have been sent”, but Response.Redirect doesn't work if I remove RedirectToAction

So I'm trying to recycle some code that was for a 'code behind' patterned .NET app for my MVC app and the Authenticate class they used. 因此,我正在尝试为我的MVC应用程序和他们使用的Authenticate类回收一些代码,这些代码用于“隐藏代码”模式的.NET应用程序。 How the SignInController's Index method based on the code they gave me is supposed to work is to call an Authenticate class method in the else if which gets a token and redirects back to the Index method at which point since the app now has a token, it goes into the first if conditional and a different method in the aforementioned Authenticate validates the token. 根据他们给我的代码,SignInController的Index方法应该如何工作,就是在else if调用Authenticate类方法, else if该方法获得了令牌并重定向回Index方法,此时应用程序现在有了令牌,因此if有条件,并且前面提到的Authenticate中的其他方法验证令牌,则进入第一个。 Since users will not start out with a token, the else if will always be dove into first. 由于用户不会以令牌开头,因此else if总是会优先考虑的。

In order to soothe the "Not all code paths return a value" error I have to add a return statement at the end of the else if clause and an else clause. 为了缓解“并非所有代码路径都返回值”错误,我必须在else if子句和else子句的末尾添加return语句。 However, if I return null Index doesn't get redirected to as confirmed by breakpoints. 但是,如果我return null ,则索引不会重定向到断点所确认的位置。 However, if I do return RedirectToAction("Index", "SignIn"); 但是,如果我确实return RedirectToAction("Index", "SignIn"); I get an error about "Cannot redirect after HTTP headers have been sent" which I suspect is because the Redirect call from the Authenticate class hasn't been completed yet. 我收到有关“发送HTTP标头后无法重定向”的错误,我怀疑这是因为来自Authenticate类的Redirect调用尚未完成。 However I'm at odds as to how to remedy situation as either return value fails to redirect the web app back to Index... 但是我对如何补救这种情况感到困惑,因为任一返回值均无法将Web应用重定向到索引...

Original "look behind" styled .NET code that I'm trying to recycle from a colleague's app: 我正尝试从同事的应用程序中回收的原始“向后看”样式的.NET代码:

if (string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name) &&  HttpContext.Current.Request.QueryString["Token"] != null)
{
// we’ve got a token, they must have logged in .. double-check the token
string ssoToken = HttpContext.Current.Request.QueryString["Token"].ToString();
string userRoles = string.Empty;
  if (Authenticate.ValidateSSOToken(ssoToken, out userRoles))
  {
      string userName = HttpContext.Current.User.Identity.Name;
      ((BaseApplicationPage)(this.Page)).CurrentSecurity.SetUser(userName, "", userRoles);
      RedirectOnSuccess();

  }
  else
  {
      RedirectToForbiddenPage();
  }
}
else if(string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name))
{
   // no user data..go ask them to get SSOToken from service
   Authenticate.isUserAuthenticated();
}

My attempt to repurpose it into a MVC styled .NET app: 我试图将其重新用于MVC样式的.NET应用程序:

        public ActionResult Index()
        {
            if (string.IsNullOrEmpty(System.Web.HttpContext.Current.User.Identity.Name) && System.Web.HttpContext.Current.Request.QueryString["Token"] != null)
            {
                // we’ve got a token, they must have logged in ... double-check the token
                string ssoToken = System.Web.HttpContext.Current.Request.QueryString["Token"].ToString();
                string userRoles = string.Empty;
                if (Authenticate.ValidateSSOToken(ssoToken, out userRoles))
                {
                    string userName = System.Web.HttpContext.Current.User.Identity.Name;
                    //((BaseApplicationPage)(this.Page)).CurrentSecurity.SetUser(userName, "", userRoles);
                    //RedirectOnSuccess();

                    // TODO: Not sure what the MVC equivalent would be for commented out code above
                    return RedirectToAction("Index", "Checklist");   
                }
                else
                {
                    //RedirectToForbiddenPage();
HttpStatusCodeResult(HttpStatusCode.Forbidden);
                }
            }
            else if (string.IsNullOrEmpty(System.Web.HttpContext.Current.User.Identity.Name))
            {
                // no user data...go ask them to get SSOToken from service
                Authenticate.isUserAuthenticated();
                return null; // Screwed if I don't return anything because of build error, screwed if I do return something because it messes with the redirect
            }
            else
            {
                return null;
            }
        }

Authenticate class snippet at the end of isUserAuthenticated that gets the token: isUserAuthenticated末尾验证类代码段,以获取令牌:

//string RedirectURL = GetBaseVirtualDirectory() + "/SignIn/Index";
string RedirectURL = "https://localhost:XXXX1/SignIn/Index";
HttpContext.Current.Response.Redirect(authServiceURL + "/Windows/Auth?RedirectURL=" + RedirectURL, true);

The problem is that your Authenticate.ValidateSSOToken method already called HttpContext.Current.Response.Redirect , which, as error message confirms, added a redirect header ( Location ) to the response. 问题是您的Authenticate.ValidateSSOToken方法已经调用了HttpContext.Current.Response.Redirect ,作为错误消息的确认,该方法向响应添加了重定向标头( Location )。

You might be able to clear the response before calling RedirectToAction . 您可以在调用RedirectToAction之前清除响应。

But a method called ValidateSSOToke probably should not do any redirects itself. 但是一个称为ValidateSSOToke的方法可能自己不应进行任何重定向。 It should return a status and you should do any redirects outside of it based on that status. 它应该返回一个状态,您应该根据该状态在其外部进行任何重定向。

And doing all that validation inside your Action is probably not a good practice to begin with. 首先,在Action中进行所有验证可能不是一个好习惯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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