namespace System.Web.DynamicData.Util { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Web.Resources; using System.Web.UI; using System.ComponentModel; using IDataBoundControlInterface = System.Web.UI.WebControls.IDataBoundControl; internal static class MetaTableHelper { private static object s_mappingKey = new object(); internal static Dictionary GetMapping(HttpContextBase httpContext) { Dictionary mapping = httpContext.Items[s_mappingKey] as Dictionary; if (mapping == null) { mapping = new Dictionary(); httpContext.Items[s_mappingKey] = mapping; } return mapping; } /// /// Gets a table from the mapping. Does not throw. /// internal static MetaTable GetTableFromMapping(HttpContextBase httpContext, object control) { IDictionary mapping = GetMapping(httpContext); // don't throw if no mapping found MappingInfo mappingInfo; if (mapping.TryGetValue(control, out mappingInfo)) { return mappingInfo.Table; } return null; } private static MappingInfo GetMappingInfo(object control, HttpContextBase httpContext) { IDictionary mapping = GetMapping(httpContext); MappingInfo mappingInfo; if (!mapping.TryGetValue(control, out mappingInfo)) { mappingInfo = new MappingInfo(); mapping[control] = mappingInfo; } return mappingInfo; } internal static void SetTableInMapping(HttpContextBase httpContext, object control, MetaTable table, IDictionary defaultValues) { MappingInfo mappingInfo = GetMappingInfo(control, httpContext); mappingInfo.Table = table; if (defaultValues != null) { mappingInfo.DefaultValueMapping = new DefaultValueMapping(defaultValues); } } internal static MetaTable GetTableWithFullFallback(IDataSource dataSource, HttpContextBase context) { MetaTable table = GetTableFromMapping(context, dataSource); if (table != null) { return table; } IDynamicDataSource dynamicDataSource = dataSource as IDynamicDataSource; if (dynamicDataSource != null) { table = GetTableFromDynamicDataSource(dynamicDataSource); if (table != null) { return table; } } table = DynamicDataRouteHandler.GetRequestMetaTable(context); if (table != null) { return table; } Control c = dataSource as Control; string id = (c != null ? c.ID : String.Empty); throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, DynamicDataResources.MetaTableHelper_CantFindTable, id)); } internal static MetaTable GetMetaTableFromObject(object dataSource) { IEnumerable enumerable = dataSource as IEnumerable; if (enumerable == null) { return null; } // Use the first item to determine the type // foreach (object o in enumerable) { if (o != null) { return MetaTable.GetTable(o.GetType()); } } return null; } /// Gets a table from an IDynamicDataSource's ContextType and EntitySetName. /// Does not throw, returns null on failure. internal static MetaTable GetTableFromDynamicDataSource(IDynamicDataSource dynamicDataSource) { string tableName = dynamicDataSource.EntitySetName; Type contextType = dynamicDataSource.ContextType; if (contextType == null || String.IsNullOrEmpty(tableName)) { return null; } MetaModel model; if (MetaModel.MetaModelManager.TryGetModel(contextType, out model)) { Debug.Assert(model != null); MetaTable table; if (model.TryGetTable(tableName, out table)) { return table; } } return null; } internal static MetaTable FindMetaTable(Control current) { return FindMetaTable(current, HttpContext.Current.ToWrapper()); } internal static DefaultValueMapping GetDefaultValueMapping(Control current, HttpContextBase context) { IDictionary mapping = GetMapping(context); if (!(current is INamingContainer)) { current = current.NamingContainer; } for (; current != null; current = current.NamingContainer) { MappingInfo mappingInfo; // If we find a mapping then return that value if (mapping.TryGetValue(current, out mappingInfo)) { return mappingInfo.DefaultValueMapping; } } return null; } internal static MetaTable FindMetaTable(Control current, HttpContextBase context) { MetaTable table = null; // Start from the first naming container if (!(current is INamingContainer)) { current = current.NamingContainer; } for (; current != null; current = current.NamingContainer) { // Find the first table mapped to a control table = GetTableFromMapping(context, current); if (table != null) { return table; } IDataBoundControlInterface dataBoundControl = DataControlHelper.GetDataBoundControl(current, false /*failIfNotFound*/); // Not a data control: continue searching if (dataBoundControl == null) { continue; } IDataSource dataSourceControl = dataBoundControl.DataSourceObject; // Check if it's associated with a DataSource or can be retrieved from the current route if (dataSourceControl != null) { return GetTableWithFullFallback(dataSourceControl, context); } // Check if it has a datasource (i.e. not a control, but directly some data) object dataSource = dataBoundControl.DataSource; if (dataSource != null) { // Try to get a MetaTable from it. If so, we're done table = GetMetaTableFromObject(dataSource); if (table != null) { return table; } } } return null; } } }