form POST in ASP.NET page - asp.net

I am trying to implement a paypal payment in my .aspx page. I have the following html in my page:
<form target="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="hosted_button_id" value="19218">
<input type="hidden" name="rm" value="2">
<input type="hidden" name="business" value="<%= ConfigurationManager.AppSettings("BusinessEmail").ToString%>">
<input type="hidden" name="item_name" value="<%= "CityBits Gold " & listplans.SelectedItem.ToString & " listing plan for " & trim(txttitle.text)%>">
<input type="hidden" name="item_number" value="<%= HiddenFieldid.Value%>">
<input type="hidden" name="amount" value="<%= listplans.SelectedValue%>">
<input type="hidden" name="currency_code" value="EUR">
<input type="hidden" name="return" value="<%= ConfigurationManager.AppSettings("ReturnUrl").ToString & "?requestID=" & HiddenFieldid.Value%>">
<input type="hidden" name="cancel_return" value="<%= ConfigurationManager.AppSettings("CancelUrl").ToString%>">
<input type="hidden" name="no_shipping" value="1">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_cart_LG.gif" border="0" name="submit" alt="">
<img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
In my aspx page, when i click the paypal button, it just refresh the page. When I put the exact same code (with actual values of course) in a plain html file and click the button, it redirect me to paypal as desired. I have tried using actual values for inputs just like in the html page, but it still does not work.
if it matters, I have update panels in my page, but this form is not inside them.
Anyone knows what I am doing wrong? It might be something stupid, but this is giving me headaches for 2 days now!

The problem here is the way ASP.NET pages work. ASP.NET always assumes only one large form on the page, and begins to perform various tricks when you introduce a second one.
However what you can use in your case is a Button control and its PostBackUrl property. It will handle your inner form correctly, gathering all parameters and performing a post:
<form target="paypal">
...
<asp:ImageButton runat="server" ID="PayPalSubmit"
PostBackUrl="https://www.paypal.com/cgi-bin/webscr"
ImageUrl="https://www.sandbox.paypal.com/en_US/i/btn/btn_cart_LG.gif" />
</form>

This is a well-known issue with ASP.NET forms when trying to post data to PayPal. Here's a really cool solution that I use all the time for E-Commerce Web Forms applications:
http://jerschneid.blogspot.com/2007/03/hide-form-tag-but-leave-content.html
And here are two personal blog posts expanding on Jeremy Schneider's idea of using a custom version of HtmlForm:
http://codersbarn.com/post/2008/03/08/Solution-to-ASPNET-Form-PayPal-Problem.aspx
http://codersbarn.com/post/2008/03/27/Integrate-PayPal-Checkout-Button-with-ASPNET-20.aspx
Stay away from using double form tags, JavaScript and other hacks.
using System;
using System.Web.UI;
using System.Web.UI.HtmlControls;
/// <summary>
/// This is a special form that can _not_ render the actual form tag, but always render the contents
/// </summary>
public class GhostForm : System.Web.UI.HtmlControls.HtmlForm
{
protected bool _render;
public bool RenderFormTag
{
get { return _render; }
set { _render = value; }
}
public GhostForm()
{
//By default, show the form tag
_render = true;
}
protected override void RenderBeginTag(HtmlTextWriter writer)
{
//Only render the tag when _render is set to true
if (_render)
base.RenderBeginTag(writer);
}
protected override void RenderEndTag(HtmlTextWriter writer)
{
//Only render the tag when _render is set to true
if (_render)
base.RenderEndTag(writer);
}
}

Related

Razor Pages action from input button

I'm trying to understand how Razor pages work, as well as .Net Core, by creating a small web application and I'm stuck on how to handle the button action within a form. I'm used to the MVC type of process (from when I first tried web apps 5 years ago) where the button would have a onClick action that could be accessed from the code behind but it seems like that's not the same with a Razor page (unless I'm just not seeing it). I have a basic form like this
<form method="post">
<fieldset>
<input type="text" value="" placeholder="user name"/>
<input type="password" value="" placeholder="password"/>
<input type="button" value="Submit" id="submitButton"/>
</fieldset>
So what I'm trying to achieve is when the button is pressed an action in the .cs file is called that will perform a couple different operations (like calling an API, getting a result and then depending on result route to a different page) but even if I add an "onClick" to the button I can't figure out how to hook it up to the code behind. I've seen various answers, most using models and a database but since that's not the same as what I'm doing those examples haven't helped.
I will try to make a simple example for you. Create a razor page and use the name "Test". The Test.cshtml file should have the following contents:
#page
#model WebApplication1.Pages.TestModel
<form method="post">
<fieldset>
<input asp-for="username" placeholder="user name" />
<span asp-validation-for="username" class="text-danger"></span>
<br />
<input asp-for="password" type="password" placeholder="password" />
<span asp-validation-for="password" class="text-danger"></span>
<br />
<input type="submit" value="Submit" id="submitButton" />
</fieldset>
</form>
The Test.cshtml.cs should have the following contents
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace WebApplication1.Pages
{
public class TestModel : PageModel
{
[BindProperty]
public string username { get; set; }
[BindProperty]
public string password { get; set; }
public void OnGet()
{
// you can initialize the values. for example I set the username
username = "test";
}
public IActionResult OnPost()
{
// do something with username and password
if (string.IsNullOrEmpty(password))
{
ModelState.AddModelError("password", "Password is a required field.");
return Page();
}
// or you can redirect to another page
return RedirectToPage("./Index");
}
}
}
Tell me if you need extra explanation for this example. I hope it helps.

How to form post from C#

I've an aspx form with a form tag as below and this form tag contains some sensitive info with hidden fields
<form id="payment_confirmation" target="myFrame" action='https://testsecureacceptance.cybersource.com/embedded/pay' method="post"/>
<input type="hidden" name="access_key" value="sensitivevalue1">
<input type="hidden" name="profile_id" value="sensitivevalue2">
<input type="hidden" name="transaction_uuid" value="<% Response.Write(getUUID()); %>">
<input type="hidden" name="signed_field_names" value="sensitivevalue3">
<input type="hidden" name="unsigned_field_names" value="card_type,card_number,card_expiry_date">
<input type="hidden" name="signed_date_time" value="<% Response.Write(getUTCDateTime()); %>">
<input type="hidden" name="locale" value="en">
<input type="submit" id="submit" name="submit" value="Submit"/>
</form>
When i click "Submit" it successfully post the values and user is "redirected" into the "https://testsecureacceptance.cybersource.com/embedded/pay" form but those hidden fields values are exposed to users (when they inspect the page). I can encrypt them but is there any other way i can post values and redirect from backend where values will not be exposed to users?
Thanks
In short, no. Hidden fields are only hidden from view on the screen and will always be available be available when viewing the source of the page when you are using web forms like this. You can use the viewstate, which will encode the fields and make them harder to read, but if it is truly sensitive information, you will need to properly encrypt that information.
Hope that helps.

Passing a cart total variable to Paypal in asp.net

When implementing Paypal I have managed to set it up to send a set value such as £25 however not a variable from the basket e.g. 'GrandTotal' which is dependent on what the customer has entered into the cart (I have created my own cart.)
<form action="paypal.com/cgi-bin/webscr"; method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="you#youremail.com">
<input type="hidden" name="item_name" value="Item Name">
<input type="hidden" name="currency_code" value="GBP">
<input type="hidden" name="amount" value="25.00">
<input type="image" src="paypal.com/en_US/i/btn/x-click-but01.gif"; name="submit" alt="Make payments with PayPal - it's fast, free and secure!"> </form>
Do you know how to send the variable rather than a set amount? Is the code below anywhere near a solution?
<input type="hidden" name="amount" value="GrandTotal">
You cannot insert your form tag in ASP.Net page (unless iframe), because ASP.Net only allows one form tag in a page.
You want similar like this in code behind. It basically collect user entered Amount and Quantity, and then post it back to PayPal.
protected void PayButton_Click(object sender, EventArgs e) {
string paypalUrl = IsTestMode ?
"https://www.sandbox.paypal.com/us/cgi-bin/webscr" :
"https://www.paypal.com/us/cgi-bin/webscr";
var builder = new StringBuilder();
builder.Append(paypalUrl);
builder.AppendFormat("?cmd=_xclick&business={0}",
HttpUtility.UrlEncode(you#youremail.com));
builder.Append("&lc=US&no_note=0&currency_code=GBP");
builder.AppendFormat("&item_name={0}",
HttpUtility.UrlEncode(YourItemName));
builder.AppendFormat("&amount={0}", AmountTextBox.Text);
builder.AppendFormat("&return={0}",
HttpUtility.UrlEncode("http://mysite.cm/ReturnUrl"));
builder.AppendFormat("&cancel_return={0}",
HttpUtility.UrlEncode("http://mysite.cm/CancelUrl"));
builder.AppendFormat("&undefined_quantity={0}", QuantityTextBox.Text);
HttpContext.Current.Response.Redirect(builder.ToString());
}
You can make input field server side by adding runat="server" in input field tag and can set it value from .cs file
field.value=GrandTotal;
Your aspx page code
<form name="_xclick" target="paypal" action="https://www.paypal.com/cgi-bin/webscr"
method="post" runat="server">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="business" value="you#youremail.com" />
<input type="hidden" name="item_name" value="Item Name" />
<input type="hidden" name="currency_code" value="GBP" />
<input type="hidden" name="amount" id="amount" runat="server" />
<input type="image" src="https://www.paypal.com/en_US/i/btn/view_cart.gif" border="0"
name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
<input type="hidden" name="display" value="1">
</form>
Your code behind page code
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
amount.Value = "25.25";
}
}

Binding arrays with missing elements in asp.net mvc

I am trying to bind a dynamic array of elements to a view model where there might be missing indexes in the html
e.g. with the view model
class FooViewModel
{
public List<BarViewModel> Bars { get; set; }
}
class BarViewModel
{
public string Something { get; set; }
}
and the html
<input type="text" name="Bars[1].Something" value="a" />
<input type="text" name="Bars[3].Something" value="b" />
<input type="text" name="Bars[6].Something" value="c" />
at the moment, bars will just be null. how could I get the model binder to ignore any missing elements? i.e. the above would bind to:
FooViewModel
{
Bars
{
BarViewModel { Something = "a" },
BarViewModel { Something = "b" },
BarViewModel { Something = "c" }
}
}
Add the .Index as your first hidden input to deal with out of sequence elements as explained in this Phil Haacked blog post:
<input type="text" name="Bars.Index" value="" />
<input type="text" name="Bars[1].Something" value="a" />
<input type="text" name="Bars[3].Something" value="b" />
<input type="text" name="Bars[6].Something" value="c" />
A possible workaround could be to instantiate the ViewModel and the collection to the correct size (assuming it's known), then update it with TryUpdateModel... something like:
[HttpPost]
public ActionResult SomePostBack(FormCollection form)
{
// you could either look in the formcollection to get this, or retrieve it from the users' settings etc.
int collectionSize = 6;
FooViewModel bars = new FooViewModel();
bars.Bars = new List<BarViewModel>(collectionSize);
TryUpdateModel(bars, form.ToValueProvider());
return View(bars);
}H
MVC is able to populate list itself.
public ActionResult Index(FooViewModel model)
{
...
So no matter if anything is missing mvc will create new List<BarViewModel> and
for each found index - [1],[3],[6] it will create new BarViewModel and add it to List. So you will get FooViewModel with populated Bars.
i didnt know even that worked!
bearing that in mind, id have done something like:
<input type="text" name="Bars.Something" value="a" />
<input type="hidden" name="Bars.Something" value="" />
<input type="text" name="Bars.Something" value="b" />
<input type="hidden" name="Bars.Something" value="" />
<input type="hidden" name="Bars.Something" value="" />
<input type="text" name="Bars.Something" value="c" />
which would hopefully post
a,,b,,,c
but I suspect that will bind in the same way as you describe
Youre probably going to have write a custom model binder that looks for the max index, makes a list of that size then puts the elements in the correct place.
Saying all that, wait for someone else to post a really simple attribute you can put on your property that makes it just work ;D

html-login form not working

I have a child page LoginContent.aspx which contains a login form. If the user logs in he should be redirected to my Welcome.aspx page. But if I press the login button the page just reloads itself, nothing happens.
The codebehind on this page is empty. Both LoginContent.aspx and Welcome.aspx are child forms of the same master page.
<form method="post" action="~/Welcome.aspx">
Username: <input type="text" name="username" size="15" /><br />
Password: <input type="password" name="passwort" size="15" /><br />
<input type="submit" value="Login"/></p>
</form>
I know I could use the asp.net login control but I want more control over things.
You can't have nested form inside aspx page.
UPDATED:
Since ASP.NET webform doesn't allow us to have multiple form in one aspx page, thus in order to make it works, do the following:
Remove the form tag
add runat server to
the input perform redirect in the server side
.
Username: <input type="text" name="username" size="15" runat=server /><br/>
Password: <input type="password" name="passwort" size="15" runat=server /><br/>
<input type="submit" value="Login" runat=server onclick="submit_onclick" /></p>
And in the code behind:
protected void submit_onclick(object sender, Event e)
{
// do some auth stuff here
Response.Redirect("~/welcome.aspx");
}
Hope this will answer your question.. :)
If your <form> tag from your LoginContent.aspx nested inside your <form runat="server"> I would try moving it so it sits outside the server-side form and see if it works from there.
It might be worth tracking the HTTP requests in the Net panel of Firebug as well, just so you can see if it is actually making the HTTP POST request to /Welcome.aspx - it might help you pinpoint exactly where the problem is.

Resources