Page 1 of 1
Custom Field in Address
Posted: Tue Jul 12, 2011 7:15 pm
by ireneable
I'm modifying the MyAddress page to add field "Mobile".
The problem now is it seems I can't get back the CustomFieldId in EditSaveButton_Click function and also when user adds the new address entry, it's unable to get the AddressId (just save zero as AddressId).
Many Thanks!
Added this code in EditMyAddressPage.ascx
Code: Select all
<tr>
<th class="rowHeader" valign="top" width="120">
<asp:Label ID="MobileLabel" runat="server" Text="Mobile:" AssociatedControlID="Mobile" EnableViewState="false"></asp:Label>
</th>
<td valign="top">
<asp:TextBox ID="Mobile" runat="server" EnableViewState="false" MaxLength="30"></asp:TextBox>
</td>
<th class="rowHeader" valign="top">
</th>
<td valign="top">
</td>
</tr>
And in EditMyAddressPage.ascx.cs
Code: Select all
public partial class ConLib_EditMyAddressPage : System.Web.UI.UserControl
{
private CustomField _CustomField;
.....
.....
}
protected void InitAddressForm()
{
Address address = this.Address;
CustomFieldCollection customFields = CustomFieldDataSource.LoadForCriteria(String.Format(" StoreId = {0} AND TableName='{1}' AND ForeignKeyId={2} ", Token.Instance.Store.StoreId, "ac_Addresses", address.AddressId));
if (customFields != null && customFields.Count > 0)
_CustomField = customFields[0];
if (_CustomField != null){
Mobile.Text = _CustomField.FieldValue;
}
protected void EditSaveButton_Click(object sender, EventArgs e)
{
string provinceName;
if (ValidateProvince(out provinceName))
{
if (Page.IsValid)
{
Address address = this.Address;
if (_CustomField == null)
_CustomField = new CustomField();
_CustomField.TableName = "ac_Addresses";
_CustomField.ForeignKeyId = this.AddressId;
_CustomField.FieldName = "mobile";
_CustomField.FieldValue = StringHelper.StripHtml(Mobile.Text);
_CustomField.Save();
.....
.....
}
Re: Custom Field in Address
Posted: Fri Jul 15, 2011 5:31 am
by AbleMods
You're probably going to want to get/set the mobile value in a variety of places in your storefront. Try using a helper class to make things easier on you as a programmer. Then you don't have to repeat your code so much throughout the application.
Here's a helper class file. Save it into your /App_Code/ folder with the name MyHelperClass.cs:
Code: Select all
using System;
using System.Collections.Generic;
using System.Web;
using CommerceBuilder.Users;
using CommerceBuilder.Stores;
using CommerceBuilder.Common;
/// <summary>
/// Summary description for MyHelperClass
/// </summary>
public class MyHelperClass
{
public static string GetMobile(Address _Address)
{
// set up return value
string _RetVal = "";
// check for valid
if (_Address == null)
return ""; // primary address does not exist
// find mobile custom field for this address ID
string _Query = "FieldName = 'MOBILE' AND StoreId={0} AND TableName='{1}' AND ForeignKeyId={2}";
_Query = String.Format(_Query, Token.Instance.StoreId, "ac_Addresses",_Address.AddressId);
CustomFieldCollection _CustomFields = CustomFieldDataSource.LoadForCriteria(_Query);
if (_CustomFields.Count == 0)
return ""; // no custom field for Mobile for this address
// got a mobile, pull in value and return it
_RetVal = _CustomFields[0].FieldValue;
// exit and return value
return _RetVal;
}
public static void SetMobile(Address _Address, string _MobileNumber)
{
// check for valid
if (_Address == null)
return; // primary address does not exist
// find mobile custom field for this address ID
string _Query = "FieldName = 'MOBILE' AND StoreId={0} AND TableName='{1}' AND ForeignKeyId={2}";
_Query = String.Format(_Query, Token.Instance.StoreId, "ac_Addresses", _Address.AddressId);
CustomFieldCollection _CustomFields = CustomFieldDataSource.LoadForCriteria(_Query);
CustomField _CustomField;
if (_CustomFields.Count == 0)
{
// have to make new custom field
_CustomField = new CustomField();
_CustomField.FieldName = "MOBILE";
_CustomField.FieldValue = _MobileNumber;
_CustomField.ForeignKeyId = _Address.AddressId;
_CustomField.TableName = "AC_Addresses";
_CustomField.StoreId = Token.Instance.StoreId;
}
else // already exists, just update it
{
_CustomField = _CustomFields[0];
_CustomField.FieldValue = _MobileNumber;
}
// either way, save it when we're done
_CustomField.Save();
// exit and return
return;
}
}
Once you have that class saved, now it's a very simple matter to set or get the mobile number for any address record at anywhere in your application.
Here's the InitAddressForm() routine with appropriate changes:
Code: Select all
protected void InitAddressForm()
{
Address address = this.Address;
string actionLabel = (address.AddressId == 0) ? "Create" : "Edit";
string typeLabel = (address.AddressId == Token.Instance.User.PrimaryAddress.AddressId) ? "Billing" : "Shipping";
EditAddressCaption.Text = string.Format(EditAddressCaption.Text, actionLabel, typeLabel);
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();
Phone.Text = address.Phone;
Company.Text = address.Company;
Fax.Text = address.Fax;
Residence.SelectedIndex = (address.Residence ? 0 : 1);
// BEGIN MOD: AbleMods.com
// 7/15/2011
txt_Mobile.Text = MyHelperClass.GetMobile(address);
// END MOD: AbleMods.com
}
And here is the EditSaveButton_Click() routine updated to store the mobile value entered by the user:
Code: Select all
protected void EditSaveButton_Click(object sender, EventArgs e)
{
string provinceName;
if (ValidateProvince(out provinceName))
{
if (Page.IsValid)
{
Address address = this.Address;
address.FirstName = StringHelper.StripHtml(FirstName.Text);
address.LastName = StringHelper.StripHtml(LastName.Text);
address.Address1 = StringHelper.StripHtml(Address1.Text);
address.Address2 = StringHelper.StripHtml(Address2.Text);
address.Company = StringHelper.StripHtml(Company.Text);
address.City = StringHelper.StripHtml(City.Text);
address.Province = provinceName;
address.PostalCode = StringHelper.StripHtml(PostalCode.Text);
address.CountryCode = Country.SelectedValue;
address.Phone = StringHelper.StripHtml(Phone.Text);
address.Fax = StringHelper.StripHtml(Fax.Text);
address.Residence = (Residence.SelectedIndex == 0);
// BEGIN MOD: AbleMods.com
// 7/15/2011
MyHelperClass.SetMobile(address, txt_Mobile.Text);
// END MOD: AbleMods.com
address.Save();
ShowAddressBook();
}
}
else
{
Province2Invalid.IsValid = false;
UpdateCountry();
}
}
As you can see, it's much easier to read the code and far quicker to deploy the new field in other areas of the application. Plus, if you need additional changes to the Get or Set routine, now you only have to change it in one place.
Finally, always remember to comment your code. The more changes you make, the more likely you'll forget why you made those changes.
Enjoy!

Re: Custom Field in Address
Posted: Mon Jul 18, 2011 1:14 am
by ireneable
Thank for your reply!
But it works only in edit Billing and Default Shipping Address. For new Other Shipping Address(es), it doesn't work since AddressId is zero before saving, so the ForeignKeyId(addressID) in ac_CustomFields must be zero.
Any suggestion?
Re: Custom Field in Address
Posted: Mon Jul 18, 2011 4:37 am
by AbleMods
ireneable wrote:it doesn't work since AddressId is zero before saving, so the ForeignKeyId(addressID) in ac_CustomFields must be zero.
Easy.
Once a new object is saved, the Id value is generated.
So let the routine save the shipping address as usual. Immediately after the .Save(), set mobile value and save again.
Re: Custom Field in Address
Posted: Mon Jul 18, 2011 6:32 pm
by ireneable
Appreciate for your great help! Thank You!
Re: Custom Field in Address
Posted: Tue Jul 19, 2011 5:36 am
by AbleMods
no problem, glad I could help.
Re: Custom Field in Address
Posted: Tue Nov 08, 2011 1:40 pm
by harryhair5
I've found this post to be very helpful. I've implemented a similar class, but (and perhaps this is a newbie thing. so please forgive me) I can't get AC to recognize that I've added the helper class to the app code folder. Do I need to include it with a using line of code at the top or fully qualify it or something?
Thanks in advance.
Re: Custom Field in Address
Posted: Tue Nov 08, 2011 4:26 pm
by AbleMods
harryhair5 wrote: I can't get AC to recognize that I've added the helper class to the app code folder.
You can either reference your new class at the top of your code file or explicitly reference it in your code. Look at some of the other code-files provided with AC7 and you'll see all of them have something like:
Code: Select all
using CommerceBuilder.Common;
using CommerceBuilder.Orders;
using System.IO;
So option 1 is, put a 'using yournamespace;' at the top of your code file.
Or option 2, just be explicit when you want to use your class like
Code: Select all
string _MyString = MyNameSpace.MyHelperClass.MyFunction();
The advantage of doing it at the top is it's easier/quicker to reference your custom class later in the meat of your programming. But if you only need to call it once or twice, sometimes it's just easier to spell out the explicit reference and move on. The choice is yours.
Good luck!