Page 1 of 3
Customizations in Gold
Posted: Thu Jul 11, 2013 7:53 pm
by Brewhaus
I am continuing in the nightmare that is upgrading to Gold. No offense to Mike and the gang, but even our customizations from as recent as 7.0.7 cannot be easily moved to Gold, so you will hearing from me a bit over the next few days. Hopefully some of the customizations that we are doing are common enough that others will find them helpful. There are certainly some nice updates in Gold, but customizations for anyone with customizations you will need to weigh if the advantages justify all of the headaches.
Because Gold appears to be so much different in how customizations have to be coded I have not gone back to the 7.0.7 threads to ask for assistance, as that may confuse people trying to customize in 7.0.7.
Now, on to our first couple of needs. These should hopefully be pretty simple:
- How can we get both the regular price (MSRP) and sale price (if there is one) to be displayed in the Featured Products Grid and Category Grid? We would also like to adjust the color and weight / size of the text for the prices.
- When an order is printed the status needs to be updated to Order Printed. It was originally addressed at viewtopic.php?f=42&t=8681, but those modifications do not seem to work with Gold, no matter how many different ways we try them.
- The e-mail address does not automatically populate in the Billing Address section at the checkout, even though the customer has logged in. Their e-mail address is obviously on file, so it should auto-populate, just as the rest of the address does. How do we get the e-mail address to automatically populate?
That should be enough for now. These are the simple ones.

Re: Customizations in Gold
Posted: Fri Jul 12, 2013 8:59 am
by jguengerich
For your first item, the prices shown in FeaturedProductsGrid come from ConLib\Utility\ProductPrice (FeaturedProductsGrid contains ProductItemDisplay which contains ProductPrice). If you already knew that and are asking for more specific help, sorry, hopefully someone else can give you more details.
In general, the email address is populated by:
in the InitAddressForm() method of EditBillAddress.
I am setting up my users ahead of time, but I seem to remember when I first started working with it that the user's email address was not getting copied to the billing address email address. You may need to find the correct place to do AbleContext.Current.User.PrimaryAddress.Email = AbleContext.Current.User.Email (checking to make sure PrimaryAddress is not null), or perhaps do BillToEmail.Text = AbleContext.Current.User.Email if the Primary (billing) address is not available yet when EditBillAddress loads.
Re: Customizations in Gold
Posted: Fri Jul 12, 2013 7:36 pm
by Brewhaus
By messing with the ConLib/Utility/ProductPrice.ascx.cs file we can get both the regular and sale price to show, when applicable, however, they are both the same color, and then on the Product page it shows Reg. Price XXX, Sale Price: both the regular price (with strike-through) and the sale price. I hope that there is better control over the pricing display than this! Honestly, why would anyone
not want to show the regular price and sale price? If you don't, then customers will simply think that this is your regular price, and when the sale goes off they will complain about the increased price.
WRT the e-mail address no populating, is there a feasible way to populate this field automatically for existing customers that are in the system prior to the upgrade. If an existing customer has logged in they will expect their e-mail address to be in the system. Making them re-enter it will cause them to question the integrity of the system, and that will cause lost sales.
No takers on having the orders automatically update to Order Printed when the orders are printed?
I am starting to get concerned that we will not be able to upgrade within AC, meaning the 40+ hours that we have spent on it so far are wasted, and we will have to start looking at other software packages.

