473,473 Members | 2,262 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Problems with custom control and asp.net

3 New Member
Hello. This is my first post here. I'm rather new to asp.net, although I have solid knowledges in other programming areas.
So, to be short. I have an Ajax enabled asp.net website to develop(using Enterprise Library, but that's not the problem). I created a master page, some content pages, and a custom control. I want to add the custom control in one of the content pages. The idea is the following: I assume I don't know the tables' structure that I'm using, so I develop some custom code and draw dynamically my controls(a gridview and a detailsview). the problem that i have is that on the content page in need to load in the custom control some data. I try to call in the PreInit method of the content pagea method from the custom control, but that control is null. Also, the insert feature of the custom control doesn't work.

Is there a way to address this issue?
May 21 '07 #1
3 2137
kenobewan
4,871 Recognized Expert Specialist
Welcome to the site. If I understand you correctly, controls are not for storing data this can be done defined in a class.
May 21 '07 #2
DaeMoohn
3 New Member
No. I can give you an example of what i've done and what should be done.
I have a database filled with tables. I don't want to use their structure in modeling my asp.net pages. That would mean writing 10 thousand times the same controls. I created a custom control where, giving in a custom class the name of the table that custom control is built for, it is able to add checkboxfields, and other bounded fields to a gridview and a detailsview(i will handle in the future with calendars, etc).
So, if you have 100 simple(yet) table, that control can be used on 100 simple pages with only drag and drops into a content page.

The problem that i have is the following: I use a master page. A have a content page, let's say adminbranches.aspx, where i want to place a custom control like that one described above. Simple drag and drop, right? I also give the params required so that the custom control can dynamically create the gridview and the detailsview. As I am a newbie in asp.net, I misplaced this initialization procedure into the OnLoad but that's not correct. As far as I've been told by friends, I must find a way so that in the OnPreInit in the content page I would load those params into the custom control. My implementation uses those params defined in the custom control, so that in the OnPreInit the custom control is still null. So my code doesn't run. I would need a way to invoke in custom control's OnInit, before base.OnInit(), a function or some params from the parent( the content page itself). But I don't know why.
In fact, I don't know if that's the way.

Sorry for this long post. I am not a native English speaker, I am at the end of another 8 frustrating hours in which I didn't complete my tasks and I've lost my hope.
May 21 '07 #3
DaeMoohn
3 New Member
Some code:
The content page:
Expand|Select|Wrap|Line Numbers
  1. using System.Data;
  2. using System.Configuration;
  3. using System.Collections;
  4. using System.Web;
  5. using System.Web.Security;
  6. using System.Web.UI;
  7. using System.Web.UI.WebControls;
  8. using System.Web.UI.WebControls.WebParts;
  9. using System.Web.UI.HtmlControls;
  10. using System.Data.SqlClient;
  11. using MyCode;
  12.  
  13. public partial class AdminArea_AdminUnits : System.Web.UI.Page
  14. {
  15.     private Sucursale suc = new Sucursale(ConfigurationManager.ConnectionStrings["Connection String"].ConnectionString);
  16.     private string[] cmds ={ "GetSucursale", "InsertSucursala", "UpdateSucursala", "DeleteSucursala" };
  17.  
  18.     protected override void OnPreInit(EventArgs e)
  19.     {
  20.         base.OnPreInit(e);
  21.     }
  22.  
  23.     protected override void OnInit(EventArgs e)
  24.     {
  25.         //SqlParameterCollection[] parames ={ suc.GetSPInsertParams(), suc.GetSPUpdateParams(), suc.GetSPDeleteParams() };
  26.         //this.CustomPanel1.LoadForm("MyCode.Sucursale", "Sucursale", suc.GetTableInfo(), cmds, parames);
  27.         base.OnInit(e);
  28.  
  29.     }
  30. }
  31.  
  32.  
The custom control:

Expand|Select|Wrap|Line Numbers
  1.  
  2. using System;
  3. using System.Data;
  4. using System.Configuration;
  5. using System.Collections;
  6. using System.Web;
  7. using System.Web.Security;
  8. using System.Web.UI;
  9. using System.Web.UI.WebControls;
  10. using System.Web.UI.WebControls.WebParts;
  11. using System.Web.UI.HtmlControls;
  12. using System.Data.SqlClient;
  13. using MyCode;
  14.  
  15. /*
  16. http://codebetter.com/blogs/raymond.lewallen/archive/2005/03/10/59583.aspx
  17.  
  18. http://john-sheehan.com/blog/index.php/net-cheat-sheets/
  19.  
  20. http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx
  21. */
  22.  
  23. struct FormAddons
  24. {
  25.     public static SqlParameterCollection updateparams, insertparams, deleteparams;
  26.     public static string typename;
  27.     public static string table;
  28.     public static object[][] columns;
  29.     public static string getcmd, insertcmd, updatecmd, deletecmd;
  30. };
  31.  
  32. public partial class Custom_Controls_CustomPanel : System.Web.UI.UserControl
  33. {
  34.     private int nodetailsitems = 1;
  35.  
  36.     protected override void OnInit(EventArgs e)
  37.     {
  38.         FormAddons.getcmd = "asa";
  39.         base.OnInit(e);
  40.         if (FormAddons.columns!=null)
  41.         {
  42.             CreateGridViewControls();
  43.             CreateDetailsViewControls();
  44.         }
  45.  
  46.     }
  47.     protected void Page_Load(object sender, EventArgs e)
  48.     {
  49.         SetObjectDataSource();
  50.     }
  51.  
  52.     #region creez controalele
  53.  
  54.     /// <summary>
  55.     /// creez controalele copil pentru grid
  56.     /// </summary>
  57.     private void CreateGridViewControls()
  58.     {
  59.         CommandField cmf = new CommandField();
  60.         cmf.ButtonType = ButtonType.Image;
  61.         cmf.EditText = "Editati inregistarea";
  62.         cmf.EditImageUrl = "~/pictures/editbox.ico";
  63.         cmf.CancelImageUrl = "~/pictures/cancel.ico";
  64.         cmf.CancelText = "Anulati modificarea";
  65.         cmf.UpdateImageUrl = "~/pictures/oki.ico";
  66.         cmf.UpdateText = "Efectuati modificarile";
  67.         cmf.ShowEditButton = true;
  68.         this.GridView1.Columns.Add(cmf);
  69.  
  70.         cmf = new CommandField();
  71.         cmf.ButtonType = ButtonType.Image;
  72.         cmf.DeleteImageUrl = "~/pictures/delete_16x.ico";
  73.         cmf.ShowDeleteButton = true;
  74.         cmf.DeleteText = "Stergeti inregistrarea";
  75.         this.GridView1.Columns.Add(cmf);
  76.  
  77.         int step = 0;
  78.         foreach (object[] param in FormAddons.columns)
  79.         {
  80.             switch (param[1].ToString())
  81.             {
  82.                 case "bit":
  83.                     CheckBoxField cf = new CheckBoxField();
  84.                     cf.HeaderText = param[0].ToString();
  85.                     if (step == 0)
  86.                     {
  87.                         cf.ReadOnly = true;
  88.                         cf.InsertVisible = false;
  89.                     }
  90.                     cf.DataField = param[0].ToString();
  91.                     cf.SortExpression = param[0].ToString();
  92.                     this.GridView1.Columns.Add(cf);
  93.                     break;
  94.                 default:
  95.                     BoundField bf = new BoundField();
  96.                     if (step == 0)
  97.                     {
  98.                         bf.ReadOnly = true;
  99.                         bf.InsertVisible = false;
  100.                     }
  101.                     bf.HeaderText = param[0].ToString();
  102.                     bf.DataField = param[0].ToString();
  103.                     bf.SortExpression = param[0].ToString();
  104.                     this.GridView1.Columns.Add(bf);
  105.                     break;
  106.             }
  107.             step++;
  108.         }
  109.     }
  110.  
  111.     /// <summary>
  112.     /// creez controalele pentru detailsview
  113.     /// </summary>
  114.     private void CreateDetailsViewControls()
  115.     {
  116.         foreach (object[] param in FormAddons.columns)
  117.         {
  118.             switch (param[1].ToString())
  119.             {
  120.                 case "bit":
  121.                     CheckBoxField cf = new CheckBoxField();                    
  122.                     cf.HeaderText = param[0].ToString();
  123.                     if (nodetailsitems == 1)
  124.                     {
  125.                         cf.ReadOnly = true;
  126.                         cf.InsertVisible = false;
  127.                     }
  128.                     cf.DataField = param[0].ToString();
  129.                     cf.SortExpression = param[0].ToString();
  130.                     this.DetailsView1.Fields.Add(cf);
  131.                     break;
  132.                 default:
  133.                     BoundField bf = new BoundField();
  134.                     if (nodetailsitems == 1)
  135.                     {
  136.                         bf.ReadOnly = true;
  137.                         bf.InsertVisible = false;
  138.                     }
  139.                     bf.HeaderText = param[0].ToString();
  140.                     bf.DataField = param[0].ToString();
  141.                     bf.SortExpression = param[0].ToString();
  142.                     this.DetailsView1.Fields.Add(bf);
  143.                     break;
  144.             }
  145.             nodetailsitems++;
  146.         }
  147.     }
  148.  
  149.     #endregion
  150.  
  151.     #region setez datasource
  152.  
  153.     /// <summary>
  154.     /// setez metodele si paramii folositi de data sourceul din pagina
  155.     /// </summary>
  156.     private void SetObjectDataSource()
  157.     {
  158.         #region setez comenzile...
  159.         this.ObjectDataSource1.TypeName = FormAddons.typename;
  160.         this.ObjectDataSource1.SelectMethod = FormAddons.getcmd;
  161.         this.ObjectDataSource1.UpdateMethod = FormAddons.updatecmd;
  162.         this.ObjectDataSource1.DeleteMethod = FormAddons.deletecmd;
  163.         this.ObjectDataSource1.InsertMethod = FormAddons.insertcmd;
  164.         #endregion
  165.  
  166.         #region setez paramii de update
  167.         if (this.ObjectDataSource1.UpdateParameters.Count < 1)
  168.         {
  169.             foreach (SqlParameter param in FormAddons.updateparams)
  170.             {
  171.                 switch (param.DbType)
  172.                 {
  173.                     case DbType.String:
  174.                         this.ObjectDataSource1.UpdateParameters.Add(param.ParameterName.Substring(1), TypeCode.String, "");
  175.                         break;
  176.                     case DbType.Int32:
  177.                         this.ObjectDataSource1.UpdateParameters.Add(param.ParameterName.Substring(1), TypeCode.Int32, "");
  178.                         break;
  179.                     case DbType.Binary:
  180.                         this.ObjectDataSource1.UpdateParameters.Add(param.ParameterName.Substring(1), TypeCode.Boolean, "");
  181.                         break;
  182.                 };
  183.             }
  184.         }
  185.         #endregion
  186.  
  187.         #region setez paramii de insert
  188.         if (this.ObjectDataSource1.InsertParameters.Count < 1)
  189.         {
  190.             foreach (SqlParameter param in FormAddons.insertparams)
  191.             {
  192.                 switch (param.DbType)
  193.                 {
  194.                     case DbType.String:
  195.                         this.ObjectDataSource1.InsertParameters.Add(param.ParameterName.Substring(1), TypeCode.String, "");
  196.                         break;
  197.                     case DbType.Int32:
  198.                         this.ObjectDataSource1.InsertParameters.Add(param.ParameterName.Substring(1), TypeCode.Int32, "");
  199.                         break;
  200.                     case DbType.Boolean:
  201.                         this.ObjectDataSource1.InsertParameters.Add(param.ParameterName.Substring(1), TypeCode.Boolean, "");
  202.                         break;
  203.                 };
  204.             }
  205.         }
  206.         #endregion
  207.  
  208.         #region setez paramii de delete
  209.         if (this.ObjectDataSource1.DeleteParameters.Count < 1)
  210.         {
  211.             foreach (SqlParameter param in FormAddons.deleteparams)
  212.             {
  213.                 switch (param.DbType)
  214.                 {
  215.                     case DbType.String:
  216.                         this.ObjectDataSource1.DeleteParameters.Add(param.ParameterName.Substring(1), TypeCode.String, "");
  217.                         break;
  218.                     case DbType.Int32:
  219.                         this.ObjectDataSource1.DeleteParameters.Add(param.ParameterName.Substring(1), TypeCode.Int32, "");
  220.                         break;
  221.                     case DbType.Binary:
  222.                         this.ObjectDataSource1.DeleteParameters.Add(param.ParameterName.Substring(1), TypeCode.Boolean, "");
  223.                         break;
  224.                 };
  225.             }
  226.         }
  227.         #endregion
  228.  
  229.         #region setez sourceurile pt ctroale
  230.         string[] datakeys ={ FormAddons.columns[0][0].ToString() };
  231.  
  232.         this.DetailsView1.DataKeyNames = datakeys;
  233.         this.DetailsView1.DataSourceID = "ObjectDataSource1";
  234.  
  235.         this.GridView1.DataKeyNames = datakeys;
  236.         this.GridView1.DataSourceID = "ObjectDataSource1";
  237.  
  238.         this.GridView1.DataBind();
  239.         this.DetailsView1.DataBind();
  240.         #endregion
  241.     }
  242.  
  243.     /// <summary>
  244.     /// setez elementele cu care lucrez in form... 
  245.     /// </summary>
  246.     /// <param name="typename"></param>
  247.     /// <param name="table"></param>
  248.     /// <param name="columns"></param>
  249.     /// <param name="cmd"></param>
  250.     /// <param name="parames"></param>
  251.     public void LoadForm(string typename, string table, object[][] columns, string[] cmd, SqlParameterCollection[] parames)
  252.     {
  253.         FormAddons.typename = typename;
  254.         FormAddons.table = table;
  255.         FormAddons.columns = columns;
  256.         FormAddons.getcmd = cmd[0];
  257.         FormAddons.insertcmd = cmd[1];
  258.         FormAddons.updatecmd = cmd[2];
  259.         FormAddons.deletecmd = cmd[3];
  260.         FormAddons.insertparams = parames[0];
  261.         FormAddons.updateparams = parames[1];
  262.         FormAddons.deleteparams = parames[2];
  263.     }
  264.  
  265.     #endregion
  266.     #region evenimente
  267.     protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
  268.     {
  269.  
  270.     }
  271.     protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
  272.     {
  273.         GridView1.PageIndex = e.NewPageIndex;
  274.         SetObjectDataSource();
  275.     }
  276.     protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
  277.     {
  278.         GridView1.EditIndex = -1;
  279.         SetObjectDataSource();
  280.     }
  281.     protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
  282.     {
  283.         GridView1.SelectedIndex = -1;
  284.         SetObjectDataSource();
  285.     }
  286.     protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
  287.     {
  288.         GridView1.EditIndex = e.NewEditIndex;
  289.         SetObjectDataSource();
  290.     }
  291.     protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
  292.     {
  293.         GridView1.EditIndex = -1;
  294.         SetObjectDataSource();
  295.     }
  296.     protected void Button1_Click(object sender, EventArgs e)
  297.     {
  298.         DetailsViewRowCollection rowcollection = this.DetailsView1.Rows;
  299.         foreach (DetailsViewRow datarow in rowcollection)
  300.         {
  301.             if(datarow.Cells[1].Controls[0].GetType().ToString()=="System.Web.UI.WebControls.TextBox")
  302.             {
  303.                 System.Web.UI.WebControls.TextBox tempTxtBox = (System.Web.UI.WebControls.TextBox)datarow.Cells[1].Controls[0];
  304.                 string a = tempTxtBox.Text;
  305.             }
  306.         }
  307.         ObjectDataSource1.Insert();
  308.     }
  309.     #endregion
  310.  
  311. }
  312.  
My business class
Expand|Select|Wrap|Line Numbers
  1.  
  2. using System;
  3. using System.Data;
  4. using System.Data.SqlClient;
  5. using System.Configuration;
  6. using System.Web;
  7. using System.Web.Security;
  8. using System.Web.UI;
  9. using System.Web.UI.WebControls;
  10. using System.Web.UI.WebControls.WebParts;
  11. using System.Web.UI.HtmlControls;
  12.  
  13. /// <summary>
  14. /// Summary description for Sucursale
  15. /// </summary>
  16. namespace MyCode
  17. {
  18.     public class Sucursale
  19.     {
  20.         MyCode.MyFactory fab = new MyFactory();
  21.         public Sucursale()
  22.         {
  23.         }
  24.  
  25.         public Sucursale(string ConnectionString)
  26.         {
  27.             fab.ConnectionString = ConnectionString;
  28.         }
  29.  
  30.         public DataSet GetSucursale()
  31.         {
  32.             return fab.ExecuteStoredProc("GetSucursale");
  33.         }
  34.  
  35.         public DataSet GetSucursalaByID(Int32 ID_Sucursala)
  36.         {
  37.             return fab.ExecuteStoredProc("GetSucursalaByID",ID_Sucursala.ToString());
  38.         }
  39.  
  40.         public DataSet DeleteSucursala(Int32 ID_Sucursala)
  41.         {
  42.             return fab.ExecuteStoredProc("DeleteSucursala", ID_Sucursala.ToString());
  43.         }
  44.  
  45.         public DataSet UpdateSucursala(String Denumire, String CodSucursala, System.Nullable<Boolean> SucursalaNoua , Int32 ID_Sucursala)
  46.         {
  47.             return fab.ExecuteStoredProc("UpdateSucursala", ID_Sucursala.ToString(), Denumire, SucursalaNoua, CodSucursala);
  48.         }
  49.  
  50.         public DataSet InsertSucursala(String Denumire,System.Nullable<Boolean> SucursalaNoua,String CodSucursala)
  51.         {
  52.             return fab.ExecuteStoredProc("InsertSucursala", Denumire, SucursalaNoua, CodSucursala);
  53.         }
  54.  
  55.         public SqlParameterCollection GetSPGetSpecialParams()
  56.         {
  57.             return fab.GetStoredProcParams("GetSucursalaByID",false);
  58.         }
  59.  
  60.         public SqlParameterCollection GetSPUpdateParams()
  61.         {
  62.             return fab.GetStoredProcParams("UpdateSucursala", false);
  63.         }
  64.  
  65.         public SqlParameterCollection GetSPDeleteParams()
  66.         {
  67.             return fab.GetStoredProcParams("DeleteSucursala", false);
  68.         }
  69.  
  70.         public SqlParameterCollection GetSPInsertParams()
  71.         {
  72.             return fab.GetStoredProcParams("InsertSucursala", false);
  73.         }
  74.  
  75.         public object[][] GetTableInfo()
  76.         {
  77.             DataSet myset = fab.ExecuteStoredProc("GetMetadata","Sucursale");
  78.             if (myset.Tables.Count != 0)
  79.             {
  80.                 Object[][] myobj=new object[myset.Tables[0].Rows.Count][];
  81.                 int counter=0;
  82.                 foreach (DataRow dr in myset.Tables[0].Rows)
  83.                 {
  84.                     myobj[counter] = new object[2];
  85.                     myobj[counter][0] = dr.ItemArray[0];
  86.                     myobj[counter][1] = dr.ItemArray[1];
  87.                     counter++;
  88.                 }
  89.                 return myobj;
  90.             }
  91.  
  92.             return null;
  93.         }
  94.     }
  95. }
  96.  
  97.  
And the database connection class

Expand|Select|Wrap|Line Numbers
  1.  
  2. using System;
  3. using System.Data;
  4. using System.Data.Common;
  5. using System.Data.SqlClient;
  6. using System.Configuration;
  7. using System.Web;
  8. using System.Web.Security;
  9. using System.Web.UI;
  10. using System.Web.UI.WebControls;
  11. using System.Web.UI.WebControls.WebParts;
  12. using System.Web.UI.HtmlControls;
  13. using Microsoft.Practices.EnterpriseLibrary.Data;
  14.  
  15. namespace MyCode
  16. {
  17.     public class MyFactory
  18.     {
  19.         public string server="Connection String";
  20.         public string ConnectionString;
  21.         public MyFactory()
  22.         {
  23.         }
  24.  
  25.         public DataSet ExecuteStringCommand(String command)
  26.         {
  27.             Database db = DatabaseFactory.CreateDatabase(server);
  28.             DbCommand dbcommand = db.GetSqlStringCommand(command);
  29.  
  30.             DataSet ds=new DataSet();
  31.             ds=db.ExecuteDataSet(dbcommand);
  32.  
  33.             return ds;
  34.         }
  35.  
  36.         public DataSet ExecuteStoredProc(String storedproc, params object[] parames)
  37.         {
  38.             Database db = DatabaseFactory.CreateDatabase(server);
  39.             DbCommand dbcommand=db.GetStoredProcCommand(storedproc,parames);
  40.  
  41.             DataSet ds=new DataSet();
  42.             ds=db.ExecuteDataSet(dbcommand);
  43.  
  44.             return ds;
  45.         }
  46.  
  47.         public SqlParameterCollection GetStoredProcParams(string storedproc,bool includereturns)
  48.         {
  49.             SqlConnection sqlcon = new SqlConnection(ConnectionString);
  50.             SqlCommand cmd = new SqlCommand(storedproc, sqlcon);
  51.             sqlcon.Open();
  52.             cmd.CommandType = CommandType.StoredProcedure;
  53.             SqlCommandBuilder.DeriveParameters(cmd);
  54.             if (!includereturns)
  55.             {
  56.                 cmd.Parameters.RemoveAt(0);
  57.             }
  58.             sqlcon.Close();
  59.             sqlcon.Dispose();
  60.             return cmd.Parameters;
  61.         }
  62.     }
  63. }
  64.  
  65.  
May 21 '07 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

19
by: Dales | last post by:
I have a custom control that builds what we refer to as "Formlets" around some content in a page. These are basically content "wrapper" sections that are tables that have a colored header and...
2
by: Brian | last post by:
NOTE ALSO POSTED IN microsoft.public.dotnet.framework.aspnet.buildingcontrols I have solved most of my Server Control Collection property issues. I wrote an HTML page that describes all of the...
6
by: Suzanne | last post by:
Hi all, I really hope someone out there can help me as I've been tearing my hair out on this one for a good while and I'm getting really frustrated now! My problem is this - my custom...
2
by: Suzanne | last post by:
Hi all, I'm reposting this message as I'm experiencing this problem more and more frequently : I really hope someone out there can help me as I've been tearing my hair out on this one for a...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.