Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Trying to replicate Webforms Realex solution using MVC

Options
  • 16-08-2014 10:26am
    #1
    Closed Accounts Posts: 1,143 ✭✭✭


    Hi folks,

    I developed a simple enough solution on my website to take online payments via Realex. We use the redirect method, which requires us to submit approximately 10 hidden form fields to an external site (the Realex payment gateway). I developed a solution for this that basically works by me setting up the variables that I need using my button click event handler in my codebehind/.cs page, and on my aspx page, I have an <asp:button> and in the Postback declaration for this button, this is where I put the URL where my hidden data fields (approximately 10, which are done like this: <input type="hidden" name="AMOUNT" id="AMOUNT" value='<asp:Literal ID="Literal_HiddenField_AMOUNT" runat="server"></asp:Literal>' /> ), and then my Literal's are then accessed and set programmatically in my codebehind, (these fields are things like OrderID, TimeStamp, Amount, UserID etc), all gets submitted to my Realex payment page. This all works exactly as I want it to.

    I've been developing a mobile website for our business, and have decided to do this using MVC. I have found MVC to be a completely different learning experience to Webforms, which I would have been fairly proficient with. Event handlers, something I relied heavily upon when I was developing in Webforms, are out the window it would seem using MVC.

    I'm trying to come up with a simple MVC solution (guided by how I previously accomplished this using Webforms), that lets me put in an amount in a Textbox in my View, click a button and then this will gather up around 10 hidden form fields, and will post this data to a 3rd party website...

    I have declared my hidden form fields in my view, but where I seem to be running into an issue is redirecting to my payment processors website. Using webforms, this was done using a Button Postback and declaring the URL there, but this is not an option in MVC it would seem. If anyone has done this before and can point me in the right direction, I'd be hugely grateful for any tips or pointers!


