Custom Field in Address

For general questions and discussions specific to the AbleCommerce 7.0 Asp.Net product.
Post Reply
ireneable
Ensign (ENS)
Ensign (ENS)
Posts: 3
Joined: Tue Jul 12, 2011 6:44 pm

Custom Field in Address

Post by ireneable » Tue Jul 12, 2011 7:15 pm

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(); 
.....
.....
}

User avatar
AbleMods
Master Yoda
Master Yoda
Posts: 5170
Joined: Wed Sep 26, 2007 5:47 am
Location: Fort Myers, Florida USA

Re: Custom Field in Address

Post by AbleMods » Fri Jul 15, 2011 5:31 am

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! :)
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com

ireneable
Ensign (ENS)
Ensign (ENS)
Posts: 3
Joined: Tue Jul 12, 2011 6:44 pm

Re: Custom Field in Address

Post by ireneable » Mon Jul 18, 2011 1:14 am

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?

User avatar
AbleMods
Master Yoda
Master Yoda
Posts: 5170
Joined: Wed Sep 26, 2007 5:47 am
Location: Fort Myers, Florida USA

Re: Custom Field in Address

Post by AbleMods » Mon Jul 18, 2011 4:37 am

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.
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com

ireneable
Ensign (ENS)
Ensign (ENS)
Posts: 3
Joined: Tue Jul 12, 2011 6:44 pm

Re: Custom Field in Address

Post by ireneable » Mon Jul 18, 2011 6:32 pm

Appreciate for your great help! Thank You!

User avatar
AbleMods
Master Yoda
Master Yoda
Posts: 5170
Joined: Wed Sep 26, 2007 5:47 am
Location: Fort Myers, Florida USA

Re: Custom Field in Address

Post by AbleMods » Tue Jul 19, 2011 5:36 am

no problem, glad I could help.
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com

harryhair5
Ensign (ENS)
Ensign (ENS)
Posts: 14
Joined: Fri Oct 15, 2010 2:05 pm

Re: Custom Field in Address

Post by harryhair5 » Tue Nov 08, 2011 1:40 pm

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.

User avatar
AbleMods
Master Yoda
Master Yoda
Posts: 5170
Joined: Wed Sep 26, 2007 5:47 am
Location: Fort Myers, Florida USA

Re: Custom Field in Address

Post by AbleMods » Tue Nov 08, 2011 4:26 pm

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!
Joe Payne
AbleCommerce Custom Programming and Modules http://www.AbleMods.com/
AbleCommerce Hosting http://www.AbleModsHosting.com/
Precise Fishing and Hunting Time Tables http://www.Solunar.com

Post Reply