2 // System.Web.UI.WebControls.ObjectDataSourceView
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // (C) 2005 Novell, Inc. (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Reflection;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.ComponentModel;
39 using System.Web.Compilation;
41 namespace System.Web.UI.WebControls
44 public class ObjectDataSourceView : DataSourceView, IStateManager
46 ObjectDataSource owner;
51 bool convertNullToDBNull = false;
52 bool enablePaging = false;
53 string dataObjectTypeName = null;
54 string filterExpression = null;
55 string maximumRowsParameterName = null;
56 string oldValuesParameterFormatString = null;
57 string deleteMethod = null;
58 string insertMethod = null;
59 string selectCountMethod = null;
60 string selectMethod = null;
61 string sortParameterName = null;
62 string startRowIndexParameterName = null;
63 string typeName = null;
64 string updateMethod = null;
66 bool isTrackingViewState = false;
67 ParameterCollection selectParameters;
68 ParameterCollection updateParameters;
69 ParameterCollection deleteParameters;
70 ParameterCollection insertParameters;
71 ParameterCollection filterParameters;
73 static readonly object DeletedEvent = new object();
74 static readonly object DeletingEvent = new object();
75 static readonly object FilteringEvent = new object();
76 static readonly object InsertedEvent = new object();
77 static readonly object InsertingEvent = new object();
78 static readonly object ObjectCreatedEvent = new object();
79 static readonly object ObjectCreatingEvent = new object();
80 static readonly object ObjectDisposingEvent = new object();
81 // static readonly object ResolvingMethodEvent = new object();
82 static readonly object SelectedEvent = new object();
83 static readonly object SelectingEvent = new object();
84 static readonly object UpdatedEvent = new object();
85 static readonly object UpdatingEvent = new object();
87 public ObjectDataSourceView (ObjectDataSource owner, string name, HttpContext context): base (owner, name)
90 this.context = context;
93 public event ObjectDataSourceStatusEventHandler Deleted {
94 add { Events.AddHandler (DeletedEvent, value); }
95 remove { Events.RemoveHandler (DeletedEvent, value); }
98 public event ObjectDataSourceMethodEventHandler Deleting {
99 add { Events.AddHandler (DeletingEvent, value); }
100 remove { Events.RemoveHandler (DeletingEvent, value); }
103 public event ObjectDataSourceFilteringEventHandler Filtering {
104 add { Events.AddHandler (FilteringEvent, value); }
105 remove { Events.RemoveHandler (FilteringEvent, value); }
108 public event ObjectDataSourceStatusEventHandler Inserted {
109 add { Events.AddHandler (InsertedEvent, value); }
110 remove { Events.RemoveHandler (InsertedEvent, value); }
113 public event ObjectDataSourceMethodEventHandler Inserting {
114 add { Events.AddHandler (InsertingEvent, value); }
115 remove { Events.RemoveHandler (InsertingEvent, value); }
118 public event ObjectDataSourceObjectEventHandler ObjectCreated {
119 add { Events.AddHandler (ObjectCreatedEvent, value); }
120 remove { Events.RemoveHandler (ObjectCreatedEvent, value); }
123 public event ObjectDataSourceObjectEventHandler ObjectCreating {
124 add { Events.AddHandler (ObjectCreatingEvent, value); }
125 remove { Events.RemoveHandler (ObjectCreatingEvent, value); }
128 public event ObjectDataSourceDisposingEventHandler ObjectDisposing {
129 add { Events.AddHandler (ObjectDisposingEvent, value); }
130 remove { Events.RemoveHandler (ObjectDisposingEvent, value); }
133 /* public event ObjectDataSourceResolvingMethodEventHandler ResolvingMethod {
134 add { Events.AddHandler (ResolvingMethodEvent, value); }
135 remove { Events.RemoveHandler (ResolvingMethodEvent, value); }
138 public event ObjectDataSourceStatusEventHandler Selected {
139 add { Events.AddHandler (SelectedEvent, value); }
140 remove { Events.RemoveHandler (SelectedEvent, value); }
143 public event ObjectDataSourceSelectingEventHandler Selecting {
144 add { Events.AddHandler (SelectingEvent, value); }
145 remove { Events.RemoveHandler (SelectingEvent, value); }
148 public event ObjectDataSourceStatusEventHandler Updated {
149 add { Events.AddHandler (UpdatedEvent, value); }
150 remove { Events.RemoveHandler (UpdatedEvent, value); }
153 public event ObjectDataSourceMethodEventHandler Updating {
154 add { Events.AddHandler (UpdatingEvent, value); }
155 remove { Events.RemoveHandler (UpdatingEvent, value); }
158 protected virtual void OnDeleted (ObjectDataSourceStatusEventArgs e)
160 if (Events != null) {
161 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [DeletedEvent];
162 if (eh != null) eh (this, e);
166 protected virtual void OnDeleting (ObjectDataSourceMethodEventArgs e)
168 if (Events != null) {
169 ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [DeletingEvent];
170 if (eh != null) eh (this, e);
174 protected virtual void OnFiltering (ObjectDataSourceFilteringEventArgs e)
176 if (Events != null) {
177 ObjectDataSourceFilteringEventHandler eh = (ObjectDataSourceFilteringEventHandler) Events [FilteringEvent];
178 if (eh != null) eh (this, e);
182 protected virtual void OnInserted (ObjectDataSourceStatusEventArgs e)
184 if (Events != null) {
185 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [InsertedEvent];
186 if (eh != null) eh (this, e);
190 protected virtual void OnInserting (ObjectDataSourceMethodEventArgs e)
192 if (Events != null) {
193 ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [InsertingEvent];
194 if (eh != null) eh (this, e);
198 protected virtual void OnObjectCreated (ObjectDataSourceEventArgs e)
200 if (Events != null) {
201 ObjectDataSourceObjectEventHandler eh = (ObjectDataSourceObjectEventHandler) Events [ObjectCreatedEvent];
202 if (eh != null) eh (this, e);
206 protected virtual void OnObjectCreating (ObjectDataSourceEventArgs e)
208 if (Events != null) {
209 ObjectDataSourceObjectEventHandler eh = (ObjectDataSourceObjectEventHandler) Events [ObjectCreatingEvent];
210 if (eh != null) eh (this, e);
214 protected virtual void OnObjectDisposing (ObjectDataSourceDisposingEventArgs e)
216 if (Events != null) {
217 ObjectDataSourceDisposingEventHandler eh = (ObjectDataSourceDisposingEventHandler) Events [ObjectDisposingEvent];
218 if (eh != null) eh (this, e);
222 /* protected virtual void OnResolvingMethod (ObjectDataSourceResolvingMethodEventArgs e)
224 if (Events != null) {
225 ObjectDataSourceResolvingMethodEventHandler eh = (ObjectDataSourceResolvingMethodEventHandler) Events [ResolvingMethodEvent];
226 if (eh != null) eh (this, e);
231 protected virtual void OnSelected (ObjectDataSourceStatusEventArgs e)
233 if (Events != null) {
234 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [SelectedEvent];
235 if (eh != null) eh (this, e);
239 protected virtual void OnSelecting (ObjectDataSourceSelectingEventArgs e)
241 if (Events != null) {
242 ObjectDataSourceSelectingEventHandler eh = (ObjectDataSourceSelectingEventHandler) Events [SelectingEvent];
243 if (eh != null) eh (this, e);
247 protected virtual void OnUpdated (ObjectDataSourceStatusEventArgs e)
249 if (Events != null) {
250 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [UpdatedEvent];
251 if (eh != null) eh (this, e);
255 protected virtual void OnUpdating (ObjectDataSourceMethodEventArgs e)
257 if (Events != null) {
258 ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [UpdatingEvent];
259 if (eh != null) eh (this, e);
263 public override bool CanDelete {
264 get { return DeleteMethod.Length > 0; }
267 public override bool CanInsert {
268 get { return InsertMethod.Length > 0; }
271 public override bool CanPage {
272 get { return EnablePaging; }
275 public override bool CanRetrieveTotalRowCount {
277 if( SelectCountMethod.Length > 0)
280 return !EnablePaging;
284 public override bool CanSort {
288 public override bool CanUpdate {
289 get { return UpdateMethod.Length > 0; }
292 // LAME SPEC: MSDN says value should be stored in ViewState but tests show otherwise.
293 ConflictOptions conflictDetection = ConflictOptions.OverwriteChanges;
294 public ConflictOptions ConflictDetection {
295 get { return conflictDetection; }
297 if (ConflictDetection == value)
299 conflictDetection = value;
300 OnDataSourceViewChanged (EventArgs.Empty);
304 public bool ConvertNullToDBNull {
305 get { return convertNullToDBNull; }
306 set { convertNullToDBNull = value; }
309 public string DataObjectTypeName {
311 return dataObjectTypeName != null ? dataObjectTypeName : string.Empty;
314 if (DataObjectTypeName == value)
316 dataObjectTypeName = value;
317 dataObjectType = null;
318 OnDataSourceViewChanged (EventArgs.Empty);
322 public string DeleteMethod {
324 return deleteMethod != null ? deleteMethod : string.Empty;
327 deleteMethod = value;
331 public ParameterCollection DeleteParameters {
333 if (deleteParameters == null) {
334 deleteParameters = new ParameterCollection ();
336 return deleteParameters;
340 public bool EnablePaging {
345 if (EnablePaging == value)
347 enablePaging = value;
348 OnDataSourceViewChanged (EventArgs.Empty);
352 public string FilterExpression {
354 return filterExpression != null ? filterExpression : string.Empty;
357 if (FilterExpression == value)
359 filterExpression = value;
360 OnDataSourceViewChanged (EventArgs.Empty);
364 public ParameterCollection FilterParameters {
366 if (filterParameters == null) {
367 filterParameters = new ParameterCollection ();
368 filterParameters.ParametersChanged += new EventHandler (OnParametersChanged);
369 if (IsTrackingViewState)
370 ((IStateManager)filterParameters).TrackViewState ();
372 return filterParameters;
376 public string InsertMethod {
378 return insertMethod != null ? insertMethod : string.Empty;
381 insertMethod = value;
385 public ParameterCollection InsertParameters {
387 if (insertParameters == null) {
388 insertParameters = new ParameterCollection ();
390 return insertParameters;
394 public string MaximumRowsParameterName {
396 return maximumRowsParameterName != null ? maximumRowsParameterName : "maximumRows";
399 if (MaximumRowsParameterName == value)
401 maximumRowsParameterName = value;
402 OnDataSourceViewChanged (EventArgs.Empty);
406 public string OldValuesParameterFormatString {
408 return oldValuesParameterFormatString != null ? oldValuesParameterFormatString : "{0}";
411 if (OldValuesParameterFormatString == value)
413 oldValuesParameterFormatString = value;
414 OnDataSourceViewChanged (EventArgs.Empty);
418 public string SelectCountMethod {
420 return selectCountMethod != null ? selectCountMethod : string.Empty;
423 if (SelectCountMethod == value)
425 selectCountMethod = value;
426 OnDataSourceViewChanged (EventArgs.Empty);
430 public string SelectMethod {
432 return selectMethod != null ? selectMethod : string.Empty;
435 if (SelectMethod == value)
437 selectMethod = value;
438 OnDataSourceViewChanged (EventArgs.Empty);
442 public ParameterCollection SelectParameters {
444 if (selectParameters == null) {
445 selectParameters = new ParameterCollection ();
446 selectParameters.ParametersChanged += new EventHandler (OnParametersChanged);
447 if (IsTrackingViewState)
448 ((IStateManager)selectParameters).TrackViewState ();
450 return selectParameters;
454 public string SortParameterName {
456 return sortParameterName != null ? sortParameterName : string.Empty;
459 sortParameterName = value;
463 public string StartRowIndexParameterName {
465 return startRowIndexParameterName != null ? startRowIndexParameterName : "startRowIndex";
468 if (StartRowIndexParameterName == value)
470 startRowIndexParameterName = value;
471 OnDataSourceViewChanged (EventArgs.Empty);
475 public string TypeName {
477 return typeName != null ? typeName : string.Empty;
480 if (TypeName == value)
484 OnDataSourceViewChanged (EventArgs.Empty);
488 public string UpdateMethod {
490 return updateMethod != null ? updateMethod : string.Empty;
493 updateMethod = value;
497 public ParameterCollection UpdateParameters {
499 if (updateParameters == null) {
500 updateParameters = new ParameterCollection ();
502 return updateParameters;
508 if (objectType == null) {
509 objectType = HttpApplication.LoadType (TypeName);
510 if (objectType == null)
511 throw new InvalidOperationException ("Type not found: " + TypeName);
517 Type DataObjectType {
519 if (dataObjectType == null) {
520 dataObjectType = HttpApplication.LoadType (DataObjectTypeName);
521 if (dataObjectType == null)
522 throw new InvalidOperationException ("Type not found: " + DataObjectTypeName);
524 return dataObjectType;
528 public IEnumerable Select (DataSourceSelectArguments arguments)
530 return ExecuteSelect (arguments);
533 public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
535 return ExecuteUpdate (keys, values, oldValues);
538 public int Delete (IDictionary keys, IDictionary oldValues)
540 return ExecuteDelete (keys, oldValues);
543 public int Insert (IDictionary values)
545 return ExecuteInsert (values);
548 protected override int ExecuteInsert (IDictionary values)
551 throw new NotSupportedException ("Insert operation not supported.");
553 IOrderedDictionary paramValues;
556 if (DataObjectTypeName.Length == 0) {
557 paramValues = MergeParameterValues (InsertParameters, values, null);
558 method = GetObjectMethod (InsertMethod, paramValues, DataObjectMethodType.Insert);
560 method = ResolveDataObjectMethod (InsertMethod, values, null, out paramValues);
563 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
568 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
571 if (rargs.Exception != null && !rargs.ExceptionHandled)
572 throw rargs.Exception;
574 if (owner.EnableCaching)
575 owner.Cache.Expire ();
577 OnDataSourceViewChanged (EventArgs.Empty);
582 protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
585 throw new NotSupportedException ("Delete operation not supported.");
587 if (ConflictDetection == ConflictOptions.CompareAllValues && (oldValues == null || oldValues.Count == 0))
588 throw new InvalidOperationException ("ConflictDetection is set to CompareAllValues and oldValues collection is null or empty.");
590 IDictionary oldDataValues;
591 oldDataValues = BuildOldValuesList (keys, oldValues, false);
593 IOrderedDictionary paramValues;
596 if (DataObjectTypeName.Length == 0) {
597 paramValues = MergeParameterValues (DeleteParameters, null, oldDataValues);
598 method = GetObjectMethod (DeleteMethod, paramValues, DataObjectMethodType.Delete);
600 method = ResolveDataObjectMethod (DeleteMethod, oldDataValues, null, out paramValues);
603 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
608 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
612 if (rargs.Exception != null && !rargs.ExceptionHandled)
613 throw rargs.Exception;
615 if (owner.EnableCaching)
616 owner.Cache.Expire ();
618 OnDataSourceViewChanged (EventArgs.Empty);
623 protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
625 IOrderedDictionary paramValues;
628 IDictionary oldDataValues;
629 oldDataValues = BuildOldValuesList (keys, oldValues, true);
631 if (DataObjectTypeName.Length == 0)
633 IDictionary dataValues;
635 paramValues = MergeParameterValues (UpdateParameters, dataValues, oldDataValues);
636 method = GetObjectMethod (UpdateMethod, paramValues, DataObjectMethodType.Update);
640 if (ConflictDetection != ConflictOptions.CompareAllValues) {
641 oldDataValues = null;
643 IDictionary dataValues = new Hashtable ();
645 foreach (DictionaryEntry de in keys)
646 dataValues [de.Key] = de.Value;
648 if (values != null) {
649 foreach (DictionaryEntry de in values)
650 dataValues [de.Key] = de.Value;
653 method = ResolveDataObjectMethod (UpdateMethod, dataValues, oldDataValues, out paramValues);
656 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
661 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
664 if (rargs.Exception != null && !rargs.ExceptionHandled)
665 throw rargs.Exception;
667 if (owner.EnableCaching)
668 owner.Cache.Expire ();
670 OnDataSourceViewChanged (EventArgs.Empty);
675 IDictionary BuildOldValuesList (IDictionary keys, IDictionary oldValues, bool keysWin)
677 IDictionary oldDataValues;
678 if (ConflictDetection == ConflictOptions.CompareAllValues) {
679 oldDataValues = new Hashtable ();
680 if (keys != null && !keysWin) {
681 foreach (DictionaryEntry de in keys)
682 oldDataValues [de.Key] = de.Value;
684 if (oldValues != null) {
685 foreach (DictionaryEntry de in oldValues)
686 oldDataValues [de.Key] = de.Value;
688 if (keys != null && keysWin) {
689 foreach (DictionaryEntry de in keys)
690 oldDataValues [de.Key] = de.Value;
694 oldDataValues = keys;
697 return oldDataValues;
700 protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
702 arguments.RaiseUnsupportedCapabilitiesError (this);
704 IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null, null);
705 ObjectDataSourceSelectingEventArgs args = new ObjectDataSourceSelectingEventArgs (paramValues, arguments, false);
707 object result = null;
709 if (owner.EnableCaching)
710 result = owner.Cache.GetCachedObject (SelectMethod, SelectParameters);
712 if (result == null) {
715 return new ArrayList ();
718 if (StartRowIndexParameterName.Length == 0)
719 throw new InvalidOperationException ("Paging is enabled, but the StartRowIndexParameterName property is not set.");
720 if (MaximumRowsParameterName.Length == 0)
721 throw new InvalidOperationException ("Paging is enabled, but the MaximumRowsParameterName property is not set.");
722 paramValues [StartRowIndexParameterName] = arguments.StartRowIndex;
723 paramValues [MaximumRowsParameterName] = arguments.MaximumRows;
726 if (SortParameterName.Length > 0)
727 paramValues [SortParameterName] = arguments.SortExpression;
729 result = InvokeSelect (SelectMethod, paramValues);
731 if (CanRetrieveTotalRowCount && arguments.RetrieveTotalRowCount)
732 arguments.TotalRowCount = QueryTotalRowCount (MergeParameterValues (SelectParameters, null, null), arguments);
734 if (owner.EnableCaching)
735 owner.Cache.SetCachedObject (SelectMethod, SelectParameters, result);
738 if (FilterExpression.Length > 0 && !(result is DataGrid || result is DataView || result is DataTable))
739 throw new NotSupportedException ("The FilterExpression property was set and the Select method does not return a DataSet, DataTable, or DataView.");
741 if (owner.EnableCaching && result is IDataReader)
742 throw new NotSupportedException ("Data source does not support caching objects that implement IDataReader");
744 if (result is DataSet) {
745 DataSet dset = (DataSet) result;
746 if (dset.Tables.Count == 0)
747 throw new InvalidOperationException ("The select method returnet a DataSet which doesn't contain any table.");
748 result = dset.Tables [0];
751 if (result is DataTable) {
752 DataView dview = new DataView ((DataTable)result);
753 if (arguments.SortExpression != null && arguments.SortExpression.Length > 0) {
754 dview.Sort = arguments.SortExpression;
756 if (FilterExpression.Length > 0) {
757 IOrderedDictionary fparams = FilterParameters.GetValues (context, owner);
758 ObjectDataSourceFilteringEventArgs fargs = new ObjectDataSourceFilteringEventArgs (fparams);
761 object[] formatValues = new object [fparams.Count];
762 for (int n=0; n<formatValues.Length; n++) {
763 formatValues [n] = fparams [n];
764 if (formatValues [n] == null) return dview;
766 dview.RowFilter = string.Format (FilterExpression, formatValues);
772 if (result is IEnumerable)
773 return (IEnumerable) result;
775 return new object[] {result};
778 int QueryTotalRowCount (IOrderedDictionary mergedParameters, DataSourceSelectArguments arguments)
780 ObjectDataSourceSelectingEventArgs countArgs = new ObjectDataSourceSelectingEventArgs (mergedParameters, arguments, true);
781 OnSelecting (countArgs);
782 if (countArgs.Cancel)
785 object count = InvokeSelect (SelectCountMethod, mergedParameters);
786 return (int) Convert.ChangeType (count, typeof(int));
789 object InvokeSelect (string methodName, IOrderedDictionary paramValues)
791 MethodInfo method = GetObjectMethod (methodName, paramValues, DataObjectMethodType.Select);
792 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
795 if (rargs.Exception != null && !rargs.ExceptionHandled)
796 throw rargs.Exception;
798 return rargs.ReturnValue;
801 ObjectDataSourceStatusEventArgs InvokeMethod (MethodInfo method, IOrderedDictionary paramValues)
803 object instance = null;
805 if (!method.IsStatic)
806 instance = CreateObjectInstance ();
808 ParameterInfo[] pars = method.GetParameters ();
810 ArrayList outParamInfos;
811 object[] methodArgs = GetParameterArray (pars, paramValues, out outParamInfos);
813 if (methodArgs == null)
814 throw CreateMethodException (method.Name, paramValues);
816 object result = null;
817 Hashtable outParams = null;
820 result = method.Invoke (instance, methodArgs);
821 if (outParamInfos != null) {
822 outParams = new Hashtable ();
823 foreach (ParameterInfo op in outParamInfos)
824 outParams [op.Name] = methodArgs [op.Position];
826 return new ObjectDataSourceStatusEventArgs (result, outParams, null);
828 catch (Exception ex) {
829 return new ObjectDataSourceStatusEventArgs (result, outParams, ex);
832 if (instance != null)
833 DisposeObjectInstance (instance);
837 MethodInfo GetObjectMethod (string methodName, IOrderedDictionary parameters, DataObjectMethodType methodType)
839 MemberInfo[] methods = ObjectType.GetMember (methodName, MemberTypes.Method, BindingFlags.Instance |
840 BindingFlags.Static |
841 BindingFlags.Public |
842 BindingFlags.IgnoreCase |
843 BindingFlags.FlattenHierarchy);
844 if (methods.Length > 1) {
845 // MSDN: The ObjectDataSource resolves method overloads by method name and number
846 // of parameters; the names and types of the parameters are not considered.
847 // LAMESPEC: the tests show otherwise
848 DataObjectMethodAttribute methodAttribute = null;
849 MethodInfo methodInfo = null;
850 bool hasConflict = false;
851 foreach (MethodInfo me in methods) { // we look for methods only
852 ParameterInfo [] pinfos = me.GetParameters ();
853 if (pinfos.Length == parameters.Count) {
854 object [] attrs = me.GetCustomAttributes (typeof (DataObjectMethodAttribute), true);
855 DataObjectMethodAttribute domAttr = (attrs != null && attrs.Length > 0) ? (DataObjectMethodAttribute) attrs [0] : null;
856 if (domAttr != null && domAttr.MethodType != methodType)
859 bool paramsMatch = true;
860 foreach (ParameterInfo pinfo in pinfos) {
861 if (!parameters.Contains (pinfo.Name)) {
870 if (domAttr != null) {
871 if (methodAttribute != null) {
872 if (methodAttribute.IsDefault) {
873 if (domAttr.IsDefault) {
875 break; //fail due to a conflict
878 continue; //existing matches better
881 methodInfo = null; //we override
882 hasConflict = !domAttr.IsDefault;
886 methodInfo = null; //we override
889 if (methodInfo == null) {
890 methodAttribute = domAttr;
899 if (!hasConflict && methodInfo != null)
902 else if (methods.Length == 1) {
903 MethodInfo me = methods[0] as MethodInfo;
904 if (me != null && me.GetParameters().Length == parameters.Count)
908 throw CreateMethodException (methodName, parameters);
911 MethodInfo ResolveDataObjectMethod (string methodName, IDictionary values, IDictionary oldValues, out IOrderedDictionary paramValues)
914 if (oldValues != null)
915 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType, DataObjectType });
917 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType });
920 throw new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters of type '" + DataObjectType + "' in '" + ObjectType + "'.");
922 paramValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
923 ParameterInfo[] ps = method.GetParameters ();
925 if (oldValues != null) {
926 if (FormatOldParameter (ps[0].Name) == ps[1].Name) {
927 paramValues [ps[0].Name] = CreateDataObject (values);
928 paramValues [ps[1].Name] = CreateDataObject (oldValues);
929 } else if (FormatOldParameter (ps[1].Name) == ps[0].Name) {
930 paramValues [ps[0].Name] = CreateDataObject (oldValues);
931 paramValues [ps[1].Name] = CreateDataObject (values);
933 throw new InvalidOperationException ("Method '" + methodName + "' does not have any parameter that fits the value of OldValuesParameterFormatString.");
935 paramValues [ps[0].Name] = CreateDataObject (values);
940 Exception CreateMethodException (string methodName, IOrderedDictionary parameters)
943 foreach (string p in parameters.Keys) {
946 return new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters " + s + "in type '" + ObjectType + "'.");
949 object CreateDataObject (IDictionary values)
951 object ob = Activator.CreateInstance (DataObjectType);
952 foreach (DictionaryEntry de in values) {
953 PropertyInfo p = DataObjectType.GetProperty ((string)de.Key);
954 if (p == null) throw new InvalidOperationException ("Property " + de.Key + " not found in type '" +DataObjectType + "'.");
955 object[] attributes = p.GetCustomAttributes (typeof (System.ComponentModel.TypeConverterAttribute),
957 Type propertyType = p.PropertyType;
958 object value = de.Value;
959 object converted = ConvertParameterWithTypeConverter (attributes, propertyType, value);
960 if (converted == null)
961 converted = ConvertParameter (propertyType, value);
963 p.SetValue (ob, converted, null);
968 object CreateObjectInstance ()
970 ObjectDataSourceEventArgs args = new ObjectDataSourceEventArgs (null);
971 OnObjectCreating (args);
973 if (args.ObjectInstance != null)
974 return args.ObjectInstance;
976 object ob = Activator.CreateInstance (ObjectType);
978 args.ObjectInstance = ob;
979 OnObjectCreated (args);
981 return args.ObjectInstance;
984 void DisposeObjectInstance (object obj)
986 ObjectDataSourceDisposingEventArgs args = new ObjectDataSourceDisposingEventArgs (obj);
987 OnObjectDisposing (args);
990 IDisposable disp = obj as IDisposable;
991 if (disp != null) disp.Dispose ();
995 object FindValueByName (string name, IDictionary values, bool format)
1000 foreach (DictionaryEntry de in values) {
1001 string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
1002 if (String.Compare (name, valueName, StringComparison.InvariantCultureIgnoreCase) == 0)
1003 return values [de.Key];
1009 /// Merge the current data item fields with view parameter default values
1011 /// <param name="viewParams">default parameters</param>
1012 /// <param name="values">new parameters for update and insert</param>
1013 /// <param name="oldValues">old parameters for update and delete</param>
1014 /// <param name="allwaysAddNewValues">true for insert, as current item is
1015 /// irrelevant for insert</param>
1016 /// <returns>merged values</returns>
1017 IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values, IDictionary oldValues)
1019 IOrderedDictionary parametersValues = viewParams.GetValues (context, owner);
1020 OrderedDictionary mergedValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
1021 foreach (string parameterName in parametersValues.Keys) {
1022 mergedValues [parameterName] = parametersValues [parameterName];
1023 if (oldValues != null) {
1024 object value = FindValueByName (parameterName, oldValues, true);
1025 if (value != null) {
1026 object dataValue = viewParams [parameterName].ConvertValue (value);
1027 mergedValues [parameterName] = dataValue;
1031 if (values != null) {
1032 object value = FindValueByName (parameterName, values, false);
1033 if (value != null) {
1034 object dataValue = viewParams [parameterName].ConvertValue (value);
1035 mergedValues [parameterName] = dataValue;
1040 if (values != null) {
1041 foreach (DictionaryEntry de in values)
1042 if (FindValueByName ((string) de.Key, mergedValues, false) == null)
1043 mergedValues [de.Key] = de.Value;
1046 if (oldValues != null) {
1047 foreach (DictionaryEntry de in oldValues) {
1048 string oldValueKey = FormatOldParameter ((string) de.Key);
1049 if (FindValueByName (oldValueKey, mergedValues, false) == null)
1050 mergedValues [oldValueKey] = de.Value;
1054 return mergedValues;
1057 object[] GetParameterArray (ParameterInfo[] methodParams, IOrderedDictionary viewParams, out ArrayList outParamInfos)
1059 // FIXME: make this case insensitive
1061 outParamInfos = null;
1062 object[] values = new object [methodParams.Length];
1064 foreach (ParameterInfo mp in methodParams) {
1066 // Parameter names must match
1067 if (!viewParams.Contains (mp.Name)) return null;
1069 values [mp.Position] = ConvertParameter (mp.ParameterType, viewParams [mp.Name]);
1070 if (mp.ParameterType.IsByRef) {
1071 if (outParamInfos == null) outParamInfos = new ArrayList ();
1072 outParamInfos.Add (mp);
1078 object ConvertParameterWithTypeConverter (object[] attributes, Type targetType, object value)
1080 if (attributes == null || attributes.Length == 0 || value == null)
1082 TypeConverterAttribute tca;
1084 TypeConverter converter;
1086 foreach (object a in attributes) {
1087 tca = a as TypeConverterAttribute;
1090 converterType = HttpApplication.LoadType (tca.ConverterTypeName, false);
1091 if (converterType == null)
1093 converter = Activator.CreateInstance (converterType, new object[] {targetType}) as TypeConverter;
1094 if (converter == null)
1096 if (converter.CanConvertFrom (value.GetType ()))
1097 return converter.ConvertFrom (value);
1098 else if (converter.CanConvertFrom (typeof (string)))
1099 return converter.ConvertFrom (value.ToString ());
1105 object ConvertParameter (Type targetType, object value)
1107 return ConvertParameter (Type.GetTypeCode (targetType), value);
1110 object ConvertParameter (TypeCode targetType, object value)
1112 if (value == null) {
1113 if (targetType != TypeCode.Object && targetType != TypeCode.String)
1115 else if (ConvertNullToDBNull)
1116 return DBNull.Value;
1118 if (targetType == TypeCode.Object || targetType == TypeCode.Empty)
1121 return Convert.ChangeType (value, targetType);
1124 string FormatOldParameter (string name)
1126 string f = OldValuesParameterFormatString;
1128 return String.Format (f, name);
1133 void OnParametersChanged (object sender, EventArgs args)
1135 OnDataSourceViewChanged (EventArgs.Empty);
1138 protected virtual void LoadViewState (object savedState)
1140 object[] state = (savedState == null) ? new object [5] : (object[]) savedState;
1141 ((IStateManager)SelectParameters).LoadViewState (state[0]);
1142 ((IStateManager)UpdateParameters).LoadViewState (state[1]);
1143 ((IStateManager)DeleteParameters).LoadViewState (state[2]);
1144 ((IStateManager)InsertParameters).LoadViewState (state[3]);
1145 ((IStateManager)FilterParameters).LoadViewState (state[4]);
1148 protected virtual object SaveViewState()
1150 object[] state = new object [5];
1152 if (selectParameters != null)
1153 state [0] = ((IStateManager)selectParameters).SaveViewState ();
1154 if (updateParameters != null)
1155 state [1] = ((IStateManager)updateParameters).SaveViewState ();
1156 if (deleteParameters != null)
1157 state [2] = ((IStateManager)deleteParameters).SaveViewState ();
1158 if (insertParameters != null)
1159 state [3] = ((IStateManager)insertParameters).SaveViewState ();
1160 if (filterParameters != null)
1161 state [4] = ((IStateManager)filterParameters).SaveViewState ();
1163 foreach (object ob in state)
1164 if (ob != null) return state;
1169 protected virtual void TrackViewState()
1171 isTrackingViewState = true;
1173 if (selectParameters != null) ((IStateManager)selectParameters).TrackViewState ();
1174 if (filterParameters != null) ((IStateManager)filterParameters).TrackViewState ();
1177 protected bool IsTrackingViewState
1179 get { return isTrackingViewState; }
1183 bool IStateManager.IsTrackingViewState
1185 get { return IsTrackingViewState; }
1188 void IStateManager.TrackViewState()
1193 void IStateManager.LoadViewState (object savedState)
1195 LoadViewState (savedState);
1198 object IStateManager.SaveViewState()
1200 return SaveViewState ();