Search code examples
c#htmltwitter-bootstrapantiforgerytoken

Server cannot append header after HTTP headers have been sent with AntiForgeryToken


I'm building my first website using C# and Twitter Bootstrap, and I get the "Server cannot append header after HTTP headers have been sent" error in a Post while finding a validation issue and a TempData["ErrorMessage"] needs to be displayed after a return View(model). The specific error occurs on the html line @Html.AntiForgeryToken(). The error does not occur if the message is set and returned to the View outside of the validation.

I've tried: changing the return View(model) to a RedirectToAction ("Action", new { id = model.id }) and Redirect ("/Controller/Action/" + model.id.ToString()), which work if the line is outside the validation, but fails when inside the conditional validation; setting the AntiForgeryConfig.SuppressXFrameOptionsHeader to true inside the Application_start; and calling HttpContext.Response.Clear() before setting the TempData and returning to the View. I haven't tried manipulating cookies yet because I'm unsure of how to specifically address the anti-forgery token.

All I want to do is return to the View with the error/validation message displayed on the page instead of as a pop-up message box, and none of the above methods has worked. Does anyone know why this goal works outside the validation but not inside of it? Many thanks in advance!

//Any return and message works correctly if done here
try
{
    //Various other validations using values pulled from database

    if (model.NewString.Length > 50 || model.NewString.Length < 7)
    {
        //This throws the error
        TempData["ErrorMessage"] = "Please enter a value of valid length.";
        return View(model);
    }
}
catch
{
    TempData["ErrorMessage"] = "There has been an error.";
    return RedirectToAction("Index");
}

EDIT: here is the Action as-is per Amit's request.

[HttpPost]
[ValidateAntiForgeryToken]
[Authorize (Roles = "Administrator, Owner, Director, Manager")]
[RequireSsl]
public ActionResult CreateCustomer (CreateCustomerModel model)
{
    dbEntities db = new dbEntities();

    var CurrentBusinessID = 0;
    var CurrentPosition = "";
    var CurrentUserID = 0;

    try
    {
        if (Session["CurrentUserID"] != null)
        {
            CurrentUserID = (int)Session["CurrentUserID"];
            CurrentBusinessID = (int)Session["CurrentBusinessInfoID"];
            CurrentPosition = (string)Session["CurrentPosition"];
        }
        else
        {
            Response.Redirect("/Account/Logon");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
        Response.Redirect("/Account/Logon");
    }

    try
    {
        var account = db.uspGetAccount(model.AccountID).FirstOrDefault();
        AccountsModel thisAccount = new AccountsModel()
        {
            AccountID = model.AccountID,
            BusinessID = account.BusinessID
        };
        if (thisAccount.BusinessID != CurrentBusinessID)
        {
            Response.Redirect("/Home/Dashboard");
        }

        if (model.Name == null || model.Name == "")
        {
            TempData["ErrorMessage"] = "Please enter a name.";
            return View(model);
        }
        if (model.NewString.Length > 50 || model.NewString.Length < 7)
        {
            //This throws the error
            TempData["ErrorMessage"] = "Please enter a value of valid length.";
            return View(model);
        }

        db.AddCustomer(model.Name, model.NewString);
    }
    catch
    {
        TempData["ErrorMessage"] = "There has been an error.";
        return RedirectToAction("Index");
    }

    return RedirectToAction("Accounts");
}

Solution

  • This issue was solved by changing the Reponse.Redirect("/Home/Dashboard") inside the if statement within the try statement containing the validation. Changing this line to return RedirectToAction("Accounts") solved the problem, although I'm not sure why.

    if (thisAccount.BusinessID != CurrentBusinessID)
    {
        Response.Redirect("/Home/Dashboard");//Solve the problem by replacing this
    }