简体   繁体   中英

“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. 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. Since users will not start out with a token, the else if will always be dove into first.

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. However, if I return null Index doesn't get redirected to as confirmed by breakpoints. However, if I do 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. However I'm at odds as to how to remedy situation as either return value fails to redirect the web app back to Index...

Original "look behind" styled .NET code that I'm trying to recycle from a colleague's app:

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:

        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:

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

You might be able to clear the response before calling RedirectToAction .

But a method called ValidateSSOToke probably should not do any redirects itself. 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.

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