Click here to Skip to main content
15,894,646 members
Articles / Web Development / ASP.NET

Implementing Model-View-Presenter in ASP.NET

Rate me:
Please Sign up or sign in to vote.
4.80/5 (27 votes)
17 Nov 2007CPOL12 min read 129.8K   2.7K   120  
Three implementations of Model-View-Presenter in ASP.NET 2.0.
using System;
using System.Text;
using System.Web.UI.WebControls;
using SubSonic;
using SubSonic.Utilities;
using System.Data;



namespace SubSonic
{
    public class ScaffoldCodeGenerator
    {
        #region Page Builders
        /// <summary>
        /// Generates the "In Front" code for an ASPX page
        /// </summary>
        /// <param name="providerName">Name of the DataProvider to use</param>
        /// <param name="tableName">Name of Table</param>
        /// <param name="pageFileName">The name of the ASPX page - like "Editor.aspx"</param>
        /// <param name="masterPage">The Master Page File, if any</param>
        /// <param name="languageType">Output language, i.e C# or that other one</param>
        /// <returns></returns>
        public static string GeneratePage(string providerName, string tableName, string pageFileName, string masterPage, LanguageType languageType)
        {
            //Grab the tableschema
            TableSchema.Table tbl = DataService.GetTableSchema(tableName, providerName);

            if (tbl.PrimaryKey == null)
            {
                return tableName + " does not contain a primary key. Primary keys are required for scaffold generation."; 
            }

            string pageTemplate = ResourceHelper.GetString(TemplateName.EDITOR);
                /*
                #PK# = Primary Key of the table
                #GRIDROWS# = all the rows in the GridView
                #EDITORROWS# = the rows inside the editor table
                #TABLENAME# = the name of the table
                */

                //this part's simple enough - just straight up text replacement
                pageTemplate = pageTemplate.Replace(TemplateVariable.TABLE_NAME, tbl.DisplayName);
                pageTemplate = pageTemplate.Replace(TemplateVariable.PK, tbl.PrimaryKey.ColumnName);
                pageTemplate = pageTemplate.Replace(TemplateVariable.PAGE_FILE, pageFileName);

                //now loop out the columns for each row of the table editor and grid
                StringBuilder gridRows = new StringBuilder();
                StringBuilder editorRows = new StringBuilder();

                foreach(TableSchema.TableColumn col in tbl.Columns)
                {
                    if(!col.IsPrimaryKey)
                    {
                        string control;
                        string properties = String.Empty;
                        control = GetControlText(typeof(BoundField).Name, null);
                        AddControlProperty(ref properties, "DataField", col.ColumnName);
                        AddControlProperty(ref properties, "HeaderText", Utility.ParseCamelToProper(col.ColumnName));
                        AddControlProperty(ref properties, "SortExpression", col.ColumnName);
                        ApplyControlProperties(ref control, properties);
                        gridRows.AppendLine(AddTabs(2) + control);
                        editorRows.AppendLine("\t\t<tr>" + Environment.NewLine + "\t\t\t<td class=\"scaffoldEditItemCaption\">" + Utility.ParseCamelToProper(col.ColumnName) + "</td>" + Environment.NewLine + "\t\t\t<td class=\"scaffoldEditItem\">" + GetEditControl(col) + "</td>" + Environment.NewLine + "\t\t</tr>");
                    }
                }

                pageTemplate = pageTemplate.Replace(TemplateVariable.EDITOR_ROWS, editorRows.ToString());
                pageTemplate = pageTemplate.Replace(TemplateVariable.GRID_ROWS, gridRows.ToString());


                //get the wrapper
                bool useMaster = !String.IsNullOrEmpty(masterPage);
                string wrapper = GetPageWrapper(useMaster);

                string jsBlock = CodeBlock.JS_BEGIN_SCRIPT + ResourceHelper.GetString(TemplateName.SCAFFOLD_DELETE_CONFIRMATION) + ResourceHelper.GetString(TemplateName.SCAFFOLD_CHARACTER_COUNTER) + CodeBlock.JS_END_SCRIPT;
                wrapper = wrapper.Replace(TemplateVariable.JAVASCRIPT_BLOCK, jsBlock);
                wrapper = wrapper.Replace(TemplateVariable.PAGE_CODE, pageTemplate.ToString());
                wrapper = wrapper.Replace(TemplateVariable.MASTER_PAGE, masterPage);
                wrapper = wrapper.Replace(TemplateVariable.TABLE_NAME, pageFileName.Replace(FileExtension.DOT_ASPX, String.Empty));

                //determine the language
                string codeFileExt = FileExtension.CS;
                if(languageType == LanguageType.VB)
                {
                    codeFileExt = FileExtension.VB;
                }
                wrapper = wrapper.Replace(TemplateVariable.LANGUAGE_EXTENSION, codeFileExt);

                return wrapper;

        }

