using System;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Xml.Serialization;
using SubSonic.Utilities;
using System.Web.UI.WebControls;
namespace SubSonic
{
/// <summary>
/// Base class for persisting objects. Follows the "Active Record Design Pattern".
/// You can read more on this pattern at http://en.wikipedia.org/wiki/Active_Record
/// </summary>
/// <typeparam name="T"></typeparam>
[Serializable]
public abstract class AbstractRecord<T> where T : AbstractRecord<T>, new()
{
#region State Properties
public virtual void Initialize()
{
}
protected virtual void Loaded()
{
}
private bool _isLoaded = false;
[XmlIgnore]
[HiddenForDataBinding(true)]
public bool IsLoaded
{
get { return _isLoaded; }
set { _isLoaded = value; }
}
internal bool _isNew = true; // ML Fix: VB is case insensitive; field name must not be the same as the property name.
/// <summary>
/// True if data in the object needs to be saved
/// </summary>
[XmlIgnore]
[HiddenForDataBinding(true)]
public bool IsNew
{
get { return _isNew; }
set { _isNew = value; }
}
/// <summary>
/// Automatically called upon object creation. Sets IsNew to true;
/// </summary>
public void MarkNew()
{
_isNew = true;
}
/// <summary>
/// True if data in the object has been changed and differs from DB.
/// </summary>
[XmlIgnore]
[HiddenForDataBinding(true)]
public bool IsDirty
{
get { return columnSettings.IsDirty; }
}
/// <summary>
/// Called after any property is set. Sets IsDirty to True.
/// </summary>
public void MarkClean()
{
columnSettings.IsDirty = false;
}
public void MarkOld()
{
_isNew = false;
}
private string tableName;
/// <summary>
/// Name of the table
/// </summary>
[XmlIgnore]
[HiddenForDataBinding(true)]
public string TableName
{
get { return tableName; }
protected set { tableName = value; }
}
#endregion
#region Object Overrides
public string Inspect()
{
return Inspect(true);
}
public string Inspect(bool useHtml)
{
StringBuilder sb = new StringBuilder();
string sOut;
if(useHtml)
{
sb.Append("<table><tr><td colspan=2><h3>" + BaseSchema.Name + " Inspection</h3></td></tr>");
foreach(TableSchema.TableColumn col in BaseSchema.Columns)
{
sb.Append("<tr><td><span style=\"font-weight:bold\">" + col.ColumnName + "</span></td><td>" + GetColumnValue<object>(col.ColumnName) + "</td></tr>");
}
sb.Append("</table>");
sOut = sb.ToString();
}
else
{
sb.AppendLine("#################" + BaseSchema.Name + " Inspection ####################");
foreach(TableSchema.TableColumn col in BaseSchema.Columns)
{
sb.AppendLine(col.ColumnName + ": " + GetColumnValue<object>(col.ColumnName));
}
sb.AppendLine("#############################################################################");
sOut = sb.ToString();
}
return sOut;
}
public override string ToString()
{
//return the value in the second column
//as by our convention, this is the "descriptor" column.
string result = "";
if(columnSettings != null)
{
if(columnSettings.Count > 1)
{
result = columnSettings[1].CurrentValue.ToString();
}
else if(columnSettings.Count == 1)
{
result = columnSettings[0].CurrentValue.ToString();
}
}
return result;
}
#endregion
#region DB Properties/Methods
/// <summary>
/// Returns a default setting per data type
/// </summary>
/// <param name="column"></param>
/// <returns></returns>
protected static object GetDefaultSetting(TableSchema.TableColumn column)
{
return Utility.GetDefaultSetting(column);
}
public DbType GetDBType(string columnName)
{
TableSchema.TableColumn col = BaseSchema.GetColumn(columnName);
return col.DataType;
}
protected static TableSchema.Table table;
/// <summary>
/// The base static class that holds all schema info for the table.
/// The class must be instanced at least once to populate this table.
/// </summary>
protected static TableSchema.Table BaseSchema
{
get
{
if(table == null)
//if (!IsSchemaInitialized)
{
new T();
}
return table;
}
set { table = value; }
}
protected static bool IsSchemaInitialized
{
get { return (table != null && table.Columns != null && table.Columns.Count > 0); }
}
/// <summary>
/// Sets the Primary Key of the object
/// </summary>
/// <param name="oValue"></param>
protected void SetPrimaryKey(object oValue)
{
columnSettings.SetValue(BaseSchema.PrimaryKey.ColumnName, oValue);
}
/// <summary>
/// Returns the current value of the primary key
/// </summary>
/// <returns></returns>
public object GetPrimaryKeyValue()
{
//return columnSettings.GetValue(table.PrimaryKey.ColumnName).ToString();
return columnSettings.GetValue<object>(BaseSchema.PrimaryKey.ColumnName);
}
/// <summary>
/// The column settings hold the current values of the object in a collection
/// so that reflection is not needed in the base class to fill out the commands
/// </summary>
private TableSchema.TableColumnSettingCollection columnSettings = null;
public void SetColumnValue(string columnName, object oValue)
{
if(columnSettings == null)
{
columnSettings = new TableSchema.TableColumnSettingCollection();
}
columnSettings.SetValue(columnName, oValue);
}
/// <summary>
/// Returns the current value of a column.
/// </summary>
/// <param name="columnName"></param>
/// <returns></returns>
public CT GetColumnValue<CT>(string columnName)
{
CT oOut = default(CT);
if(columnSettings != null)
{
oOut = columnSettings.GetValue<CT>(columnName);
}
return oOut;
}
private string _providerName;
[XmlIgnore]
[HiddenForDataBinding(true)]
public string ProviderName
{
get { return _providerName; }
protected set { _providerName = value; }
}
public TableSchema.Table GetSchema()
{
return BaseSchema;
}
#endregion
public static Query Query()
{
new T();
return new Query(table);
}
protected virtual void SetDefaults()
{
//initialize to default settings
bool setDefault = true;
bool setDbDefaults = DataService.GetInstance(ProviderName).SetPropertyDefaultsFromDatabase;
if(DataService.GetInstance(ProviderName).CurrentSharedConnection != null)
{
setDefault = DataService.GetInstance(ProviderName).CurrentSharedConnection.State == ConnectionState.Closed;
}
if (setDefault)
{
foreach(TableSchema.TableColumn col in BaseSchema.Columns)
{
if(setDbDefaults && !String.IsNullOrEmpty(col.DefaultSetting))
{
if(!Utility.IsMatch(col.DefaultSetting, SqlSchemaVariable.DEFAULT))
{
QueryCommand cmdDefault = new QueryCommand(SqlFragment.SELECT + col.DefaultSetting, col.Table.Provider.Name);
SetColumnValue(col.ColumnName, DataService.ExecuteScalar(cmdDefault));
}
}
else
{
SetColumnValue(col.ColumnName, Utility.GetDefaultSetting(col));
}
}
}
Initialize();
}
protected void ForceDefaults()
{
foreach (TableSchema.TableColumn col in BaseSchema.Columns)
{
if (!String.IsNullOrEmpty(col.DefaultSetting))
{
if (!Utility.IsMatch(col.DefaultSetting, SqlSchemaVariable.DEFAULT))
{
QueryCommand cmdDefault = new QueryCommand(SqlFragment.SELECT + col.DefaultSetting, col.Table.Provider.Name);
SetColumnValue(col.ColumnName, DataService.ExecuteScalar(cmdDefault));
}
}
else
{
SetColumnValue(col.ColumnName, Utility.GetDefaultSetting(col));
}
}
}
public void LoadByParam(string columnName, object paramValue)
{
MarkOld();
IDataReader rdr = null;
try
{
rdr = new Query(BaseSchema).AddWhere(columnName, paramValue).ExecuteReader();
if(rdr.Read())
{
Load(rdr);
}
else
{
//if no records, this is new still
MarkNew();
}
}
finally
{
if(rdr != null)
{
rdr.Close();
}
}
}
public void LoadByKey(object keyID)
{
MarkOld();
IDataReader rdr = null;
try
{
Query q = new Query(BaseSchema).AddWhere(BaseSchema.PrimaryKey.ColumnName, keyID);
//CheckLogicalDelete(q);
rdr = q.ExecuteReader();
if(rdr.Read())
{
Load(rdr);
}
else
{
//if no records, this is new still
MarkNew();
}
}
finally
{
if(rdr != null)
{
rdr.Close();
}
}
}
#region Serializers
public string ToXML()
{
Type type = typeof(T);
XmlSerializer ser = new XmlSerializer(type);
using(System.IO.MemoryStream stm = new System.IO.MemoryStream())
{
//serialize to a memory stream
ser.Serialize(stm, this);
//reset to beginning so we can read it.
stm.Position = 0;
//Convert a string.
using(System.IO.StreamReader stmReader = new System.IO.StreamReader(stm))
{
string xmlData = stmReader.ReadToEnd();
return xmlData;
}
}
}
/// <summary>
/// Returns an object based on the passed-in XML.
/// </summary>
/// <param name="xml"></param>
/// <returns></returns>
public object NewFromXML(string xml)
{
object oOut = null;
Type type = typeof(T);
//hydrate based on private string var
if(xml.Length > 0)
{
XmlSerializer serializer = new XmlSerializer(type);
StringBuilder sb = new StringBuilder();
sb.Append(xml);
System.IO.StringReader sReader = new System.IO.StringReader(xml);
oOut = serializer.Deserialize(sReader);
//sb = null;
sReader.Close();
}
return oOut;
}
#endregion
#region CommandMethods
public QueryCommand GetSelectCommand()
{
Query q = new Query(BaseSchema);
q.QueryType = QueryType.Select;
QueryCommand cmd = DataService.BuildCommand(q);
return cmd;
}
#endregion
#region Loaders
protected void SetLoadState()
{
IsLoaded = true;
IsNew = false;
Loaded();
}
/// <summary>
/// Loads the object with the current reader's values. Assumes the reader is already moved to
/// first position in recordset (aka has been "Read()")
/// </summary>
/// <param name="rdr">The RDR.</param>
public virtual void Load(IDataReader rdr)
{
foreach(TableSchema.TableColumn col in BaseSchema.Columns)
{
try
{
SetColumnValue(col.ColumnName, rdr[col.ColumnName]);
}
catch
{
throw new Exception("Unable to set column value for " + col.ColumnName);
}
}
SetLoadState();
MarkClean();
}
/// <summary>
/// Loads the object with the current reader's values. Assumes the reader is already moved to
/// first position in recordset (aka has been "Read()")
/// </summary>
/// <param name="tbl"></param>
public virtual void Load(DataTable tbl)
{
if(tbl.Rows.Count > 0)
{
DataRow dr = tbl.Rows[0];
Load(dr);
}
}
/// <summary>
/// Loads the object with the current DataRow's values.
/// </summary>
/// <param name="dr"></param>
public virtual void Load(DataRow dr)
{
foreach(TableSchema.TableColumn col in BaseSchema.Columns)
{
try
{
SetColumnValue(col.ColumnName, dr[col.ColumnName]);
}
catch(Exception x)
{
//this will happen only if there's a reader error.
throw new Exception("Unable to set column value for " + col.ColumnName + "; " + x.Message);
}
}
SetLoadState();
}
/// <summary>
/// Opens the IDataReader, loads the object and closes the IDataReader. Unlike AbstractList.LoadAndCloseReader,
/// this method does not assume that reader is open and in the first position!
/// </summary>
/// <param name="rdr"></param>
public void LoadAndCloseReader(IDataReader rdr)
{
if(rdr.Read())
{
Load(rdr);
}
if(!rdr.IsClosed)
{
rdr.Close();
}
}
#endregion
#region Fetchers
/// <summary>
/// Returns all records for this table
/// </summary>
/// <returns>IDataReader</returns>
public static IDataReader FetchAll()
{
//makes sure the table schema is loaded
//new T();
//build the query
Query q = new Query(BaseSchema);
CheckLogicalDelete(q);
//load the reader
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
return rdr;
}
/// <summary>
/// Returns all records for this table, ordered
/// </summary>
/// <returns>Generic Typed List</returns>
/// <param name="orderBy">Column to order by</param>
public static IDataReader FetchAll(OrderBy orderBy)
{
//makes sure the table schema is loaded
//new T();
//build the query
Query q = new Query(BaseSchema);
CheckLogicalDelete(q);
q.OrderBy = orderBy;
//load the reader
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
return rdr;
}
/// <summary>
/// Returns all records for the given column/parameter, ordered by the passed in orderBy
/// The expression for this is always "column=parameter"
/// </summary>
/// <param name="columnName">Name of the column to use in parmeter statement</param>
/// <param name="oValue">Value of the column</param>
/// <param name="oValue">Column to order by</param>
/// <param name="orderBy">Ordering of results</param>
/// <returns>IDataReader</returns>
public static IDataReader FetchByParameter(string columnName, object oValue, OrderBy orderBy)
{
//makes sure the table schema is loaded
//new T();
//build the query
Query q = new Query(BaseSchema);
q.OrderBy = orderBy;
CheckLogicalDelete(q); //CheckLogicalDelete Should Always Be Called Before AddWhere!
q.AddWhere(columnName, oValue);
//load the reader
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
return rdr;
}
/// <summary>
/// Returns all records for the given column/parameter
/// The expression for this is always "column=parameter"
/// </summary>
/// <param name="columnName"></param>
/// <param name="oValue"></param>
/// <returns>IDataReader</returns>
public static IDataReader FetchByParameter(string columnName, object oValue)
{
//new T();
//build the query
Query q = new Query(BaseSchema);
CheckLogicalDelete(q); //CheckLogicalDelete Should Always Be Called Before AddWhere!
q.AddWhere(columnName, oValue);
//load the reader
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
//load up the list
return rdr;
}
/// <summary>
/// Returns all records for the given column/parameter
/// The expression for this is always "column=parameter"
/// </summary>
/// <param name="columnName"></param>
/// <param name="comparison"></param>
/// <param name="oValue"></param>
/// <returns>IDataReader</returns>
public static IDataReader FetchByParameter(string columnName, Comparison comparison, object oValue)
{
//new T();
//build the query
Query q = new Query(BaseSchema);
CheckLogicalDelete(q); //CheckLogicalDelete Should Always Be Called Before AddWhere!
q.AddWhere(columnName, comparison, oValue);
//load the reader
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
return rdr;
}
/// <summary>
/// Returns all records for the given column/parameter
/// The expression for this is always "column=parameter"
/// </summary>
/// <param name="columnName"></param>
/// <param name="comparison"></param>
/// <param name="oValue"></param>
/// <param name="orderBy"></param>
/// <returns>IDataReader</returns>
public static IDataReader FetchByParameter(string columnName, Comparison comparison, object oValue, OrderBy orderBy)
{
//new T();
//build the query
Query q = new Query(BaseSchema);
CheckLogicalDelete(q); //CheckLogicalDelete Should Always Be Called Before AddWhere!
q.AddWhere(columnName, comparison, oValue);
q.OrderBy = orderBy;
//load the reader
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
//load up the list
return rdr;
}
/// <summary>
/// Returns all records for the given query
/// </summary>
/// <returns>Generic Typed List</returns>
/// <param name="query">Query for complex records</param>
public static IDataReader FetchByQuery(Query query)
{
//makes sure the table schema is loaded
//new T();
CheckLogicalDelete(query);
//load the reader
IDataReader rdr = DataService.GetReader(query.BuildSelectCommand());
return rdr;
}
/// <summary>
/// Uses the passed-in object as a parameter set. Does not use the created/modified fields
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public static IDataReader Find(T item)
{
return Find(item, null);
}
public static IDataReader Find(T item, OrderBy orderBy)
{
//build the sql string and command statements at the same time
Query q = new Query(BaseSchema);
CheckLogicalDelete(q);
//retrieve data from database
foreach(TableSchema.TableColumn col in BaseSchema.Columns)
{
string columnName;
object columnValue;
columnName = col.ColumnName;
columnValue = item.GetColumnValue<object>(columnName);
if(!Utility.IsAuditField(columnName))
{
object defaultValue = String.Empty;
switch(col.DataType)
{
case DbType.Boolean:
defaultValue = false;
break;
case DbType.Currency:
case DbType.Decimal:
case DbType.Int16:
case DbType.Double:
case DbType.Int32:
defaultValue = 0;
break;
case DbType.Date:
case DbType.DateTime:
defaultValue = new DateTime(1900, 1, 1);
break;
case DbType.Guid:
defaultValue = Guid.Empty;
break;
}
if(columnValue != null)
{
if(!columnValue.Equals(defaultValue))
{
q.AddWhere(columnName, columnValue);
}
}
}
}
if(orderBy != null)
{
q.OrderBy = orderBy;
}
IDataReader rdr = DataService.GetReader(q.BuildSelectCommand());
return rdr;
}
#endregion
#region Utility
/// <summary>
/// Returns an ordered ListItemCollection for use with DropDowns, RadioButtonLists, and CheckBoxLists
/// Note: This method assumes that the column in the second position is the text value column
/// </summary>
/// <returns></returns>
public static ListItemCollection GetListItems()
{
//get the textColumn based on position
//which should be the second column of the table
//T item = new T();
string textColumn = BaseSchema.Columns[1].ColumnName;
return GetListItems(textColumn);
}
/// <summary>
/// Returns an ordered ListItemCollection for use with DropDowns, RadioButtonLists, and CheckBoxLists
/// </summary>
/// <param name="textColumn">The name of the column which should be used as the text value column</param>
/// <returns></returns>
public static ListItemCollection GetListItems(string textColumn)
{
//T item = new T();
ListItemCollection list = new ListItemCollection();
string pkCol = BaseSchema.PrimaryKey.ColumnName;
string textCol = BaseSchema.GetColumn(textColumn).ColumnName;
//run a query retrieving the two columns
Query q = new Query(BaseSchema);
q.SelectList = pkCol + "," + textCol;
q.OrderBy = OrderBy.Asc(textCol);
IDataReader rdr = q.ExecuteReader();
while(rdr.Read())
{
ListItem listItem = new ListItem(rdr[1].ToString(), rdr[0].ToString());
list.Add(listItem);
}
return list;
}
/// <summary>
/// If this object has a logical delete column, this method will append in the required parameter to avoid returning
/// deleted records
/// </summary>
/// <param name="q"></param>
internal static void CheckLogicalDelete(Query q)
{
//check the columns and see if there's a "deleted" or "isDeleted"
q.CheckLogicalDelete();
}
public TableSchema.TableColumnSettingCollection GetColumnSettings()
{
return columnSettings;
}
/// <summary>
/// Copies the current instance to a new instance
/// </summary>
/// <returns>New instance of current object</returns>
public T Clone()
{
//copy this instance to a new instance
T thisInstance = new T();
foreach(TableSchema.TableColumnSetting setting in columnSettings)
{
thisInstance.SetColumnValue(setting.ColumnName, setting.CurrentValue);
}
return thisInstance;
}
/// <summary>
/// Copies current instance to passed in instance
/// </summary>
/// <param name="copyInstance"></param>
public void CopyTo(T copyInstance)
{
if(copyInstance == null)
{
copyInstance = new T();
}
foreach(TableSchema.TableColumnSetting setting in columnSettings)
{
copyInstance.SetColumnValue(setting.ColumnName, setting.CurrentValue);
}
}
/// <summary>
/// Adds a new row to a Datatable with this record
/// You must be sure the column names are the same
/// </summary>
/// <param name="dataTable"></param>
public void CopyTo(DataTable dataTable)
{
DataRow newRow = dataTable.NewRow();
foreach(TableSchema.TableColumnSetting setting in columnSettings)
{
try
{
newRow[setting.ColumnName] = setting.CurrentValue;
}
catch
{
//swallow this - this is a forgiving procedure :)
}
}
dataTable.Rows.Add(newRow);
}
/// <summary>
/// Copies a record from a DataTable to this instance. Column names must match.
/// </summary>
/// <param name="row"></param>
public void CopyFrom(DataRow row)
{
foreach(TableSchema.TableColumnSetting setting in columnSettings)
{
try
{
setting.CurrentValue = row[setting.ColumnName];
}
catch
{
//swallow this - this is a forgiving procedure :)
}
}
}
/// <summary>
/// Copies the passed-in instance settings to this instance
/// </summary>
/// <param name="copyInstance"></param>
public void CopyFrom(T copyInstance)
{
if(copyInstance != null)
{
foreach(TableSchema.TableColumnSetting setting in copyInstance.columnSettings)
{
SetColumnValue(setting.ColumnName, setting.CurrentValue);
}
}
else
{
throw new Exception("Copy instance is null");
}
}
#endregion
#region WebUI Helper
private string nullExceptionMessage = "{0} requires a value";
[XmlIgnore]
[HiddenForDataBinding(true)]
public string NullExceptionMessage
{
get { return nullExceptionMessage; }
protected set { nullExceptionMessage = value; }
}
private string invalidTypeExceptionMessage = "{0} is not a valid {1}";
[XmlIgnore]
[HiddenForDataBinding(true)]
public string InvalidTypeExceptionMessage
{
get { return invalidTypeExceptionMessage; }
protected set { invalidTypeExceptionMessage = value; }
}
private string lengthExceptionMessage = "{0} exceeds the maximum length of {1}";
[XmlIgnore]
[HiddenForDataBinding(true)]
public string LengthExceptionMessage
{
get { return lengthExceptionMessage; }
protected set { lengthExceptionMessage = value; }
}
private System.Collections.Generic.List<string> errorList = new System.Collections.Generic.List<string>();
[HiddenForDataBinding(true)]
protected System.Collections.Generic.List<string> Errors
{
get { return errorList; }
}
public bool HasErrors() {
return errorList.Count > 0;
}
/// <summary>
/// Loops the underlying settings collection to validate type, nullability, and length
/// </summary>
public void ValidateColumnSettings()
{
//loop the current settings
//make sure they are valid for their type
foreach(TableSchema.TableColumnSetting setting in GetColumnSettings())
{
//Utility.WriteTrace("Validating " + setting.ColumnName);
object settingValue = setting.CurrentValue;
TableSchema.TableColumn col = table.GetColumn(setting.ColumnName);
if(!col.IsReadOnly)
{
string formattedName = Utility.ParseCamelToProper(col.ColumnName);
Type t = col.GetPropertyType();
//Convert the existing value to the type for this column
//if there's an error, report it.
//OK to bypass if the column is nullable and this setting is null
//just check for now if the value isn't null - it will be checked
//later for nullability
if(!col.IsNullable && settingValue != null && settingValue != DBNull.Value)
{
try
{
if(col.DataType != DbType.Guid)
{
Convert.ChangeType(settingValue, t);
}
}
catch
{
//there's a conversion problem here
//add it to the Exception List<>
if(col.IsNumeric)
{
errorList.Add(String.Format(InvalidTypeExceptionMessage, formattedName, "number"));
}
else if(col.IsDateTime)
{
errorList.Add(String.Format(InvalidTypeExceptionMessage, formattedName, "date"));
}
else
{
errorList.Add(String.Format(InvalidTypeExceptionMessage, formattedName, "value"));
}
}
}
//now make sure that this column's null settings match with what's in the setting
//Utility.WriteTrace("Testing nullability of " + setting.ColumnName);
if(!col.IsNullable && (settingValue == null || settingValue == DBNull.Value))
{
//Utility.WriteTrace("Null Error Caught " + setting.ColumnName);
errorList.Add(String.Format(NullExceptionMessage, formattedName));
}
//finally, check the length
//Utility.WriteTrace("Testing Max Length of " + setting.ColumnName);
if((settingValue != null && settingValue != DBNull.Value) && col.MaxLength > 0)
{
if(col.DataType != DbType.Boolean && settingValue.ToString().Length > col.MaxLength)
{
//Utility.WriteTrace("Max Length Exceeded " + col.ColumnName + " can't exceed " + col.MaxLength + "; current value is set to " + settingValue.ToString().Length);
errorList.Add(String.Format(LengthExceptionMessage, formattedName, col.MaxLength));
}
}
}
}
}
/// <summary>
/// Loads your object from a form postback
/// </summary>
public void LoadFromPost()
{
LoadFromPost(true);
}
/// <summary>
/// Loads your object from a form postback
/// </summary>
/// <param name="validatePost">Set this to false to skip validation</param>
public void LoadFromPost(bool validatePost)
{
if(System.Web.HttpContext.Current != null)
{
//use Request.form, since the ControlCollection can return weird results based on
//the container structure.
System.Collections.Specialized.NameValueCollection formPost = System.Web.HttpContext.Current.Request.Form;
TableSchema.TableColumnSettingCollection settings = GetColumnSettings();
if(formPost != null && settings != null)
{
foreach(string s in formPost.AllKeys)
{
//Utility.WriteTrace("Looking at form field " + s);
foreach(TableSchema.TableColumnSetting setting in settings)
{
if(s.ToLower().EndsWith("_" + setting.ColumnName.ToLower()) || s.ToLower().EndsWith("$" + setting.ColumnName.ToLower()) || s.ToLower().Equals(setting.ColumnName.ToLower()))
{
setting.CurrentValue = formPost[s];
//Utility.WriteTrace("Matched " + s + " to " + setting.ColumnName);
}
}
}
}
//validate the settings, since we're setting the object values here, not
//using the accessors as we should be.
if(validatePost)
{
ValidateColumnSettings();
if(errorList.Count > 0)
{
//format this for the web
if(System.Web.HttpContext.Current != null)
{
//decorate the output
string errorReport = "<b>Validation Error:<b><ul>";
foreach(string s in errorList)
{
errorReport += "<li><i>" + s + "</i></li>";
}
errorReport += "</ul>";
throw new Exception(errorReport);
}
else
{
throw new Exception("Validation error - catch this and check the ExceptionList property to review the exceptions. You can change the output message as needed by accessing the ExceptionMessage properties of this object");
}
}
}
}
}
#endregion
}
[AttributeUsage(AttributeTargets.Property)]
sealed class HiddenForDataBindingAttribute : Attribute
{
private bool _isHidden;
public HiddenForDataBindingAttribute()
{
}
public HiddenForDataBindingAttribute(bool isHidden)
{
_isHidden = isHidden;
}
public bool IsHidden
{
get { return _isHidden; }
}
}
}