ASP.NET MVC 3 - Replacing HttpContext Response Not Working

4.3k Views Asked by At

I am using Nopcommerce which has recently been upgraded to use MVC3 - previously it used webforms. I am attempting to connect to Worldpay's (payment gateway) hosted site. The process is a little convoluted but essentially a form needs to be submitted to Worldpay and the user is then redirected to their hosted site to fill in their credit card details etc.

Nopcommerce takes care of this using a Post method which, on the server side, builds the form that needs to be posted and replaces the httpcontext response with built out HTML

_httpContext.Response.Clear();
_httpContext.Response.Write("<html><head>");
_httpContext.Response.Write(string.Format("</head><body onload=\"document.{0}.submit()\">", FormName));
_httpContext.Response.Write(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\" >", FormName, Method, Url));
for (int i = 0; i < _inputValues.Keys.Count; i++)
    _httpContext.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">", HttpUtility.HtmlEncode(_inputValues.Keys[i]), HttpUtility.HtmlEncode(_inputValues[_inputValues.Keys[i]])));
_httpContext.Response.Write("</form>");
_httpContext.Response.Write("</body></html>");
_httpContext.Response.End();

This works fine in the webforms version but does not work in the MVC version. There is no error, and everything appears to work correctly. However, processing continues and execution returns from the service layer (in which this method is located) to the controller and the following redirect is issued:

 return RedirectToRoute("CheckoutCompleted");

Does MVC work differently to webforms with regard to modifying the response on the server side? I have tried the following code and can confirm that worldpay is indeed being hit and is sending the response I would expect:

_httpContext.Response.Clear();
var webClient = new WebClient();
var responseBytes = webClient.UploadValues(Url, "POST", _inputValues);
var response = Encoding.UTF8.GetString(responseBytes);
_httpContext.Response.Write(response);
_httpContext.Response.End();

Note: in the above examples the HttpContext is injected into the service. The same result is achieved by using the HttpContext.Current

Update:

Doing a little more digging I see that if i write to the response stream from any controller and end the response I get a blank (0 length response) screen. Below is the index action on the home controller which causes said issue. The same code, in a throwaway project I created, works perfectly...

  public ActionResult Index()
  {    
            Response.Write("test");
            Response.End();
            return View(_storeInformationSettings);
  }
1

There are 1 best solutions below

0
On

If you change your third snippet of the code you can leave the Response.Write and Response.End out of your controller.

HttpContext.Current.Response.Clear();
var webClient = new WebClient();
var responseBytes = webClient.UploadValues(Url, "POST", _inputValues);
var response = Encoding.UTF8.GetString(responseBytes);
HttpContext.Current.Response.Write(response);
HttpContext.Current.ApplicationInstance.CompleteRequest();

HttpContext.Current.ApplicationInstance.CompleteRequest(); did the trick for me. See also a nice post about this MSDN Blog about Response.End and Response.Close