        static string GetPageWrapper(bool useMaster)
        {
            string result;

            if (useMaster)
            {
                result = ResourceHelper.GetString(TemplateName.EDITOR_WRAPPER_MASTERPAGE);
            }
            else
            {
                result = ResourceHelper.GetString(TemplateName.EDITOR_WRAPPER);
            }
            return result;
        }

        private static string GetControlText(string controlType, string controlId)
        {
            if(!String.IsNullOrEmpty(controlId))
            {
                return "<asp:" + controlType + " ID=\"" + controlId + "\" runat=\"server\" " + TemplateVariable.CONTROL_PROPERTY + "></asp:" + controlType + ">";
            }
            else
            {
                return "<asp:" + controlType + " " + TemplateVariable.CONTROL_PROPERTY + "></asp:" + controlType + ">";
            }
        }

        private static string AddTabs(int count)
        {
            StringBuilder sb = new StringBuilder();
            for(int i = 0; i < count; i++)
            {
                sb.Append("\t");
            }
            return sb.ToString();
        }

        private static void AddControlProperty(ref string variableText, string propertyName, string propertyValue)
        {
            variableText += propertyName + "=\"" + propertyValue + "\" ";
        }

        private static void ApplyControlProperties(ref string controlText, string variableText)
        {
            controlText = controlText.Replace(TemplateVariable.CONTROL_PROPERTY, variableText.Trim());
        }

        private static string GetEditControl(TableSchema.TableColumn col)
        {
            string result;
            string variableText = String.Empty;
            string controlID = col.PropertyName;
            bool isTextBox = false;

            if(col.IsForeignKey)
            {
                result = GetControlText(typeof(DropDownList).Name, controlID);
            }
            else
            {
                switch(col.DataType)
                {
                    case DbType.Binary:
                    case DbType.Byte:
                        result = String.Empty;
                        break;
                    case DbType.Guid:
                    case DbType.AnsiString:
                    case DbType.String:
                    case DbType.StringFixedLength:
                    case DbType.Xml:
                    case DbType.Object:
                    case DbType.AnsiStringFixedLength:
                        if(Utility.IsMatch(col.ColumnName, ReservedColumnName.CREATED_BY) || Utility.IsMatch(col.ColumnName, ReservedColumnName.MODIFIED_BY))
                        {
                            result = GetControlText(typeof(Label).Name, controlID);
                        }
                        else
                        {
                            isTextBox = true;
                            result = GetControlText(typeof(TextBox).Name, controlID);
                            if(col.MaxLength > 250)
                            {
                                AddControlProperty(ref variableText, "TextMode", "MultiLine");
                                AddControlProperty(ref variableText, "Height", "100px");
                                AddControlProperty(ref variableText, "Width", "500px");
                            }
                        }
                        break;
                    case DbType.Date:
                    case DbType.Time:
                    case DbType.DateTime:
                        if(Utility.IsMatch(col.ColumnName, ReservedColumnName.MODIFIED_ON) || Utility.IsMatch(col.ColumnName, ReservedColumnName.CREATED_ON))
                        {
                            result = GetControlText(typeof(Label).Name, controlID);
                        }
                        else
                        {
                            result = GetControlText(typeof(Calendar).Name, controlID);
                        }
                        break;
                    case DbType.Int16:
                    case DbType.Int32:
                    case DbType.UInt16:
                    case DbType.Int64:
                    case DbType.UInt32:
                    case DbType.UInt64:
                    case DbType.VarNumeric:
                    case DbType.Single:
                    case DbType.Currency:
                    case DbType.Decimal:
                    case DbType.Double:
                        isTextBox = true;
                        result = GetControlText(typeof(TextBox).Name, controlID);
                        AddControlProperty(ref variableText, "Width", "50px");
                        if(col.DataType == DbType.Currency)
                        {
                            result = "$" + result;
                        }
                        break;
                    case DbType.Boolean:
                        bool isChecked = false;
                        if(Utility.IsMatch(col.ColumnName, ReservedColumnName.IS_ACTIVE))
                        {
                            isChecked = true;
                        }
                        result = GetControlText(typeof(CheckBox).Name, controlID);
                        AddControlProperty(ref variableText, ControlValueProperty.CHECK_BOX, isChecked.ToString());
                        break;
                    default:
                        isTextBox = true;
                        result = GetControlText(typeof(TextBox).Name, controlID);
                        break;
                }
            }
            if(isTextBox && col.MaxLength > 0)
            {
                AddControlProperty(ref variableText, "MaxLength", col.MaxLength.ToString());
            }
            ApplyControlProperties(ref result, variableText);
            return result;
        }
        #endregion


