/// <summary> /// Invokes the select method and gets the result. Also handles auto paging and sorting when required. /// </summary> /// <param name="arguments">The DataSourceSelectArguments for the select operation. /// When applicable, this method sets the TotalRowCount out parameter in the arguments. /// </param> /// <returns>The return value from the select method.</returns> protected virtual object GetSelectMethodResult(DataSourceSelectArguments arguments) { if (SelectMethod.Length == 0) { throw new InvalidOperationException(SR.GetString(SR.ModelDataSourceView_SelectNotSupported)); } DataSourceSelectResultProcessingOptions options = null; ModelDataSourceMethod method = EvaluateSelectMethodParameters(arguments, out options); ModelDataMethodResult result = InvokeMethod(method); return(ProcessSelectMethodResult(arguments, options, result)); }
/// <summary> /// Evaluates the select method parameters and also determines the options for processing select result like auto paging and sorting behavior. /// </summary> /// <param name="arguments">The DataSourceSelectArguments for the select operation.</param> /// <param name="selectResultProcessingOptions">The <see cref="System.Web.UI.WebControls.DataSourceSelectResultProcessingOptions"/> to use /// for processing the select result once select operation is complete. These options are determined in this method and later used /// by the method <see cref="System.Web.UI.WebControls.ModelDataSourceView.ProcessSelectMethodResult"/>. /// </param> /// <returns>A <see cref="System.Web.UI.WebControls.ModelDataSourceMethod"/> with the information required to invoke the select method.</returns> protected virtual ModelDataSourceMethod EvaluateSelectMethodParameters(DataSourceSelectArguments arguments, out DataSourceSelectResultProcessingOptions selectResultProcessingOptions) { ModelDataSourceMethod method; IOrderedDictionary mergedParameters = MergeSelectParameters(arguments); // Resolve the method method = FindMethod(SelectMethod); Type selectMethodReturnType = method.MethodInfo.ReturnType; Type modelType = ModelType; if (modelType == null) { //When ModelType is not specified but SelectMethod returns IQueryable<T>, we treat T as model type for auto paging and sorting. //If the return type is something like CustomType<U,T> : IQueryable<T>, we should use T for paging and sorting, hence //we walk over the return type's generic arguments for a proper match. foreach (Type typeParameter in selectMethodReturnType.GetGenericArguments()) { if (typeof(IQueryable <>).MakeGenericType(typeParameter).IsAssignableFrom(selectMethodReturnType)) { modelType = typeParameter; } } } Type queryableModelType = (modelType != null) ? typeof(IQueryable <>).MakeGenericType(modelType) : null; //We do auto paging or auto sorting when the select method is returning an IQueryable and does not have parameters for paging or sorting. bool isReturningQueryable = queryableModelType != null && queryableModelType.IsAssignableFrom(selectMethodReturnType); bool autoPage = false; bool autoSort = false; if (arguments.StartRowIndex >= 0 && arguments.MaximumRows > 0) { autoPage = IsAutoPagingRequired(method.MethodInfo, isReturningQueryable); } if (!String.IsNullOrEmpty(arguments.SortExpression)) { autoSort = IsAutoSortingRequired(method.MethodInfo, isReturningQueryable); } selectResultProcessingOptions = new DataSourceSelectResultProcessingOptions() { ModelType = modelType, AutoPage = autoPage, AutoSort = autoSort }; EvaluateMethodParameters(DataSourceOperation.Select, method, mergedParameters); return(method); }
/// <summary> /// This method performs operations on the select method result like auto paging and sorting if applicable. /// </summary> /// <param name="arguments">The DataSourceSelectArguments for the select operation.</param> /// <param name="selectResultProcessingOptions">The <see cref="System.Web.UI.WebControls.DataSourceSelectResultProcessingOptions"/> to use for processing the select result. /// These options are determined in an earlier call to <see cref="System.Web.UI.WebControls.ModelDataSourceView.EvaluateSelectMethodParameters"/>. /// </param> /// <param name="result">The result after operations like auto paging/sorting are done.</param> /// <returns></returns> protected virtual object ProcessSelectMethodResult(DataSourceSelectArguments arguments, DataSourceSelectResultProcessingOptions selectResultProcessingOptions, ModelDataMethodResult result) { // If the return value is null, there is no more processing to be done if (result.ReturnValue == null) { return null; } bool autoPage = selectResultProcessingOptions.AutoPage; bool autoSort = selectResultProcessingOptions.AutoSort; Type modelType = selectResultProcessingOptions.ModelType; string sortExpression = arguments.SortExpression; if (autoPage) { MethodInfo countHelperMethod = typeof(QueryableHelpers).GetMethod("CountHelper").MakeGenericMethod(modelType); arguments.TotalRowCount = (int)countHelperMethod.Invoke(null, new object[] { result.ReturnValue }); //Bug 180907: We would like to auto sort on DataKeyName when paging is enabled and result is not already sorted by user to overcome a limitation in EF. MethodInfo isOrderingMethodFoundMethod = typeof(QueryableHelpers).GetMethod("IsOrderingMethodFound").MakeGenericMethod(modelType); bool isOrderingMethodFound = (bool)isOrderingMethodFoundMethod.Invoke(null, new object[] { result.ReturnValue }); if (!isOrderingMethodFound) { if (String.IsNullOrEmpty(sortExpression) && !String.IsNullOrEmpty(DataKeyName)) { autoSort = true; selectResultProcessingOptions.AutoSort = true; sortExpression = DataKeyName; } } } else if (arguments.StartRowIndex >= 0 && arguments.MaximumRows > 0) { //When paging is handled by developer, we need to set the TotalRowCount parameter from the select method out parameter. arguments.TotalRowCount = (int)result.OutputParameters[TotalRowCountParameterName]; } if (autoPage || autoSort) { MethodInfo sortPageHelperMethod = typeof(QueryableHelpers).GetMethod("SortandPageHelper").MakeGenericMethod(modelType); object returnValue = sortPageHelperMethod.Invoke(null, new object[] { result.ReturnValue, autoPage ? (int?)arguments.StartRowIndex : null, autoPage ? (int?)arguments.MaximumRows : null, autoSort ? sortExpression : null }); return returnValue; } return result.ReturnValue; }
private ModelDataSourceMethod EvaluateSelectMethodParameters(DataSourceSelectArguments arguments, ModelDataSourceMethod method, bool isAsyncSelect, out DataSourceSelectResultProcessingOptions selectResultProcessingOptions) { IOrderedDictionary mergedParameters = MergeSelectParameters(arguments); // Resolve the method method = method ?? FindMethod(SelectMethod); Type selectMethodReturnType = method.MethodInfo.ReturnType; if (isAsyncSelect) { selectMethodReturnType = ExtractAsyncSelectReturnType(selectMethodReturnType); } Type modelType = ModelType; if (modelType == null) { //When ModelType is not specified but SelectMethod returns IQueryable<T>, we treat T as model type for auto paging and sorting. //If the return type is something like CustomType<U,T> : IQueryable<T>, we should use T for paging and sorting, hence //we walk over the return type's generic arguments for a proper match. foreach (Type typeParameter in selectMethodReturnType.GetGenericArguments()) { if (typeof(IQueryable<>).MakeGenericType(typeParameter).IsAssignableFrom(selectMethodReturnType)) { modelType = typeParameter; } } } Type queryableModelType = (modelType != null) ? typeof(IQueryable<>).MakeGenericType(modelType) : null; //We do auto paging or auto sorting when the select method is returning an IQueryable and does not have parameters for paging or sorting. bool isReturningQueryable = queryableModelType != null && queryableModelType.IsAssignableFrom(selectMethodReturnType); if (isAsyncSelect && isReturningQueryable) { // async select method does not support returning IQueryable<>. throw new InvalidOperationException(SR.GetString(SR.ModelDataSourceView_InvalidAsyncSelectReturnType, modelType)); } bool autoPage = false; bool autoSort = false; if (arguments.StartRowIndex >= 0 && arguments.MaximumRows > 0) { autoPage = IsAutoPagingRequired(method.MethodInfo, isReturningQueryable, isAsyncSelect); if (isAsyncSelect) { Debug.Assert(!autoPage, "auto-paging should not be true when using async select method"); // custom paging is not supported if the return type is not SelectResult if (typeof(SelectResult) != selectMethodReturnType) { throw new InvalidOperationException(SR.GetString(SR.ModelDataSourceView_MustUseSelectResultAsReturnType)); } } } if (!String.IsNullOrEmpty(arguments.SortExpression)) { autoSort = IsAutoSortingRequired(method.MethodInfo, isReturningQueryable); } selectResultProcessingOptions = new DataSourceSelectResultProcessingOptions() { ModelType = modelType, AutoPage = autoPage, AutoSort = autoSort }; EvaluateMethodParameters(DataSourceOperation.Select, method, mergedParameters); return method; }
/// <summary> /// Evaluates the select method parameters and also determines the options for processing select result like auto paging and sorting behavior. /// </summary> /// <param name="arguments">The DataSourceSelectArguments for the select operation.</param> /// <param name="selectResultProcessingOptions">The <see cref="System.Web.UI.WebControls.DataSourceSelectResultProcessingOptions"/> to use /// for processing the select result once select operation is complete. These options are determined in this method and later used /// by the method <see cref="System.Web.UI.WebControls.ModelDataSourceView.ProcessSelectMethodResult"/>. /// </param> /// <returns>A <see cref="System.Web.UI.WebControls.ModelDataSourceMethod"/> with the information required to invoke the select method.</returns> protected virtual ModelDataSourceMethod EvaluateSelectMethodParameters(DataSourceSelectArguments arguments, out DataSourceSelectResultProcessingOptions selectResultProcessingOptions) { return EvaluateSelectMethodParameters(arguments, null/*method*/, false /*isAsyncSelect*/, out selectResultProcessingOptions); }
/// <summary> /// This method performs operations on the select method result like auto paging and sorting if applicable. /// </summary> /// <param name="arguments">The DataSourceSelectArguments for the select operation.</param> /// <param name="selectResultProcessingOptions">The <see cref="System.Web.UI.WebControls.DataSourceSelectResultProcessingOptions"/> to use for processing the select result. /// These options are determined in an earlier call to <see cref="System.Web.UI.WebControls.ModelDataSourceView.EvaluateSelectMethodParameters"/>. /// </param> /// <param name="result">The result after operations like auto paging/sorting are done.</param> /// <returns></returns> protected virtual object ProcessSelectMethodResult(DataSourceSelectArguments arguments, DataSourceSelectResultProcessingOptions selectResultProcessingOptions, ModelDataMethodResult result) { // If the return value is null, there is no more processing to be done if (result.ReturnValue == null) { return(null); } bool autoPage = selectResultProcessingOptions.AutoPage; bool autoSort = selectResultProcessingOptions.AutoSort; Type modelType = selectResultProcessingOptions.ModelType; string sortExpression = arguments.SortExpression; if (autoPage) { MethodInfo countHelperMethod = typeof(QueryableHelpers).GetMethod("CountHelper").MakeGenericMethod(modelType); arguments.TotalRowCount = (int)countHelperMethod.Invoke(null, new object[] { result.ReturnValue }); //Bug 180907: We would like to auto sort on DataKeyName when paging is enabled and result is not already sorted by user to overcome a limitation in EF. MethodInfo isOrderingMethodFoundMethod = typeof(QueryableHelpers).GetMethod("IsOrderingMethodFound").MakeGenericMethod(modelType); bool isOrderingMethodFound = (bool)isOrderingMethodFoundMethod.Invoke(null, new object[] { result.ReturnValue }); if (!isOrderingMethodFound) { if (String.IsNullOrEmpty(sortExpression) && !String.IsNullOrEmpty(DataKeyName)) { autoSort = true; selectResultProcessingOptions.AutoSort = true; sortExpression = DataKeyName; } } } else if (arguments.StartRowIndex >= 0 && arguments.MaximumRows > 0) { //When paging is handled by developer, we need to set the TotalRowCount parameter from the select method out parameter. arguments.TotalRowCount = (int)result.OutputParameters[TotalRowCountParameterName]; } if (autoPage || autoSort) { MethodInfo sortPageHelperMethod = typeof(QueryableHelpers).GetMethod("SortandPageHelper").MakeGenericMethod(modelType); object returnValue = sortPageHelperMethod.Invoke(null, new object[] { result.ReturnValue, autoPage ? (int?)arguments.StartRowIndex : null, autoPage ? (int?)arguments.MaximumRows : null, autoSort ? sortExpression : null }); return(returnValue); } return(result.ReturnValue); }
/// <summary> /// Evaluates the select method parameters and also determines the options for processing select result like auto paging and sorting behavior. /// </summary> /// <param name="arguments">The DataSourceSelectArguments for the select operation.</param> /// <param name="selectResultProcessingOptions">The <see cref="System.Web.UI.WebControls.DataSourceSelectResultProcessingOptions"/> to use /// for processing the select result once select operation is complete. These options are determined in this method and later used /// by the method <see cref="System.Web.UI.WebControls.ModelDataSourceView.ProcessSelectMethodResult"/>. /// </param> /// <returns>A <see cref="System.Web.UI.WebControls.ModelDataSourceMethod"/> with the information required to invoke the select method.</returns> protected virtual ModelDataSourceMethod EvaluateSelectMethodParameters(DataSourceSelectArguments arguments, out DataSourceSelectResultProcessingOptions selectResultProcessingOptions) { ModelDataSourceMethod method; IOrderedDictionary mergedParameters = MergeSelectParameters(arguments); // Resolve the method method = FindMethod(SelectMethod); Type selectMethodReturnType = method.MethodInfo.ReturnType; Type modelType = ModelType; if (modelType == null) { //When ModelType is not specified but SelectMethod returns IQueryable<T>, we treat T as model type for auto paging and sorting. //If the return type is something like CustomType<U,T> : IQueryable<T>, we should use T for paging and sorting, hence //we walk over the return type's generic arguments for a proper match. foreach (Type typeParameter in selectMethodReturnType.GetGenericArguments()) { if (typeof(IQueryable<>).MakeGenericType(typeParameter).IsAssignableFrom(selectMethodReturnType)) { modelType = typeParameter; } } } Type queryableModelType = (modelType != null) ? typeof(IQueryable<>).MakeGenericType(modelType) : null; //We do auto paging or auto sorting when the select method is returning an IQueryable and does not have parameters for paging or sorting. bool isReturningQueryable = queryableModelType != null && queryableModelType.IsAssignableFrom(selectMethodReturnType); bool autoPage = false; bool autoSort = false; if (arguments.StartRowIndex >= 0 && arguments.MaximumRows > 0) { autoPage = IsAutoPagingRequired(method.MethodInfo, isReturningQueryable); } if (!String.IsNullOrEmpty(arguments.SortExpression)) { autoSort = IsAutoSortingRequired(method.MethodInfo, isReturningQueryable); } selectResultProcessingOptions = new DataSourceSelectResultProcessingOptions() { ModelType = modelType, AutoPage = autoPage, AutoSort = autoSort }; EvaluateMethodParameters(DataSourceOperation.Select, method, mergedParameters); return method; }