Comments

  • Registered Users Posts: 11,979 ✭✭✭✭Giblet


    You need to use a form to post to an action, and return a RedirectResult to another action or issue Response.Redirect


  • Registered Users Posts: 2,815 ✭✭✭SimonTemplar


    Just as an aside, I really hate WebForms. Trying to awkwardly force the WinForms architecture to web development just caused too many headaches. Much prefer MVC.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Just as an aside, I really hate WebForms. Trying to awkwardly force the WinForms architecture to web development just caused too many headaches. Much prefer MVC.

    I'm the exact opposite, I started with Webforms and am finding MVC nothing less than a fúcking nightmare to get my head around!


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Giblet wrote: »
    You need to use a form to post to an action, and return a RedirectResult to another action or issue Response.Redirect

    Hi Giblet,

    The problem is that I need the View to appear first, so the user can enter an amount to pay, then click a button and on the buttonclick, then I want the redirect to work.

    Using Webforms, this was done using a buttonclick event handler and a postback, but using MVC, I'm not sure how I go about loading a page (View), that has a number of hidden fields in it and one textbox (for the transaction amount), and a few variables that get created at runtime, (a timestamp and an order ID which is a random number appended to a Timestamp), and a UserID.

    Even if I just hardcode in all these values in my View, to get the page to connect properly to realex, I'm still running into an issue/error.


  • Registered Users Posts: 1,717 ✭✭✭Raging_Ninja


    Hi Giblet,

    The problem is that I need the View to appear first, so the user can enter an amount to pay, then click a button and on the buttonclick, then I want the redirect to work.

    Using Webforms, this was done using a buttonclick event handler and a postback, but using MVC, I'm not sure how I go about loading a page (View), that has a number of hidden fields in it and one textbox (for the transaction amount), and a few variables that get created at runtime, (a timestamp and an order ID which is a random number appended to a Timestamp), and a UserID.

    Even if I just hardcode in all these values in my View, to get the page to connect properly to realex, I'm still running into an issue/error.

    Are you using a viewmodel?


  • Advertisement
  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Are you using a viewmodel?

    I think so, insofar as I have a model, a controller and a view...

    Here's the basic problem...

    I have in my view:

    [HTML]<input id="MERCHANT_ID" name="MERCHANT_ID" type="text" value="MyRealexMerchantID" />[/HTML]

    When I run the solution and go into the respective View, I do a right click and then go into "View Source"... My MERCHANT_ID is EXACTLY as it is meant to be, but when I click on the submit button in the View, which brings me to the Realex payment page, I'm getting an error saying:

    Error 508
    Invalid data in MERCHANT_ID field.

    I've managed the redirect to the Realex payment page as follows:

    I have a button set up like this:

    [HTML]
    <input type="button" value="Submit to Realex" onclick="@(&quot;window.location.href='" + @Url.Action("SubmitRealex", "Home") + "'");" />
    [/HTML]
    And in my home controller I have an action result:

    [HTML]
    public ActionResult SubmitRealex()
    {

    return Redirect("https://theURL.ThatRealexGaveMe.com/epage.cgi");

    }
    [/HTML]





    Edit: The submitting URL that Realex gave me, works fine in my Desktop (Webforms) website, as does the MerchantID and all other values...


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    I've tried something like the following but am still getting an error saying invalid data in MERCHANT_ID field:

    [HTML]
    public ActionResult SubmitRealex(HiddenField MERCHANT_ID)
    {

    ShoppingCart My_Cart = new ShoppingCart();

    My_Cart.MERCHANT_ID = "MyUniqueMerchantIDString";

    MERCHANT_ID.Value = My_Cart.MERCHANT_ID.ToString();
    return Redirect("https://TheRedirectPage.ForRealex.com/epage.cgi");


    }
    [/HTML]


  • Registered Users Posts: 1,717 ✭✭✭Raging_Ninja


    Is it that the merchantid is null when the form is submitted?

    Check these links for passing values on a view to a controller:

    http://stackoverflow.com/questions/21840894/how-to-pass-values-by-post-in-asp-net-mvc-4

    http://stackoverflow.com/questions/12954806/how-to-pass-a-textbox-value-from-view-to-a-controller-in-mvc-4

    http://stackoverflow.com/questions/21454232/asp-net-mvc-how-to-pass-full-model-from-view-to-controller

    I'm on my tablet, not sure if the above are appearing as hyperlinks...


  • Registered Users Posts: 11,979 ✭✭✭✭Giblet


    Ahhh. Stop!

    You need to create a form. A form will post any inputs (hidden or otherwise) back to the action.

    If the view has a Model of
    public class SomeModel
    {
        public int MyModelId { get; set; }
        public string MyValueToCollect { get; set; }
    }
    

    Your form looks like
    <form action="MyController/MyAction">
       @Html.HiddenFor(x => x.MyHiddenId)
       @Html.InputFor(x => x.MyValueToCollect)
       <button type="submit">Submit Form</button>
    </form>
    

    Your action looks like
    public ActionResult MyAction(SomeClass model)
    {
        var id = model.MyHiddenId;
        var value = model.MyValueToCollect;
        //DoStuff
        return RedirectResult("SomeUrl");
    }
    


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Thanks to all on thread for the help with this, I almost have it working, only one obstacle left to overcome...!

    Here's the last prob that I have with this...

    In my view, I have a form with around 10 different input hidden fields. I also have a Textbox that takes in a decimal value (the transaction amount), from the user who is making a payment.

    In my View Controller, I have (1) set up a variable to take a value from my Textbox, (2) multiplied this value by 100, and (3) Converted this variable into an int.

    The reason I have to do this is because Realex needs the amount field to be in this format, for example 1.00 Euro has to be passed as 100, 50.20 Euro has to be passed as 5020, basically you need to remove the decimal point from the variable, so I do this by multiplying the decimal value by 100 and converting it then to an int.

    My problem is getting this code to run. When I did this previously using Webforms, I was using an event handler so I could run this code from: OnTextChanged="TextBox1_TextChanged", so in my codebehind, when the text changed, I just ran the code that converted the decimal to an int, from there, and it all worked fine.

    But here on planet MVC, there are no event handlers! Could someone maybe advise me how I would go about implementing this necessary conversion from my Controller?


  • Advertisement
  • Registered Users Posts: 11,979 ✭✭✭✭Giblet


    Well you can just always convert it whenever you post the value back, you don't need an event.
    public ActionResult MyAction(SomeClass model)
    {
        var id = model.MyHiddenId;
        var value = ConvertMyValue(model.MyValueToCollect);
    
        //DoStuff
        return RedirectResult("SomeUrl");
    }
    
    public int ConvertMyValue(decimal value)
    {
        //Convert to int
        return result;
    }
    

    If you need to check the value has changed, store the initial value as a hidden field on the page, or source the value from somewhere else.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Giblet wrote: »
    Well you can just always convert it whenever you post the value back, you don't need an event.
    public ActionResult MyAction(SomeClass model)
    {
        var id = model.MyHiddenId;
        var value = ConvertMyValue(model.MyValueToCollect);
    
        //DoStuff
        return RedirectResult("SomeUrl");
    }
    
    public int ConvertMyValue(decimal value)
    {
        //Convert to int
        return result;
    }
    
    If you need to check the value has changed, store the initial value as a hidden field on the page, or source the value from somewhere else.

    I have this working now, only thing is that I have hard coded in one value (AMOUNT), this should be taken from a textbox, but in my Controller I have just fixed it to 100 to get everything else working, which it now is.

    So I'm now down to just taking a value from my Textbox and passing it to a decimal variable in my Controller, then running a quick conversion on this and assigning this value back to my Model...


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Quick question lads, does this expression, when placed in a View:

    [HTML] @Html.TextBoxFor(m => m.AMOUNT)[/HTML]

    mean,

    (1) The value of the Textbox is the value of the variable AMOUNT that is in the model?

    or does it mean...


    (1) The Value of the Model is equal to whatever value is entered into the Textbox that exists in the View?

    :confused::confused::confused:


  • Registered Users Posts: 11,979 ✭✭✭✭Giblet


    It means 1 and 2 :)

    If you output the model value in a view, it will be the model value.

    Whatever is typed into the Textbox will be submitted to the controller action when you post the form.
    (Assuming the Action parameter is that model).


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Giblet wrote: »
    It means 1 and 2 :)

    If you output the model value in a view, it will be the model value.

    Whatever is typed into the Textbox will be submitted to the controller action when you post the form.
    (Assuming the Action parameter is that model).

    This is my only prob here, what I am putting into my Textbox is not making its way into my Model

    Model (extract from) is:

    [HTML]public int AMOUNT { get; set; }[/HTML]

    View is below:
    [HTML]
    <form action="https://XYZ.TheURL_That_I_NeedSubmitTo.com/ABC&quot; method="post">
    @Html.TextBoxFor(m => m.AMOUNT)

    <input id="AMOUNT" name="AMOUNT" type="hidden" value="@ViewBag.REALEXAMOUNT" />
    [/HTML]

    Controller below:

    [HTML] decimal RealexAdjusted = (My_Cart.AMOUNT * 100);
    RealexPrice = Convert.ToInt32(RealexAdjusted);
    My_Cart.AMOUNT = RealexPrice;
    ViewBag.REALEXAMOUNT = RealexPrice;
    [/HTML]

    When I remove my textbox and just hardcode in a value of say 100 for the AMOUNT, this solution works fine, only that of course the amount will always be different, hence the need for the Textbox!


  • Registered Users Posts: 11,979 ✭✭✭✭Giblet


    Ah!
    Well if you look at what will output above, it will be the following
    <form action="https://XYZ.TheURL_That_I_NeedSubmitTo.com/ABC" method="post">
      <input id="AMOUNT" name="AMOUNT" type="text" value="@Model.AMOUNT" />
    
      <input id="AMOUNT" name="AMOUNT" type="hidden" value="@ViewBag.REALEXAMOUNT" />
    

    So you have the same field twice.

    Don't use viewbag at all, ever if possible.

    Here's how I would do it

    Model
    public class Model
    {
        public decimal InputAmount { get; set; }
        public int InitialAmount { get; set; }
    }
    

    Form
    <form action="@Url.Action("ControllerName","UpdateAmount")" method="post">
      @Html.TextBoxFor(x => x.InputAmount)
      @Html.HiddenFor(x => x.InitialAmount)
      @Html.ValidationSummary()
    </form>
    

    Action(s), I expect you to call http://www.mypage.com/ControllerName/GetAmount to view what you have, and you post the updates to another action that just deals with updating the amount.
    [HttpGet]
    public ActionResult GetAmount()
    {
        var model = SomeMethodToGetModel();
        return View("InitialView", model);
    }
    
    [HttpPost]
    public ActionResult UpdateAmount(Model model)
    {
        var intAmount = Convert.ToInt32(model.InputAmount);
        if(intAmount != model.InitialAmount)
        {
             //Do Something.
             return RedirectResult("SomeUrl");
        }
       ModelState.AddError("InputAmount","You didn't enter a different amount");
        return View("InitialView",model)
    }
    
    
    


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Giblet wrote: »
    Ah!
    Well if you look at what will output above, it will be the following
    <form action="https://XYZ.TheURL_That_I_NeedSubmitTo.com/ABC" method="post">
      <input id="AMOUNT" name="AMOUNT" type="text" value="@Model.AMOUNT" />
    
      <input id="AMOUNT" name="AMOUNT" type="hidden" value="@ViewBag.REALEXAMOUNT" />
    
    So you have the same field twice.

    Don't use viewbag at all, ever if possible.

    Here's how I would do it

    Model
    public class Model
    {
        public decimal InputAmount { get; set; }
        public int InitialAmount { get; set; }
    }
    
    Form
    <form action="@Url.Action("ControllerName","UpdateAmount")" method="post">
      @Html.TextBoxFor(x => x.InputAmount)
      @Html.HiddenFor(x => x.InitialAmount)
      @Html.ValidationSummary()
    </form>
    
    Action(s), I expect you to call http://www.mypage.com/ControllerName/GetAmount to view what you have, and you post the updates to another action that just deals with updating the amount.
    [HttpGet]
    public ActionResult GetAmount()
    {
        var model = SomeMethodToGetModel();
        return View("InitialView", model);
    }
    
    [HttpPost]
    public ActionResult UpdateAmount(Model model)
    {
        var intAmount = Convert.ToInt32(model.InputAmount);
        if(intAmount != model.InitialAmount)
        {
             //Do Something.
             return RedirectResult("SomeUrl");
        }
       ModelState.AddError("InputAmount","You didn't enter a different amount");
        return View("InitialView",model)
    }
    
    
    

    I've tried that return RedirectResult("SomeUrl"); approach and it isn't agreeing with whatever is going on at the Realex end, I had to go back to:

    <form action="https://123.theServerThatRealexUse.com/ABCDEF&quot; method="post">

    I just haven't the proficiency with MVC to work with it yet to the point where I can do stuff easily, it is a nightmare at the mo I'm finding!


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Like say I just want to put the integer value into the Textbox, and forget about converting a decimal, to an int, even that seems to be complicated?!?


Advertisement