        #region Code Builder

        private static void CreatePropertySetter(ref string controlText, string controlId, string itemPropertyName, string controlPropertyName, bool toString, bool nullableType)
        {
            StringBuilder sb = new StringBuilder();
            if(nullableType)
            {
                sb.AppendLine("if(item." + itemPropertyName + ".HasValue)");
                sb.AppendLine(AddTabs(2) + "{");
                if(toString)
                {
                    sb.AppendLine(AddTabs(3) + controlId + "." + controlPropertyName + " = item." + itemPropertyName + ".Value.ToString();");
                }
                else
                {
                    sb.AppendLine(AddTabs(3) + controlId + "." + controlPropertyName + " = item." + itemPropertyName + ".Value;");
                }
                sb.AppendLine(AddTabs(2) + "}");
            }
            else
            {
                if (toString)
                {
                    sb.AppendLine(AddTabs(2) + controlId + "." + controlPropertyName + " = item." + itemPropertyName + ".ToString();");
                }
                else
                {
                    sb.AppendLine(AddTabs(2) + controlId + "." + controlPropertyName + " = item." + itemPropertyName + ";");
                }
            }
            controlText = sb.ToString();
        }

        static string GetControlValue(TableSchema.TableColumn col, string className)
        {
            StringBuilder result = new StringBuilder();
            string controlID = col.PropertyName;
            string propName = col.PropertyName;
            string converterType = (col.DataType == DbType.Currency || col.DataType == DbType.VarNumeric) ? "Decimal" : col.DataType.ToString();
            int tabIndent = 2;

            result.AppendLine(AddTabs(2) + "object val" + controlID + " = Utility.GetDefaultControlValue(" + className + ".Schema.GetColumn(\"" + propName + "\"), Page.FindControl(\"" + controlID + "\"), isAdd, false);");
            if(col.IsNullable)
            {
                result.AppendLine(AddTabs(2) + "if(val" + controlID + " == null)");
                result.AppendLine(AddTabs(2) + "{");
                result.AppendLine(AddTabs(3) + "item." + propName + " = null;");
                result.AppendLine(AddTabs(2) + "}");
                result.AppendLine(AddTabs(2) + "else");
                result.AppendLine(AddTabs(2) + "{");
                tabIndent++;
            }

            if (col.DataType != DbType.Guid)
            {
                result.AppendLine(AddTabs(tabIndent) + "item." + propName + " = Convert.To" + converterType + "(val" + controlID + ");");
            }
            else
            {
                result.AppendLine(AddTabs(tabIndent) + "item." + propName + " = new " + converterType + "(val" + controlID + ".ToString());");
            }

            if(col.IsNullable)
            {
                result.AppendLine(AddTabs(2) + "}");
            }
            return result.ToString();
        }

