I recently posted a solution to the eternal PayPal / ASP.NET form submission problem using Jeremy Schneider's custom GhostForm class. Since then, several people have made mention of a problem that I came across myself when coding this, namely getting your project to recognize the reference to the new custom form class.
Using a Web Application Project in VS 2005, I recently came up against something similar when attempting to place the SqlHelper.cs class in the App_Code folder. At that time I offered a quick hack. Since then, I have thought better of using the App_Code folder in my Web Application Projects and just create a normal folder and put the helper class in there along with my data access class. The App-Code is more trouble than it is worth for a small project where there is practically zero compilation time to be saved anyway.
Back to the problem at hand... when attempting to compile, you may get the following error:
"The name 'mainForm' does not exist in the current context"
First, check your scopes; make sure that wherever you are using the mainForm object is in the same scope as the instantiation. Ideally, create a separate Class Library Project in your solution and add the custom form class to it. Compile your new project separately and reference that from your e-commerce project. Right-click the References folder in Solution Explorer and browse to the DLL for the custom form.
Add the following to your master page and ignore any red squigglies you get in Visual Studio:
<%@ Register TagPrefix="CF" Namespace="CustomForm" Assembly="CustomForm" %>
<body>
<CF:GhostForm id="mainForm" runat="server">
...
</body>
Add markup to the ASPX for the dummy PayPal button and a functioning ASP.NET button:
<img src="https://www.sandbox.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"> <asp:Button ID="checkoutBtn" runat="server" OnClick="CheckButton_Click"
Text="Checkout" Width="100" CausesValidation="false" />
using CustomForm;
namespace MyProject
{
public partial class purchase : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
...
// Workaround for PayPal form problem
GhostForm mainForm = new GhostForm();
mainForm.RenderFormTag = false;
}
...
}
...
}
Although specific to my own project requirements, here's the complete handler code for the button click:
protected void CheckButton_Click(object sender, EventArgs e)
{
// Live PayPal URL
// const string SERVER_URL = "https://www.paypal.com/cgi-bin/webscr";
// Sandbox PayPal URL
const string SERVER_URL = "https://www.sandbox.paypal.com/cgi-bin/webscr";
// Live business parameter
// const string BUSINESS = "grace@graceguitars.com";
// Sandbox business parameter
const string BUSINESS = "tester@hotmail.com";
// Return URL for IPN processing
const string NOTIFY_URL = "http://www.mysite.com/PayPalReturnURL.aspx";
decimal totalAmount = 0.00M;
int productID = 0;
int totalUnits = 0;
decimal totalShipping = 0.00M;
string paypalURL = "";
string itemName = "Grace\'s Guitars";
string itemNumber = "";
if (cart.Count > 0)
{
BizClass biz = new BizClass();
// TransactionID will be later used to check against IPN info
string transID = Guid.NewGuid().ToString();
// Create a new Order in DB
orderID = biz.AddOrder(out orderID, transID, false, DateTime.Now);
itemNumber = Convert.ToString(orderID);
foreach (ShoppingCartItem item in cart)
{
totalAmount += item.Total;
totalUnits += item.Units;
productID += item.ProductID;
// Store order details in database
biz.AddOrderDetails(orderID, productID, item.Units);
}
// Eventually, use a SQL Server job to remove unconfirmed orders
// Calculate total shipping cost for total number of units
totalShipping = CalculateShipping(totalUnits);
// Get back the URL-encoded URL for PayPal
paypalURL = GetPayPalURL(SERVER_URL, BUSINESS, itemName, itemNumber,
totalAmount, totalShipping, NOTIFY_URL);
Response.Redirect(paypalURL, true);
}
}
You need to sign into your PayPal Developer account before submitting your test purchases. You will be able to see a history of your test transactions in the sandbox admin section.
If you want some sample code for constructing the URL, I suggest you check out the following whitepaper from Rick Strahl. This should be enough to see you up and running. Many times, people get compiler errors due to badly-formed namespace declarations and class references. Always double-check your code :-)
GhostForm.zip (448.00 bytes)