4

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);
  }
JP.
  • 5,536
  • 7
  • 58
  • 100
  • use fiddler for both and compare the responses. the question on 'does mvc work differently' is a bit loaded as it depends on what anything is doing in the web forms pipeline vs. mvc controller. in general, 'no' but it depends on the content type returned, etc. – Adam Tuliper Jan 10 '12 at 05:57
  • I tested and for me it worked fine. I mean, I was able to write on the screen via `response.Write()` and my call to `return RedirectToRoute("CheckoutCompleted");` was not executed after `response.End()` – ClayKaboom Jan 10 '12 at 10:59
  • I have the same issue, but don't see the solution yet. If I put Response.Write("somestring"); Response.End(); in the controller I got no problem. But if I use that in a class I get an error no matter what I use in the class. I have tried:(1) passing HttpContext from controller to method (2) passing ControllerContext to method and then use the HttpContext and (3) HttpContext.Current. All of which didnt work. – Mounhim Apr 17 '13 at 18:47
  • UPDATE: Found a solution I will put it in the answers. – Mounhim Apr 17 '13 at 18:56

1 Answers1

0

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

Mounhim
  • 1,674
  • 1
  • 17
  • 32