Re: Customizations in Gold
Posted: Sat Jul 13, 2013 1:07 pm
by Brewhaus
When needing help with v7 we found that we were getting plenty of response and help, but virtually none with Gold. Is it that so few people have upgraded or worked with Gold yet that they do not know how to customize the files yet? If that is the case, then maybe AC should jump in and lend more of a hand, as people will just give up, and that means no sale. We will need to purchase two upgrades, but only if we can get the customizations completed. I would think that it is far better for AC to help via the forums, as the next person trying to make a similar customization will be able to find the answer on the forum instead of having to contact AC directly.
The file structure has changed significantly in Gold, so we cannot use our prevous files (such as the Invoice.ascx and Invoice.ascx.cs), and copying even just the customized parts of the files result in compilation errors, so we are dead in the water.
Re: Customizations in Gold
Posted: Mon Jul 15, 2013 9:58 am
by chemistrudy
Rick,
We started working with Able last summer, with 7.0.7, right before Gold was released. Learned how to create our "custom file" in the Conlib/custom folder and the whole bit.
The structure for customizing in Gold that has worked for us is way different. I waited and started with Gold R3, I think. And am now on R5, so we've "merged" our customizations with Able's fixes and improvements twice. It works great.
Also, I should note that I decided to stick with WSP.
Step 1: Modify whatever file it is that you need for the customization you want. Don't rename, don't move it. Just make the changes for the customization you want. And save. You'll probably want to comment before and after your changes with something like "Customized Start -- RLO -- 7/12/13" and ""Customized End -- RLO -- 7/12/13". But by no means do you have to, but it will help with step #2 below to know if it is a file difference you've made, or if it is a change from Able, because;
Step 2: When Able comes out with a new release, use a tool like WinMerge to compare any line by line differences between the new released files and those on your live site. Reconcile the differences, by using Ables "new" file with your custom code inserted. Note: With probably 30+ files that I've touched, it took less than 2 hours to go thru from R4 to R5, and resolve them. I've made mods both on our front-end site, and on the admin end, added custom fields - -I think the whole nine yards. (I should give up a special thanks to Judy and Joe for their awesome posts, along with the Able team.)
Step 3: Copy the combined released/customized files into a development site to test them all out. When you are satisfied, with the great combination of Able's improvements and your work, go live.
Once I wrapped my mind around how the customizations could work in Gold, it seems lot easier than in 7.0.7, both from the standpoint of making the change and to keep up with future releases. It is just very different.
Someone who is more of an expert could comment here and revise/improve on what I've been doing... Also, I'm pretty sure this has all be discussed on the forum previously, as I picked it up from somewhere.
Happy with Gold,
Rudy
Re: Customizations in Gold
Posted: Mon Jul 15, 2013 11:05 am
by jguengerich
Rick,
Just guessing here, but you are probably right, it is a combination of things:
A. Fewer people using Gold because it is relatively new version
B. Anyone who is new to AC with the gold version may be still trying to figure things out themselves
C. Anyone who is new to AC with the gold version doesn't know how things were done in prior versions, so helping with upgrade questions is more difficult.
Personally, I just recently started with Gold. There are questions I could probably figure out an answer for. However, since I'm a paid employee, I have to be careful how much time I spend doing that "on the clock" unless it is also a question I need answered. When I'm not "on the clock", I try to leave work at work, so I'm not likely to post as many answers.
On the printed status issue, it looks like the OrderStatusDataSource.Load() method just takes one parameter, the id. It looks like one of the code examples in that other thread has a second parameter for that method, so maybe you just need to remove that second parameter.
In general, I have found the Api Reference to be very helpful (
http://wiki.ablecommerce.com/index.php/ ... uilder_API, click AbleCommerce Gold in the top section). I also frequently use grepWin (a free search tool) to find all files that contain a certain string (method, propery, etc.). This is especially useful in finding where in the source code a method is defined, so I can see exactly what is going on "behind the scenes".
Re: Customizations in Gold
Posted: Mon Jul 15, 2013 4:36 pm
by Shopping Cart Admin
Hello Rick,
I've brought this post to our ForumsAdmin team and hopefully they will have some more detailed insight into your questions. Through the ForumsAdmin account we are working to answer more posts than normal in light of GOLD's changes.
Re: Customizations in Gold
Posted: Mon Jul 15, 2013 7:26 pm
by mazhar
How can we get both the regular price (MSRP) and sale price (if there is one) to be displayed in the Featured Products Grid and Category Grid? We would also like to adjust the color and weight / size of the text for the prices.
In order to show MSRP if available you need to edit
Website/ConLib/Utility/ProductItemDisplay.ascx file and then locate following line
Code: Select all
<uc:ProductPrice ID="ProductPrice" runat="server" PriceFormat="<span class='label'>Price:</span> <span class='value'>{0}</span>" BasePriceFormat='Price: <span class="msrp">{0}</span> '></uc:ProductPrice>
and update it like
Code: Select all
<uc:ProductPrice ID="ProductPrice" runat="server" PriceFormat="<span class='label'>Price:</span> <span class='value'>{0}</span>" BasePriceFormat='Price: <span class="msrp">{0}</span> ' ShowRetailPrice="true"></uc:ProductPrice>
This will enable the desired function accross entire store. In order to set different color or size on MSRP edit the stylesheet of current theme and locate following line in it
Code: Select all
span.msrp { text-decoration:line-through;}
and then you can update it to have red color like
Code: Select all
span.msrp { text-decoration:line-through; color:Red; }
You can also apply more styles like different font etc
Re: Customizations in Gold
Posted: Mon Jul 15, 2013 8:10 pm
by mazhar
When an order is printed the status needs to be updated to Order Printed. It was originally addressed at viewtopic.php?f=42&t=8681, but those modifications do not seem to work with Gold, no matter how many different ways we try them.
Edit your Invoice.ascx.cs file and add following method to it
Code: Select all
protected void MarkPrinted_Click(object sender, EventArgs e)
{
IList<int> selectedOrders = GetSelectedOrders();
if ((selectedOrders == null) || (selectedOrders.Count == 0)) Response.Redirect("~/Admin/Orders/Default.aspx");
IList<Order> orders = GetOrders(selectedOrders.ToArray());
OrderStatus orderStatus = OrderStatusDataSource.Load(7);
foreach (Order order in orders)
order.UpdateOrderStatus(orderStatus);
}
Now find the following line of code in Invoices.ascx file
Code: Select all
<asp:Button ID="Print" runat="server" Text="Print" OnClientClick="window.print();return false;" />
and make it look like
Code: Select all
<asp:Button ID="Print" runat="server" Text="Print" OnClientClick="window.print();return true;" OnClick="MarkPrinted_Click" />
This change will change the order status with the print button.
Re: Customizations in Gold
Posted: Mon Jul 15, 2013 8:25 pm
by mazhar
The e-mail address does not automatically populate in the Billing Address section at the checkout, even though the customer has logged in. Their e-mail address is obviously on file, so it should auto-populate, just as the rest of the address does. How do we get the e-mail address to automatically populate?
I can see that its loading the Email in billing address section for me. I am not sure which version of Gold you are working with. As
jguengerich said about handling it in InItAddress method of website/checkout/EditBillingAddress.aspx.cs file. There you can try to have somthing like
Code: Select all
BillToEmail.Text = string.IsNullOfEmpty(address.Email) ? AbleContext.Current.User.Email : address.Email;
This way it will fallback to user's Email address if billing email is not set on address.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 3:08 pm
by Brewhaus
Thank you so much, Mazhar. You are always a lot of help.
One error that I found, and I am only mentioning it so that others do not have a problem finding the file, is that you pointed to:
In order to show MSRP if available you need to edit Website/ConLib/ProductItemDisplay.ascx file and then locate following line
but the file is actually in the ConLib/Utility folder.
I am also getting a Compilation error when I make the suggested changes to the Invoices.ascx and Invoices.ascx.cs files:
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1518: Expected class, delegate, enum, interface, or struct
Source Error:
Line 183: }
Line 184: }
Line 185: protected void MarkPrinted_Click(object sender, EventArgs e)
Line 186: {
Line 187: IList<int> selectedOrders = GetSelectedOrders();
I can see that its loading the Email in billing address section for me. I am not sure which version of Gold you are working with. As jguengerich said about handling it in InItAddress method of website/checkout/EditBillingAddress.aspx.cs file. There you can try to have somthing like
Code: Select all
BillToEmail.Text = string.IsNullOfEmpty(address.Email) ? AbleContext.Current.User.Email : address.Email;
This way it will fallback to user's Email address if billing email is not set on address.
Where exactly should this be added? When I add this code below InitAddressForm I get a compilation error.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 5:12 pm
by mazhar
Brewhaus wrote:Thank you so much, Mazhar. You are always a lot of help.
One error that I found, and I am only mentioning it so that others do not have a problem finding the file, is that you pointed to:
In order to show MSRP if available you need to edit Website/ConLib/ProductItemDisplay.ascx file and then locate following line
but the file is actually in the ConLib/Utility folder.
I am also getting a Compilation error when I make the suggested changes to the Invoices.ascx and Invoices.ascx.cs files:
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1518: Expected class, delegate, enum, interface, or struct
Source Error:
Line 183: }
Line 184: }
Line 185: protected void MarkPrinted_Click(object sender, EventArgs e)
Line 186: {
Line 187: IList<int> selectedOrders = GetSelectedOrders();
Make sure to place the function code in Website/ConLib/Utility/ProductItemDisplay.ascx.cs just above the very last closing curly brace
}
Brewhaus wrote:
I can see that its loading the Email in billing address section for me. I am not sure which version of Gold you are working with. As jguengerich said about handling it in InItAddress method of website/checkout/EditBillingAddress.aspx.cs file. There you can try to have somthing like
Code: Select all
BillToEmail.Text = string.IsNullOfEmpty(address.Email) ? AbleContext.Current.User.Email : address.Email;
This way it will fallback to user's Email address if billing email is not set on address.
Where exactly should this be added? When I add this code below InitAddressForm I get a compilation error.
Edit Website/Checkout/EditBillingAddress.aspx.cs file and locate following code
if found then update it like
Code: Select all
BillToEmail.Text = string.IsNullOrEmpty(address.Email) ? AbleContext.Current.User.Email : address.Email;
BTW which version of Gold you are using?
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 6:11 pm
by Brewhaus
Mazhar,
That is where I had placed the code. Here is the bottom of my Invoices.ascx.cs file:
Code: Select all
protected void OrderItems_DataBinding(object sender, EventArgs e)
{
GridView grid = (GridView)sender;
grid.Columns[2].Visible = TaxHelper.ShowTaxColumn;
grid.Columns[2].HeaderText = TaxHelper.TaxColumnHeader;
}
}
protected void MarkPrinted_Click(object sender, EventArgs e)
{
IList<int> selectedOrders = GetSelectedOrders();
if ((selectedOrders == null) || (selectedOrders.Count == 0)) Response.Redirect("~/Admin/Orders/Default.aspx");
IList<Order> orders = GetOrders(selectedOrders.ToArray());
OrderStatus orderStatus = OrderStatusDataSource.Load(7);
foreach (Order order in orders)
order.UpdateOrderStatus(orderStatus);
}
}
and the top of my Invoices.ascx file:
Code: Select all
<%@ Page Language="C#" MasterPageFile="~/Admin/Admin.master" Inherits="AbleCommerce.Admin.Orders.Print.Invoices" Title="Invoices" CodeFile="Invoices.aspx.cs" %>
<%@ Register Src="OrderItemDetail.ascx" TagName="OrderItemDetail" TagPrefix="uc" %>
<%@ Register Src="~/Admin/UserControls/PrintableLogo.ascx" TagName="PrintableLogo" TagPrefix="uc" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
<div class="pageHeader noPrint">
<div class="caption">
<h1><asp:Localize ID="Caption" runat="server" Text="Invoices"></asp:Localize></h1>
</div>
</div>
<div class="content noPrint">
<p><asp:Label ID="OrderListLabel" runat="server" Text="Includes Order Numbers:" SkinID="FieldHeader"></asp:Label><asp:Label ID="OrderList" runat="server" Text=""></asp:Label></p>
<p><asp:Localize ID="PrintInstructions" runat="server" Text="This document includes a printable stylesheet. Your browser will print with appropriate styles and page breaks if needed. Website headers, footers, and this message will not be printed."></asp:Localize></p>
<asp:Button ID="Print" runat="server" Text="Print" OnClientClick="window.print();return true;" OnClick="MarkPrinted_Click" />
<asp:Button ID="Back" runat="server" Text="Back" OnClientClick="window.history.go(-1);return false;" />
</div>
The only changes that have been made are the two that you suggested.
Edit Website/Checkout/EditBillingAddress.aspx.cs file and locate following code
When I search the file, this code is not found.
I am running Gold V5 (VERSION: 7.0.8.5731)
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 7:01 pm
by mazhar
Brewhaus wrote:Mazhar,
That is where I had placed the code. Here is the bottom of my Invoices.ascx.cs file:
Code: Select all
protected void OrderItems_DataBinding(object sender, EventArgs e)
{
GridView grid = (GridView)sender;
grid.Columns[2].Visible = TaxHelper.ShowTaxColumn;
grid.Columns[2].HeaderText = TaxHelper.TaxColumnHeader;
}
}
protected void MarkPrinted_Click(object sender, EventArgs e)
{
IList<int> selectedOrders = GetSelectedOrders();
if ((selectedOrders == null) || (selectedOrders.Count == 0)) Response.Redirect("~/Admin/Orders/Default.aspx");
IList<Order> orders = GetOrders(selectedOrders.ToArray());
OrderStatus orderStatus = OrderStatusDataSource.Load(7);
foreach (Order order in orders)
order.UpdateOrderStatus(orderStatus);
}
}
and the top of my Invoices.ascx file:
Code: Select all
<%@ Page Language="C#" MasterPageFile="~/Admin/Admin.master" Inherits="AbleCommerce.Admin.Orders.Print.Invoices" Title="Invoices" CodeFile="Invoices.aspx.cs" %>
<%@ Register Src="OrderItemDetail.ascx" TagName="OrderItemDetail" TagPrefix="uc" %>
<%@ Register Src="~/Admin/UserControls/PrintableLogo.ascx" TagName="PrintableLogo" TagPrefix="uc" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
<div class="pageHeader noPrint">
<div class="caption">
<h1><asp:Localize ID="Caption" runat="server" Text="Invoices"></asp:Localize></h1>
</div>
</div>
<div class="content noPrint">
<p><asp:Label ID="OrderListLabel" runat="server" Text="Includes Order Numbers:" SkinID="FieldHeader"></asp:Label><asp:Label ID="OrderList" runat="server" Text=""></asp:Label></p>
<p><asp:Localize ID="PrintInstructions" runat="server" Text="This document includes a printable stylesheet. Your browser will print with appropriate styles and page breaks if needed. Website headers, footers, and this message will not be printed."></asp:Localize></p>
<asp:Button ID="Print" runat="server" Text="Print" OnClientClick="window.print();return true;" OnClick="MarkPrinted_Click" />
<asp:Button ID="Back" runat="server" Text="Back" OnClientClick="window.history.go(-1);return false;" />
</div>
The only changes that have been made are the two that you suggested.
Ohh sorry we need to place it above two last closing braces one closes the class and second the namespace. Move one closing brace thats just above your newly added method to the bottm so that at the end you have two closing braces.
Brewhaus wrote:
Edit Website/Checkout/EditBillingAddress.aspx.cs file and locate following code
When I search the file, this code is not found.
I am running Gold V5 (VERSION: 7.0.8.5731)
In EditBillingAddress.aspx.cs file look inside
InitAddressForm() method and try to find the above statement it should be there. If its not there then I am not sure why is so and that pretty much explains why you don't see Billing email address populated automatically. This functionality is there in Gold R5 out of the box.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 7:18 pm
by Brewhaus
Moving the code in Invoices.aspx.cs up by one line (before the last two }'s) fixed the issue. Thank you!
The section that you are referring to in EditBillinAddress.aspx.cs looks like this:
Code: Select all
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
InitAddressForm();
}
IntializeCreateAccountPanel();
IntializeShippingPanel();
IntializeEmailLists();
PasswordValidatorPanel.Controls.Clear();
}
The line:
BillToEmail.Text = address.Email;
is not there. The download says that it is GoldR5, build 5731
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 7:33 pm
by mazhar
No I was reffering to following method.
Code: Select all
protected void InitAddressForm()
{
Address address = AbleContext.Current.User.PrimaryAddress;
FirstName.Text = address.FirstName;
LastName.Text = address.LastName;
Address1.Text = address.Address1;
Address2.Text = address.Address2;
City.Text = address.City;
PostalCode.Text = address.PostalCode;
InitCountryAndProvince();
Company.Text = address.Company;
BillToEmail.Text = address.Email;
Telephone.Text = address.Phone;
Fax.Text = address.Fax;
IsBusinessAddress.Checked = !address.Residence;
AddressValidationPanel.Visible = _addressValidator != null;
}
compare yours with above code.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 7:48 pm
by Brewhaus
Is this supposed to be in Checkout/EditBillAddress.ascx.cs? The only instance of "InitAddressForm" that I have in that file is in the code that I showed above.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 8:14 pm
by mazhar
Yes this should be in Checkout/EditBillAddress.ascx.cs file.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 9:15 pm
by Brewhaus
Here is a copy and paste of my Checkout/EditBillAddress.ascx.cs file
Code: Select all
namespace AbleCommerce.Checkout
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommerceBuilder.Common;
using CommerceBuilder.Marketing;
using CommerceBuilder.Orders;
using CommerceBuilder.Services.Checkout;
using CommerceBuilder.Shipping;
using CommerceBuilder.Shipping.Providers;
using CommerceBuilder.Stores;
using CommerceBuilder.Users;
using CommerceBuilder.Utility;
public partial class EditBillAddress : CommerceBuilder.UI.AbleCommercePage
{
private StoreSettingsManager _settings;
private IAddressValidatorService _addressValidator = null;
public List<ValidAddress> ValidAddresses
{
get
{
return Session["VALID_ADDRESSES"] as List<ValidAddress>;
}
set
{
Session["VALID_ADDRESSES"] = value;
}
}
protected void Page_Init(object sender, EventArgs e)
{
_settings = AbleContext.Current.Store.Settings;
if (AbleContext.Current.User.Basket.Items.Count == 0)
Response.Redirect(AbleCommerce.Code.NavigationHelper.GetBasketUrl());
_addressValidator = AddressValidatorServiceLocator.Locate();
Country.DataSource = CountryDataSource.LoadAll();
Country.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
InitAddressForm();
}
IntializeCreateAccountPanel();
IntializeShippingPanel();
IntializeEmailLists();
PasswordValidatorPanel.Controls.Clear();
}
protected void BillingPageContinue_Click(Object sender, EventArgs e)
{
if (Page.IsValid)
{
// NEED TO REGISTER USER
if (AbleContext.Current.User.IsAnonymous)
{
if (CreateNewAccountPanel.Visible)
{
if (!CreateNewAccount()) return;
}
else
{
// ANONYMOUS USER SELECTING GUEST CHECKOUT, CREATE TEMPORARY ACCOUNT
User oldUser = AbleContext.Current.User;
string newUserName = "zz_anonymous_" + Guid.NewGuid().ToString("N") + "@domain.xyz";
string newEmail = StringHelper.StripHtml(BillToEmail.Text);
string newPassword = Guid.NewGuid().ToString("N");
MembershipCreateStatus createStatus;
User newUser = UserDataSource.CreateUser(newUserName, newEmail, newPassword, string.Empty, string.Empty, true, 0, out createStatus);
// IF THE CREATE FAILS, IGNORE AND CONTINUE CREATING THE ORDER
if (createStatus == MembershipCreateStatus.Success)
{
// CHANGE THE NAME AND EMAIL TO SOMETHING MORE FRIENDLY THAN GUID
newUser.UserName = "zz_anonymous_" + newUser.Id.ToString() + "@domain.xyz";
newUser.Save();
CommerceBuilder.Users.User.Migrate(oldUser, newUser, true, true);
AbleContext.Current.User = newUser;
FormsAuthentication.SetAuthCookie(newUser.UserName, false);
}
}
}
// MAILING LIST SIGNUP
if (EmailLists.Visible && EmailLists.Items.Count > 0)
{
string email = AbleContext.Current.User.Email;
int listIndex = 0;
IList<EmailList> emailLists = GetPublicEmailLists();
if (emailLists != null && emailLists.Count > 0)
{
foreach (ListViewDataItem item in EmailLists.Items)
{
EmailList list = emailLists[listIndex];
CheckBox selected = (CheckBox)item.FindControl("Selected");
if (selected != null)
{
if (selected.Checked)
list.ProcessSignupRequest(email);
else
list.RemoveMember(email);
}
else list.RemoveMember(email);
listIndex++;
}
}
}
string provinceName = string.Empty;
if (ValidateProvince(out provinceName))
{
Address address = AbleContext.Current.User.PrimaryAddress;
string address1 = StringHelper.StripHtml(Address1.Text);
string address2 = StringHelper.StripHtml(Address2.Text);
string city = StringHelper.StripHtml(City.Text);
string postColde = StringHelper.StripHtml(PostalCode.Text);
if (address.Address1 != address1 || address.Address2 != address2 || address.City != city || address.Province != provinceName || address.PostalCode != postColde)
address.Validated = false;
address.FirstName = StringHelper.StripHtml(FirstName.Text);
address.LastName = StringHelper.StripHtml(LastName.Text);
address.Address1 = address1;
address.Address2 = address2;
address.Company = StringHelper.StripHtml(Company.Text);
address.Email = CreateNewAccountPanel.Visible ? StringHelper.StripHtml(UserName.Text) : StringHelper.StripHtml(BillToEmail.Text);
address.City = city;
address.Province = provinceName;
address.PostalCode = postColde;
address.CountryCode = Country.SelectedValue;
address.Phone = StringHelper.StripHtml(Telephone.Text);
address.Fax = StringHelper.StripHtml(Fax.Text);
address.Residence = !IsBusinessAddress.Checked;
address.Save();
if (!address.Validated && _addressValidator != null)
{
AddressValidationResponse avr = _addressValidator.ValidateAddress(address);
if(avr != null)
{
if (!avr.IsValid.HasValue || !avr.IsValid.Value)
{
ValidAddresses = avr.Addresses;
if (ValidAddresses != null)
{
int index = 0;
foreach (ValidAddress validAddress in ValidAddresses)
{
validAddress.Id = ++index;
}
ValidAddressesList.DataSource = ValidAddresses;
ValidAddressesList.DataBind();
ValidAddressesPanel.Visible = true;
ValidAddressesList.Items.Add(new ListItem("Use the address exactly as I entered it", "0"));
ValidAddressesList.Items[0].Selected = true;
if (ValidAddressesList.Items.Count > 1)
{
PHAddressFound.Visible = true;
PHNoAddress.Visible = false;
}
else
{
PHAddressFound.Visible = false;
PHNoAddress.Visible = true;
}
return;
}
}
}
}
}
else
{
Province2Invalid.IsValid = false;
UpdateCountry();
}
GoToNextPage();
}
}
protected void GoToNextPage()
{
string nextPageUrl = "Payment.aspx";
if (ShippingAddressPanel.Visible)
{
switch (ShipToOption.SelectedValue)
{
case "SHIP_TO_BILLING_ADDRESS":
// need to ensure all items are going to the billing address
Basket basket = AbleContext.Current.User.Basket;
IBasketService preCheckoutService = AbleContext.Resolve<IBasketService>();
preCheckoutService.Package(basket, true);
nextPageUrl = "ShipMethod.aspx";
break;
case "SHIP_TO_ADDRESS":
nextPageUrl = "ShipAddress.aspx";
break;
case "SHIP_TO_MULTIPLE_ADDRESSES":
nextPageUrl = "ShipAddresses.aspx";
break;
}
}
Response.Redirect(nextPageUrl);
}
protected void UseValidAddressButton_Click(object sender, EventArgs e)
{
if (ValidAddresses != null)
{
Address address = AbleContext.Current.User.PrimaryAddress;
int id = AlwaysConvert.ToInt(ValidAddressesList.SelectedValue);
if (id == 0)
{
address.Validated = true;
address.Save();
}
else
{
ValidAddress validAddress = (from va in ValidAddresses where va.Id == id select va).SingleOrDefault();
if (validAddress != null)
{
address.Address1 = validAddress.Address1;
address.Address2 = validAddress.Address2;
address.City = validAddress.City;
address.Province = validAddress.Province;
address.PostalCode = validAddress.PostalCode;
address.CountryCode = Country.SelectedValue;
address.Validated = true;
address.Save();
}
}
}
ValidAddresses = null;
GoToNextPage();
}
protected void CancelValidAddressButton_Click(Object sender, EventArgs e)
{
ValidAddresses = null;
ValidAddressesList.Items.Clear();
ValidAddressesPanel.Visible = false;
}
#region SHIPPING
protected void IntializeShippingPanel()
{
bool hasShippableProducts = AbleContext.Current.User.Basket.Items.HasShippableProducts();
bool allowsMultipleShipments = AbleContext.Current.User.Basket.Items.ShippableProductCount() > 1 && !AbleContext.Current.User.IsAnonymous;
// IF THERE IS ATLEAST ONE SHIPPABLE PRODUCT THEN SHOW SHIPPING PANEL OTHERWISE HIDE IT
if (hasShippableProducts)
{
ShippingAddressPanel.Visible = true;
// IF MULTIPLE SHIPMENT OPTION IS NOT ALLOWED THEN REMOVE IT
if (!allowsMultipleShipments)
{
ListItem item = ShipToOption.Items.FindByValue("SHIP_TO_MULTIPLE_ADDRESSES");
if (item != null)
ShipToOption.Items.Remove(item);
}
NoShipmentPanel.Visible = false;
}
else
{
ShippingAddressPanel.Visible = false;
NoShipmentPanel.Visible = true;
}
}
#endregion
#region NEW ACCOUNT
protected void IntializeCreateAccountPanel()
{
bool showCreateAccount = false;
if (_settings.AllowAnonymousCheckout && AbleContext.Current.User.IsAnonymous)
{
if (Request.QueryString["GC"] == "0")
showCreateAccount = false;
else
showCreateAccount = true;
}
else
if (!_settings.AllowAnonymousCheckout && AbleContext.Current.User.IsAnonymous)
{
showCreateAccount = true;
}
// SHOW ACCOUNT PANEL ONLY IF REQUIRED
if (showCreateAccount)
{
ShowPasswordPolicy();
CreateNewAccountPanel.Visible = true;
trEmail.Visible = false;
}
else
{
CreateNewAccountPanel.Visible = false;
}
}
protected bool CreateNewAccount()
{
bool result = false;
if (Page.IsValid && ValidatePassword())
{
if ((!trCaptchaField.Visible) || CaptchaImage.Authenticate(CaptchaInput.Text))
{
// PERFORM CUSTOM VALIDATION TO ENSURE EMAIL IS NOT ALREADY REGISTERED
string userName = UserName.Text.Trim();
int userIde = UserDataSource.GetUserIdByEmail(userName);
int userIdu = UserDataSource.GetUserIdByUserName(userName);
if (userIde == 0 && userIdu == 0)
{
// NO USER REGISTERED WITH THAT USERNAME OR EMAIL
MembershipCreateStatus status;
User newUser = UserDataSource.CreateUser(userName, userName, Password.Text, string.Empty, string.Empty, true, 0, out status);
if (status == MembershipCreateStatus.Success)
{
// WE HAVE TO VALIDATE CREDENTIALS SO A MODIFIED FORM POST CANNOT ACCESS THIS CODE
if (Membership.ValidateUser(userName, Password.Text))
{
// SET A DEFAULT BILLING ADDRESS FOR THE USER
newUser.PrimaryAddress.Email = userName;
newUser.PrimaryAddress.CountryCode = AbleContext.Current.Store.DefaultWarehouse.CountryCode;
newUser.PrimaryAddress.Residence = true;
newUser.Save();
// MIGRATE ACTIVE USER TO NEW ACCOUNT
CommerceBuilder.Users.User.Migrate(AbleContext.Current.User, newUser, false, true);
AbleContext.Current.User = newUser;
FormsAuthentication.SetAuthCookie(userName, false);
result = true;
}
}
else
{
InvalidRegistration.IsValid = false;
switch (status)
{
case MembershipCreateStatus.DuplicateUserName:
case MembershipCreateStatus.DuplicateEmail:
InvalidRegistration.ErrorMessage = "The user-name you have provided is already registered. Sign in to access your account.";
break;
case MembershipCreateStatus.InvalidEmail:
InvalidRegistration.ErrorMessage = "The email address you have provided is not valid.";
break;
case MembershipCreateStatus.InvalidUserName:
InvalidRegistration.ErrorMessage = "The user-name you have provided is not valid.";
break;
case MembershipCreateStatus.InvalidPassword:
InvalidRegistration.ErrorMessage = "The password you have provided is not valid.";
break;
default:
InvalidRegistration.ErrorMessage = "Unexpected error in registration (" + status.ToString() + ")";
break;
}
}
}
else
{
DuplicateEmailValidator.IsValid = false;
}
}
else
{
//CAPTCHA IS VISIBLE AND DID NOT AUTHENTICATE
CustomValidator invalidInput = new CustomValidator();
invalidInput.Text = "*";
invalidInput.ErrorMessage = "You did not input the verification number correctly.";
invalidInput.IsValid = false;
phCaptchaValidators.Controls.Add(invalidInput);
CaptchaInput.Text = "";
Password.Attributes.Add("value", string.Empty);
RefreshCaptcha();
}
}
return result;
}
private bool _PasswordLengthValidatorAdded = false;
private void ShowPasswordPolicy()
{
//SHOW THE PASSWORD POLICY
CustomerPasswordPolicy policy = new CustomerPasswordPolicy();
if (policy.MinLength > 0)
{
PasswordPolicyLength.Text = string.Format(PasswordPolicyLength.Text, policy.MinLength);
if (!_PasswordLengthValidatorAdded)
{
RegularExpressionValidator PasswordLengthValidator = new RegularExpressionValidator();
PasswordLengthValidator.ID = "PasswordLengthValidator";
PasswordLengthValidator.EnableViewState = false;
PasswordLengthValidator.ControlToValidate = "Password";
PasswordLengthValidator.Text = "*";
PasswordLengthValidator.ErrorMessage = "Password must be at least " + policy.MinLength.ToString() + " characters.";
PasswordLengthValidator.ValidationExpression = ".{" + policy.MinLength.ToString() + ",}";
PasswordLengthValidator.SetFocusOnError = false;
PasswordLengthValidator.EnableClientScript = false;
PasswordValidatorPanel.Controls.Add(PasswordLengthValidator);
_PasswordLengthValidatorAdded = true;
}
}
else PasswordPolicyLength.Visible = false;
List<string> requirements = new List<string>();
if (policy.RequireUpper) requirements.Add("uppercase letter");
if (policy.RequireLower) requirements.Add("lowercase letter");
if (policy.RequireNumber) requirements.Add("number");
if (policy.RequireSymbol) requirements.Add("symbol");
if (!policy.RequireNumber && !policy.RequireSymbol && policy.RequireNonAlpha) requirements.Add("non-letter");
PasswordPolicyRequired.Visible = (requirements.Count > 0);
if (PasswordPolicyRequired.Visible)
{
if (requirements.Count > 1) requirements[requirements.Count - 1] = "and " + requirements[requirements.Count - 1];
PasswordPolicyRequired.Text = string.Format(PasswordPolicyRequired.Text, string.Join(", ", requirements.ToArray()));
}
// SHOW THE REGISTRATION CAPTCHA IF CUSTOMER POLICY INDICATES IT
trCaptchaField.Visible = policy.ImageCaptcha;
trCaptchaImage.Visible = policy.ImageCaptcha;
}
private bool ValidatePassword()
{
//VALIDATE PASSWORD POLICY
CustomerPasswordPolicy policy = new CustomerPasswordPolicy();
if (!policy.TestPassword(null, Password.Text))
{
CustomValidator policyValidator = new CustomValidator();
policyValidator.ControlToValidate = "Password";
policyValidator.IsValid = false;
policyValidator.Text = "*";
policyValidator.ErrorMessage = "The password does not meet the minimum requirements.";
policyValidator.SetFocusOnError = false;
PasswordValidatorPanel.Controls.Add(policyValidator);
return false;
}
return true;
}
protected void ChangeImageLink_Click(object sender, EventArgs e)
{
RefreshCaptcha();
Password.Attributes.Add("value", Password.Text);
}
private void RefreshCaptcha()
{
CaptchaImage.ChallengeText = StringHelper.RandomNumber(6);
}
#endregion
#region EMAIL LISTS
private void IntializeEmailLists()
{
if (!Page.IsPostBack)
{
if (!AbleContext.Current.User.IsAnonymous || CreateNewAccountPanel.Visible)
{
EmailLists.DataSource = GetPublicEmailLists();
EmailLists.DataBind();
}
else
{
EmailLists.Visible = false;
}
}
}
private IList<EmailList> GetPublicEmailLists()
{
IList<EmailList> emailLists = new List<EmailList>();
IList<EmailList> allLists = EmailListDataSource.LoadAll("Name");
foreach (EmailList list in allLists)
{
if (list.IsPublic)
emailLists.Add(list);
}
return emailLists;
}
protected bool IsEmailListChecked(object dataItem)
{
User user = AbleContext.Current.User;
if (user.IsAnonymous) return true;
EmailList list = (EmailList)dataItem;
return (list.IsMember(user.Email));
}
#endregion
#region BILLING ADDRESS
protected void InitAddressForm()
{
Address address = AbleContext.Current.User.PrimaryAddress;
FirstName.Text = address.FirstName;
LastName.Text = address.LastName;
Address1.Text = address.Address1;
Address2.Text = address.Address2;
City.Text = address.City;
PostalCode.Text = address.PostalCode;
InitCountryAndProvince();
Company.Text = address.Company;
BillToEmail.Text = address.Email;
Telephone.Text = address.Phone;
Fax.Text = address.Fax;
IsBusinessAddress.Checked = !address.Residence;
AddressValidationPanel.Visible = _addressValidator != null;
}
private void InitCountryAndProvince()
{
//MAKE SURE THE CORRECT ADDRESS IS SELECTED
Address address = AbleContext.Current.User.PrimaryAddress;
bool foundCountry = false;
if (!string.IsNullOrEmpty(address.CountryCode))
{
ListItem selectedCountry = Country.Items.FindByValue(address.CountryCode);
if (selectedCountry != null)
{
Country.SelectedIndex = Country.Items.IndexOf(selectedCountry);
foundCountry = true;
}
}
if (!foundCountry)
{
Warehouse defaultWarehouse = AbleContext.Current.Store.DefaultWarehouse;
ListItem selectedCountry = Country.Items.FindByValue(defaultWarehouse.CountryCode);
if (selectedCountry != null) Country.SelectedIndex = Country.Items.IndexOf(selectedCountry);
}
//MAKE SURE THE PROVINCE LIST IS CORRECT FOR THE COUNTRY
UpdateCountry();
//NOW LOOK FOR THE PROVINCE TO SET
if (Province.Visible) Province.Text = address.Province;
else
{
ListItem selectedProvince = Province2.Items.FindByValue(address.Province);
if (selectedProvince != null) Province2.SelectedIndex = Province2.Items.IndexOf(selectedProvince);
}
}
/// <summary>
/// Validates the current province value
/// </summary>
/// <returns></returns>
private bool ValidateProvince(out string provinceName)
{
provinceName = (Province.Visible ? StringHelper.StripHtml(Province.Text) : Province2.SelectedValue);
string countryCode = Country.SelectedValue;
if (ProvinceDataSource.CountForCountry(countryCode) == 0) return true;
//CHECK THE VALUE
int provinceId = ProvinceDataSource.GetProvinceIdByName(countryCode, provinceName);
if (provinceId > 0)
{
//UPDATE VALUE
Province p = ProvinceDataSource.Load(provinceId);
if (p.ProvinceCode.Length > 0) provinceName = p.ProvinceCode;
else provinceName = p.Name;
}
return (provinceId > 0);
}
private void UpdateCountry()
{
//SEE WHETHER POSTAL CODE IS REQUIRED
string[] countries = AbleContext.Current.Store.Settings.PostalCodeCountries.Split(",".ToCharArray());
PostalCodeRequired.Enabled = (Array.IndexOf(countries, Country.SelectedValue) > -1);
PostalCodeRequiredLabel.Visible = PostalCodeRequired.Enabled;
//SEE WHETHER PROVINCE LIST IS DEFINED
IList<Province> provinces = ProvinceDataSource.LoadForCountry(Country.SelectedValue);
if (provinces.Count > 0)
{
Province.Visible = false;
Province2.Visible = true;
Province2.Items.Clear();
Province2.Items.Add(string.Empty);
foreach (Province province in provinces)
{
string provinceValue = (!string.IsNullOrEmpty(province.ProvinceCode) ? province.ProvinceCode : province.Name);
Province2.Items.Add(new ListItem(province.Name, provinceValue));
}
ListItem selectedProvince = FindSelectedProvince();
if (selectedProvince != null) selectedProvince.Selected = true;
Province2Required.Enabled = true;
Province.Text = string.Empty;
}
else
{
Province.Visible = true;
Province2.Visible = false;
Province2.Items.Clear();
Province2Required.Enabled = false;
}
}
/// <summary>
/// Obtains the province that should default to selected in the drop down list
/// </summary>
/// <returns>The province that should default to selected in the drop down list</returns>
private ListItem FindSelectedProvince()
{
string defaultValue = Province.Text;
if (string.IsNullOrEmpty(defaultValue)) defaultValue = Request.Form[Province2.UniqueID];
if (string.IsNullOrEmpty(defaultValue)) return null;
defaultValue = defaultValue.ToUpperInvariant();
foreach (ListItem item in Province2.Items)
{
string itemText = item.Text.ToUpperInvariant();
string itemValue = item.Value.ToUpperInvariant();
if (itemText == defaultValue || itemValue == defaultValue) return item;
}
return null;
}
protected void Country_Changed(object sender, EventArgs e)
{
//UPDATE THE FORM FOR THE NEW COUNTRY
UpdateCountry();
}
#endregion
}
}
Just to be sure that I had not changed something and forgotten, I copied the file from the GoldR5 download. The file properties show it to be from 04/30/13, if that helps.
Re: Customizations in Gold
Posted: Tue Jul 16, 2013 9:34 pm
by ForumsAdmin
I can see that 'BillToEmail.Text = address.Email;" line is there in the code you have posted. Why are you not able to find it? It is in InitAddressForm() method.
Re: Customizations in Gold
Posted: Wed Jul 17, 2013 8:03 am
by Brewhaus
I had copied the code that Mazhar had posted:
Edit Website/Checkout/EditBillingAddress.aspx.cs file and locate following code
but there was a bracket missing in the code above. It is actually ...BillToEmail.Text);
Hence it could not be found on a 'find' routine.
Is it this line that we need to change
Code: Select all
address.Email = CreateNewAccountPanel.Visible ? StringHelper.StripHtml(UserName.Text) : StringHelper.StripHtml(BillToEmail.Text);
to
Code: Select all
address.Email = CreateNewAccountPanel.Visible ? StringHelper.StripHtml(UserName.Text) : StringHelper.StripHtml(BillToEmail.Text = string.IsNullOrEmpty(address.Email) ? AbleContext.Current.User.Email : address.Email);
If so, unfortunately, it did not work (ie. when we add items to the cart and then log in with an existing account, the e-mail address field is still blank).
Re: Customizations in Gold
Posted: Fri Jul 19, 2013 1:37 pm
by Brewhaus
Can anyone help further with this?
Re: Customizations in Gold
Posted: Fri Jul 19, 2013 1:50 pm
by jguengerich
I think you are still putting it at the wrong place. Look for this area of the file:
Code: Select all
#region BILLING ADDRESS
protected void InitAddressForm()
{
Address address = AbleContext.Current.User.PrimaryAddress;
FirstName.Text = address.FirstName;
LastName.Text = address.LastName;
Address1.Text = address.Address1;
Address2.Text = address.Address2;
City.Text = address.City;
PostalCode.Text = address.PostalCode;
InitCountryAndProvince();
Company.Text = address.Company;
BillToEmail.Text = address.Email;
Telephone.Text = address.Phone;
Fax.Text = address.Fax;
IsBusinessAddress.Checked = !address.Residence;
AddressValidationPanel.Visible = _addressValidator != null;
}
The 10th line inside the curly braces ({ }) is the line that needs to be changed.
Re: Customizations in Gold
Posted: Fri Jul 19, 2013 2:15 pm
by Brewhaus
I just tried running a 'find' for several pieces of the code that you listed ("Billing Address", "InitAddressForm", "BillToEmail"). The only spot that I could even find address.email is the following line
Code: Select all
address.Email = CreateNewAccountPanel.Visible ? StringHelper.StripHtml(UserName.Text) : StringHelper.StripHtml(BillToEmail.Text);
My entire EditBillAddress.ascx.cs file is below
Code: Select all
namespace AbleCommerce.Checkout
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using CommerceBuilder.Common;
using CommerceBuilder.Marketing;
using CommerceBuilder.Orders;
using CommerceBuilder.Services.Checkout;
using CommerceBuilder.Shipping;
using CommerceBuilder.Shipping.Providers;
using CommerceBuilder.Stores;
using CommerceBuilder.Users;
using CommerceBuilder.Utility;
public partial class EditBillAddress : CommerceBuilder.UI.AbleCommercePage
{
private StoreSettingsManager _settings;
private IAddressValidatorService _addressValidator = null;
public List<ValidAddress> ValidAddresses
{
get
{
return Session["VALID_ADDRESSES"] as List<ValidAddress>;
}
set
{
Session["VALID_ADDRESSES"] = value;
}
}
protected void Page_Init(object sender, EventArgs e)
{
_settings = AbleContext.Current.Store.Settings;
if (AbleContext.Current.User.Basket.Items.Count == 0)
Response.Redirect(AbleCommerce.Code.NavigationHelper.GetBasketUrl());
_addressValidator = AddressValidatorServiceLocator.Locate();
Country.DataSource = CountryDataSource.LoadAll();
Country.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
InitAddressForm();
}
IntializeCreateAccountPanel();
IntializeShippingPanel();
IntializeEmailLists();
PasswordValidatorPanel.Controls.Clear();
}
protected void BillingPageContinue_Click(Object sender, EventArgs e)
{
if (Page.IsValid)
{
// NEED TO REGISTER USER
if (AbleContext.Current.User.IsAnonymous)
{
if (CreateNewAccountPanel.Visible)
{
if (!CreateNewAccount()) return;
}
else
{
// ANONYMOUS USER SELECTING GUEST CHECKOUT, CREATE TEMPORARY ACCOUNT
User oldUser = AbleContext.Current.User;
string newUserName = "zz_anonymous_" + Guid.NewGuid().ToString("N") + "@domain.xyz";
string newEmail = StringHelper.StripHtml(BillToEmail.Text);
string newPassword = Guid.NewGuid().ToString("N");
MembershipCreateStatus createStatus;
User newUser = UserDataSource.CreateUser(newUserName, newEmail, newPassword, string.Empty, string.Empty, true, 0, out createStatus);
// IF THE CREATE FAILS, IGNORE AND CONTINUE CREATING THE ORDER
if (createStatus == MembershipCreateStatus.Success)
{
// CHANGE THE NAME AND EMAIL TO SOMETHING MORE FRIENDLY THAN GUID
newUser.UserName = "zz_anonymous_" + newUser.Id.ToString() + "@domain.xyz";
newUser.Save();
CommerceBuilder.Users.User.Migrate(oldUser, newUser, true, true);
AbleContext.Current.User = newUser;
FormsAuthentication.SetAuthCookie(newUser.UserName, false);
}
}
}
// MAILING LIST SIGNUP
if (EmailLists.Visible && EmailLists.Items.Count > 0)
{
string email = AbleContext.Current.User.Email;
int listIndex = 0;
IList<EmailList> emailLists = GetPublicEmailLists();
if (emailLists != null && emailLists.Count > 0)
{
foreach (ListViewDataItem item in EmailLists.Items)
{
EmailList list = emailLists[listIndex];
CheckBox selected = (CheckBox)item.FindControl("Selected");
if (selected != null)
{
if (selected.Checked)
list.ProcessSignupRequest(email);
else
list.RemoveMember(email);
}
else list.RemoveMember(email);
listIndex++;
}
}
}
string provinceName = string.Empty;
if (ValidateProvince(out provinceName))
{
Address address = AbleContext.Current.User.PrimaryAddress;
string address1 = StringHelper.StripHtml(Address1.Text);
string address2 = StringHelper.StripHtml(Address2.Text);
string city = StringHelper.StripHtml(City.Text);
string postColde = StringHelper.StripHtml(PostalCode.Text);
if (address.Address1 != address1 || address.Address2 != address2 || address.City != city || address.Province != provinceName || address.PostalCode != postColde)
address.Validated = false;
address.FirstName = StringHelper.StripHtml(FirstName.Text);
address.LastName = StringHelper.StripHtml(LastName.Text);
address.Address1 = address1;
address.Address2 = address2;
address.Company = StringHelper.StripHtml(Company.Text);
address.Email = CreateNewAccountPanel.Visible ? StringHelper.StripHtml(UserName.Text) : StringHelper.StripHtml(BillToEmail.Text);
address.City = city;
address.Province = provinceName;
address.PostalCode = postColde;
address.CountryCode = Country.SelectedValue;
address.Phone = StringHelper.StripHtml(Telephone.Text);
address.Fax = StringHelper.StripHtml(Fax.Text);
address.Residence = !IsBusinessAddress.Checked;
address.Save();
if (!address.Validated && _addressValidator != null)
{
AddressValidationResponse avr = _addressValidator.ValidateAddress(address);
if(avr != null)
{
if (!avr.IsValid.HasValue || !avr.IsValid.Value)
{
ValidAddresses = avr.Addresses;
if (ValidAddresses != null)
{
int index = 0;
foreach (ValidAddress validAddress in ValidAddresses)
{
validAddress.Id = ++index;
}
ValidAddressesList.DataSource = ValidAddresses;
ValidAddressesList.DataBind();
ValidAddressesPanel.Visible = true;
ValidAddressesList.Items.Add(new ListItem("Use the address exactly as I entered it", "0"));
ValidAddressesList.Items[0].Selected = true;
if (ValidAddressesList.Items.Count > 1)
{
PHAddressFound.Visible = true;
PHNoAddress.Visible = false;
}
else
{
PHAddressFound.Visible = false;
PHNoAddress.Visible = true;
}
return;
}
}
}
}
}
else
{
Province2Invalid.IsValid = false;
UpdateCountry();
}
GoToNextPage();
}
}
protected void GoToNextPage()
{
string nextPageUrl = "Payment.aspx";
if (ShippingAddressPanel.Visible)
{
switch (ShipToOption.SelectedValue)
{
case "SHIP_TO_BILLING_ADDRESS":
// need to ensure all items are going to the billing address
Basket basket = AbleContext.Current.User.Basket;
IBasketService preCheckoutService = AbleContext.Resolve<IBasketService>();
preCheckoutService.Package(basket, true);
nextPageUrl = "ShipMethod.aspx";
break;
case "SHIP_TO_ADDRESS":
nextPageUrl = "ShipAddress.aspx";
break;
case "SHIP_TO_MULTIPLE_ADDRESSES":
nextPageUrl = "ShipAddresses.aspx";
break;
}
}
Response.Redirect(nextPageUrl);
}
protected void UseValidAddressButton_Click(object sender, EventArgs e)
{
if (ValidAddresses != null)
{
Address address = AbleContext.Current.User.PrimaryAddress;
int id = AlwaysConvert.ToInt(ValidAddressesList.SelectedValue);
if (id == 0)
{
address.Validated = true;
address.Save();
}
else
{
ValidAddress validAddress = (from va in ValidAddresses where va.Id == id select va).SingleOrDefault();
if (validAddress != null)
{
address.Address1 = validAddress.Address1;
address.Address2 = validAddress.Address2;
address.City = validAddress.City;
address.Province = validAddress.Province;
address.PostalCode = validAddress.PostalCode;
address.CountryCode = Country.SelectedValue;
address.Validated = true;
address.Save();
}
}
}
ValidAddresses = null;
GoToNextPage();
}
protected void CancelValidAddressButton_Click(Object sender, EventArgs e)
{
ValidAddresses = null;
ValidAddressesList.Items.Clear();
ValidAddressesPanel.Visible = false;
}
#region SHIPPING
protected void IntializeShippingPanel()
{
bool hasShippableProducts = AbleContext.Current.User.Basket.Items.HasShippableProducts();
bool allowsMultipleShipments = AbleContext.Current.User.Basket.Items.ShippableProductCount() > 1 && !AbleContext.Current.User.IsAnonymous;
// IF THERE IS ATLEAST ONE SHIPPABLE PRODUCT THEN SHOW SHIPPING PANEL OTHERWISE HIDE IT
if (hasShippableProducts)
{
ShippingAddressPanel.Visible = true;
// IF MULTIPLE SHIPMENT OPTION IS NOT ALLOWED THEN REMOVE IT
if (!allowsMultipleShipments)
{
ListItem item = ShipToOption.Items.FindByValue("SHIP_TO_MULTIPLE_ADDRESSES");
if (item != null)
ShipToOption.Items.Remove(item);
}
NoShipmentPanel.Visible = false;
}
else
{
ShippingAddressPanel.Visible = false;
NoShipmentPanel.Visible = true;
}
}
#endregion
#region NEW ACCOUNT
protected void IntializeCreateAccountPanel()
{
bool showCreateAccount = false;
if (_settings.AllowAnonymousCheckout && AbleContext.Current.User.IsAnonymous)
{
if (Request.QueryString["GC"] == "0")
showCreateAccount = false;
else
showCreateAccount = true;
}
else
if (!_settings.AllowAnonymousCheckout && AbleContext.Current.User.IsAnonymous)
{
showCreateAccount = true;
}
// SHOW ACCOUNT PANEL ONLY IF REQUIRED
if (showCreateAccount)
{
ShowPasswordPolicy();
CreateNewAccountPanel.Visible = true;
trEmail.Visible = false;
}
else
{
CreateNewAccountPanel.Visible = false;
}
}
protected bool CreateNewAccount()
{
bool result = false;
if (Page.IsValid && ValidatePassword())
{
if ((!trCaptchaField.Visible) || CaptchaImage.Authenticate(CaptchaInput.Text))
{
// PERFORM CUSTOM VALIDATION TO ENSURE EMAIL IS NOT ALREADY REGISTERED
string userName = UserName.Text.Trim();
int userIde = UserDataSource.GetUserIdByEmail(userName);
int userIdu = UserDataSource.GetUserIdByUserName(userName);
if (userIde == 0 && userIdu == 0)
{
// NO USER REGISTERED WITH THAT USERNAME OR EMAIL
MembershipCreateStatus status;
User newUser = UserDataSource.CreateUser(userName, userName, Password.Text, string.Empty, string.Empty, true, 0, out status);
if (status == MembershipCreateStatus.Success)
{
// WE HAVE TO VALIDATE CREDENTIALS SO A MODIFIED FORM POST CANNOT ACCESS THIS CODE
if (Membership.ValidateUser(userName, Password.Text))
{
// SET A DEFAULT BILLING ADDRESS FOR THE USER
newUser.PrimaryAddress.Email = userName;
newUser.PrimaryAddress.CountryCode = AbleContext.Current.Store.DefaultWarehouse.CountryCode;
newUser.PrimaryAddress.Residence = true;
newUser.Save();
// MIGRATE ACTIVE USER TO NEW ACCOUNT
CommerceBuilder.Users.User.Migrate(AbleContext.Current.User, newUser, false, true);
AbleContext.Current.User = newUser;
FormsAuthentication.SetAuthCookie(userName, false);
result = true;
}
}
else
{
InvalidRegistration.IsValid = false;
switch (status)
{
case MembershipCreateStatus.DuplicateUserName:
case MembershipCreateStatus.DuplicateEmail:
InvalidRegistration.ErrorMessage = "The user-name you have provided is already registered. Sign in to access your account.";
break;
case MembershipCreateStatus.InvalidEmail:
InvalidRegistration.ErrorMessage = "The email address you have provided is not valid.";
break;
case MembershipCreateStatus.InvalidUserName:
InvalidRegistration.ErrorMessage = "The user-name you have provided is not valid.";
break;
case MembershipCreateStatus.InvalidPassword:
InvalidRegistration.ErrorMessage = "The password you have provided is not valid.";
break;
default:
InvalidRegistration.ErrorMessage = "Unexpected error in registration (" + status.ToString() + ")";
break;
}
}
}
else
{
DuplicateEmailValidator.IsValid = false;
}
}
else
{
//CAPTCHA IS VISIBLE AND DID NOT AUTHENTICATE
CustomValidator invalidInput = new CustomValidator();
invalidInput.Text = "*";
invalidInput.ErrorMessage = "You did not input the verification number correctly.";
invalidInput.IsValid = false;
phCaptchaValidators.Controls.Add(invalidInput);
CaptchaInput.Text = "";
Password.Attributes.Add("value", string.Empty);
RefreshCaptcha();
}
}
return result;
}
private bool _PasswordLengthValidatorAdded = false;
private void ShowPasswordPolicy()
{
//SHOW THE PASSWORD POLICY
CustomerPasswordPolicy policy = new CustomerPasswordPolicy();
if (policy.MinLength > 0)
{
PasswordPolicyLength.Text = string.Format(PasswordPolicyLength.Text, policy.MinLength);
if (!_PasswordLengthValidatorAdded)
{
RegularExpressionValidator PasswordLengthValidator = new RegularExpressionValidator();
PasswordLengthValidator.ID = "PasswordLengthValidator";
PasswordLengthValidator.EnableViewState = false;
PasswordLengthValidator.ControlToValidate = "Password";
PasswordLengthValidator.Text = "*";
PasswordLengthValidator.ErrorMessage = "Password must be at least " + policy.MinLength.ToString() + " characters.";
PasswordLengthValidator.ValidationExpression = ".{" + policy.MinLength.ToString() + ",}";
PasswordLengthValidator.SetFocusOnError = false;
PasswordLengthValidator.EnableClientScript = false;
PasswordValidatorPanel.Controls.Add(PasswordLengthValidator);
_PasswordLengthValidatorAdded = true;
}
}
else PasswordPolicyLength.Visible = false;
List<string> requirements = new List<string>();
if (policy.RequireUpper) requirements.Add("uppercase letter");
if (policy.RequireLower) requirements.Add("lowercase letter");
if (policy.RequireNumber) requirements.Add("number");
if (policy.RequireSymbol) requirements.Add("symbol");
if (!policy.RequireNumber && !policy.RequireSymbol && policy.RequireNonAlpha) requirements.Add("non-letter");
PasswordPolicyRequired.Visible = (requirements.Count > 0);
if (PasswordPolicyRequired.Visible)
{
if (requirements.Count > 1) requirements[requirements.Count - 1] = "and " + requirements[requirements.Count - 1];
PasswordPolicyRequired.Text = string.Format(PasswordPolicyRequired.Text, string.Join(", ", requirements.ToArray()));
}
// SHOW THE REGISTRATION CAPTCHA IF CUSTOMER POLICY INDICATES IT
trCaptchaField.Visible = policy.ImageCaptcha;
trCaptchaImage.Visible = policy.ImageCaptcha;
}
private bool ValidatePassword()
{
//VALIDATE PASSWORD POLICY
CustomerPasswordPolicy policy = new CustomerPasswordPolicy();
if (!policy.TestPassword(null, Password.Text))
{
CustomValidator policyValidator = new CustomValidator();
policyValidator.ControlToValidate = "Password";
policyValidator.IsValid = false;
policyValidator.Text = "*";
policyValidator.ErrorMessage = "The password does not meet the minimum requirements.";
policyValidator.SetFocusOnError = false;
PasswordValidatorPanel.Controls.Add(policyValidator);
return false;
}
return true;
}
protected void ChangeImageLink_Click(object sender, EventArgs e)
{
RefreshCaptcha();
Password.Attributes.Add("value", Password.Text);
}
private void RefreshCaptcha()
{
CaptchaImage.ChallengeText = StringHelper.RandomNumber(6);
}
#endregion
#region EMAIL LISTS
private void IntializeEmailLists()
{
if (!Page.IsPostBack)
{
if (!AbleContext.Current.User.IsAnonymous || CreateNewAccountPanel.Visible)
{
EmailLists.DataSource = GetPublicEmailLists();
EmailLists.DataBind();
}
else
{
EmailLists.Visible = false;
}
}
}
private IList<EmailList> GetPublicEmailLists()
{
IList<EmailList> emailLists = new List<EmailList>();
IList<EmailList> allLists = EmailListDataSource.LoadAll("Name");
foreach (EmailList list in allLists)
{
if (list.IsPublic)
emailLists.Add(list);
}
return emailLists;
}
protected bool IsEmailListChecked(object dataItem)
{
User user = AbleContext.Current.User;
if (user.IsAnonymous) return true;
EmailList list = (EmailList)dataItem;
return (list.IsMember(user.Email));
}
#endregion
#region BILLING ADDRESS
protected void InitAddressForm()
{
Address address = AbleContext.Current.User.PrimaryAddress;
FirstName.Text = address.FirstName;
LastName.Text = address.LastName;
Address1.Text = address.Address1;
Address2.Text = address.Address2;
City.Text = address.City;
PostalCode.Text = address.PostalCode;
InitCountryAndProvince();
Company.Text = address.Company;
BillToEmail.Text = address.Email;
Telephone.Text = address.Phone;
Fax.Text = address.Fax;
IsBusinessAddress.Checked = !address.Residence;
AddressValidationPanel.Visible = _addressValidator != null;
}
private void InitCountryAndProvince()
{
//MAKE SURE THE CORRECT ADDRESS IS SELECTED
Address address = AbleContext.Current.User.PrimaryAddress;
bool foundCountry = false;
if (!string.IsNullOrEmpty(address.CountryCode))
{
ListItem selectedCountry = Country.Items.FindByValue(address.CountryCode);
if (selectedCountry != null)
{
Country.SelectedIndex = Country.Items.IndexOf(selectedCountry);
foundCountry = true;
}
}
if (!foundCountry)
{
Warehouse defaultWarehouse = AbleContext.Current.Store.DefaultWarehouse;
ListItem selectedCountry = Country.Items.FindByValue(defaultWarehouse.CountryCode);
if (selectedCountry != null) Country.SelectedIndex = Country.Items.IndexOf(selectedCountry);
}
//MAKE SURE THE PROVINCE LIST IS CORRECT FOR THE COUNTRY
UpdateCountry();
//NOW LOOK FOR THE PROVINCE TO SET
if (Province.Visible) Province.Text = address.Province;
else
{
ListItem selectedProvince = Province2.Items.FindByValue(address.Province);
if (selectedProvince != null) Province2.SelectedIndex = Province2.Items.IndexOf(selectedProvince);
}
}
/// <summary>
/// Validates the current province value
/// </summary>
/// <returns></returns>
private bool ValidateProvince(out string provinceName)
{
provinceName = (Province.Visible ? StringHelper.StripHtml(Province.Text) : Province2.SelectedValue);
string countryCode = Country.SelectedValue;
if (ProvinceDataSource.CountForCountry(countryCode) == 0) return true;
//CHECK THE VALUE
int provinceId = ProvinceDataSource.GetProvinceIdByName(countryCode, provinceName);
if (provinceId > 0)
{
//UPDATE VALUE
Province p = ProvinceDataSource.Load(provinceId);
if (p.ProvinceCode.Length > 0) provinceName = p.ProvinceCode;
else provinceName = p.Name;
}
return (provinceId > 0);
}
private void UpdateCountry()
{
//SEE WHETHER POSTAL CODE IS REQUIRED
string[] countries = AbleContext.Current.Store.Settings.PostalCodeCountries.Split(",".ToCharArray());
PostalCodeRequired.Enabled = (Array.IndexOf(countries, Country.SelectedValue) > -1);
PostalCodeRequiredLabel.Visible = PostalCodeRequired.Enabled;
//SEE WHETHER PROVINCE LIST IS DEFINED
IList<Province> provinces = ProvinceDataSource.LoadForCountry(Country.SelectedValue);
if (provinces.Count > 0)
{
Province.Visible = false;
Province2.Visible = true;
Province2.Items.Clear();
Province2.Items.Add(string.Empty);
foreach (Province province in provinces)
{
string provinceValue = (!string.IsNullOrEmpty(province.ProvinceCode) ? province.ProvinceCode : province.Name);
Province2.Items.Add(new ListItem(province.Name, provinceValue));
}
ListItem selectedProvince = FindSelectedProvince();
if (selectedProvince != null) selectedProvince.Selected = true;
Province2Required.Enabled = true;
Province.Text = string.Empty;
}
else
{
Province.Visible = true;
Province2.Visible = false;
Province2.Items.Clear();
Province2Required.Enabled = false;
}
}
/// <summary>
/// Obtains the province that should default to selected in the drop down list
/// </summary>
/// <returns>The province that should default to selected in the drop down list</returns>
private ListItem FindSelectedProvince()
{
string defaultValue = Province.Text;
if (string.IsNullOrEmpty(defaultValue)) defaultValue = Request.Form[Province2.UniqueID];
if (string.IsNullOrEmpty(defaultValue)) return null;
defaultValue = defaultValue.ToUpperInvariant();
foreach (ListItem item in Province2.Items)
{
string itemText = item.Text.ToUpperInvariant();
string itemValue = item.Value.ToUpperInvariant();
if (itemText == defaultValue || itemValue == defaultValue) return item;
}
return null;
}
protected void Country_Changed(object sender, EventArgs e)
{
//UPDATE THE FORM FOR THE NEW COUNTRY
UpdateCountry();
}
#endregion
}
}
Am I simply blind? I prefer that do dumb.

Re: Customizations in Gold
Posted: Fri Jul 19, 2013 2:21 pm
by jguengerich
Not sure. When I scroll through the code you just posted, it is there, towards the bottom of the code. Just manually scroll through the code until you see #region BILLING ADDRESS. Do you see it here on the forum? If so, go to Visual Studio and make sure none of the #regions are collapsed - look for a + in the left margin of the code and click it.