        static string SetControlValue(TableSchema.TableColumn col, string tableName)
        {
            string result = String.Empty;
            string propName = col.PropertyName;
            string controlID = col.PropertyName;
            bool isNullableType = (col.IsNullable && Utility.IsNullableDbType(col.DataType));

            if (col.IsForeignKey)
            {
                CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.DROP_DOWN_LIST, true, isNullableType);
            }
            else
            {
                
                switch(col.DataType)
                {
                    case DbType.Binary:
                    case DbType.Byte:
                        result = String.Empty;
                        break;
                    case DbType.DateTime:
                        CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.CALENDAR, false, isNullableType);
                        break;
                    case DbType.Boolean:
                        CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.CHECK_BOX, false, isNullableType);
                        break;
                    case DbType.Currency:
                    case DbType.VarNumeric:
                        CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.TEXT_BOX, true, isNullableType);
                        break;
                    case DbType.Int16:
                    case DbType.Int32:
                    case DbType.UInt16:
                    case DbType.Int64:
                    case DbType.UInt32:
                    case DbType.UInt64:
                    case DbType.Single:
                    case DbType.Decimal:
                    case DbType.Double:
                        CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.TEXT_BOX, true, isNullableType);
                        break;
                    case DbType.String:
                        CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.TEXT_BOX, false, isNullableType);
                        break;
                    default:
                        CreatePropertySetter(ref result, controlID, propName, ControlValueProperty.TEXT_BOX, true, isNullableType);
                        break;
                }
            }
            return AddTabs(2) + result;
        }

        /// <summary>
        /// Generates the CodeBehind for the Editor
        /// </summary>
        /// <param name="pageName">The name of the page - can end with ASPX if you like but it will be stripped</param>
        /// <param name="providerName">The Data provider to use</param>
        /// <param name="tableName">Name of the table</param>
        /// <param name="languageType">Output language, i.e C# or that other one</param>
        /// <returns></returns>
        public static string GenerateCode(string pageName, string providerName, string tableName, LanguageType languageType)
        {
            //Grab the tableschema
            TableSchema.Table tbl = DataService.GetTableSchema(tableName, providerName);
            string pageTemplate = ResourceHelper.GetString(TemplateName.EDITOR_CODE);
            /*
            #NAMESPACE_USING# = if there is more than one provider, include this Using statement
            #PAGEBINDLIST# = The list that binds the page to the object
            #BINDLIST# = List that binds the object to the page
            #DROPLIST# = Loads each dropdown
            #CLASSNAME# = the name of the class
            */

            //make sure the providers are loaded
            DataService.LoadProviders();

            //Set the Namespace
            string namespaceUsing;
            //if (DataService.Databases.Count > 1)
            //{
                //have to use the namespace
                namespaceUsing = "using " + Utility.CheckNamingRules(tbl.Provider) + ";";
            //}
            pageTemplate = pageTemplate.Replace(TemplateVariable.NAMESPACE_USING, namespaceUsing);

            //Set the class name
            string className = tbl.ClassName;
            pageTemplate = pageTemplate.Replace(TemplateVariable.CLASS_NAME, className);

            //Set the page class name
            string pageClass = pageName.Replace(FileExtension.DOT_ASPX, String.Empty);
            pageTemplate = pageTemplate.Replace(TemplateVariable.PAGE_CLASS, pageClass);


            //now loop out the columns for each row of the table editor and grid
            StringBuilder bindRows = new StringBuilder();
            StringBuilder pageBindRows = new StringBuilder();
            StringBuilder dropList = new StringBuilder();

            foreach (TableSchema.TableColumn col in tbl.Columns)
            {
                string controlName = col.PropertyName;

                if (!col.IsPrimaryKey)
                {
                    if(col.IsForeignKey)
                    {
                        //dropdown lists

                        TableSchema.Table FKTable = DataService.GetForeignKeyTable(col, tbl);
                        if(FKTable != null)
                        {
                            dropList.AppendLine(AddTabs(2) + "Query qry" + controlName + " = " + FKTable.ClassName + ".CreateQuery();");
                            dropList.AppendLine(AddTabs(2) + "qry" + controlName + ".OrderBy = OrderBy.Asc(\"" + FKTable.Columns[1].ColumnName + "\");");
                            dropList.AppendLine(AddTabs(2) + "Utility.LoadDropDown(" + controlName + ", " + "qry" + controlName + ".ExecuteReader(), true);");
                            if(col.IsNullable)
                            {
                                dropList.AppendLine(AddTabs(2) + controlName + ".Items.Insert(0, new ListItem(\"(Not Specified)\", String.Empty));");
                            }
                        }
                    }
                    pageBindRows.AppendLine(SetControlValue(col, className));
                    if(col.DataType != DbType.Binary && col.DataType != DbType.Byte)
                    {
                        bindRows.AppendLine(GetControlValue(col, className));
                    }
                }
            }
            
            pageTemplate = pageTemplate.Replace(TemplateVariable.BIND_LIST, bindRows.ToString());
            pageTemplate = pageTemplate.Replace(TemplateVariable.PAGE_BIND_LIST, pageBindRows.ToString());
            pageTemplate = pageTemplate.Replace(TemplateVariable.DROP_LIST, dropList.ToString());
            

            return pageTemplate;

        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions