您的位置:首页 > 编程语言 > ASP

我使用Asp.net MVC WebAPI支持OData协议进行分页操作的笔记(第二篇)

2015-05-14 15:46 841 查看
在阅读这篇文章的时候,我想你已经看完第一篇文章啦・也有可能跟我一样,现在正在使用它Asp.net WebAPI为我们干活儿。可能是服务分页查询接口,也可能是其它操作,遇到了一些小问题。有问题,那咱就来解决问题吧!(码农万岁,万岁,万万岁!)

扯两句,Asp.net MVC WebAPI,是建立在Asp.net MVC基础上的。所有的请求处理,都遵循MVC的路由规则,对于请求的拦截与处理,都可以通过自定义继承自
System.Web.Http.Filters.ActionFilterAttribute
的任意标记类,然后重写里面的4个方法OnActionExecuted,OnActionExecutedAsync,OnActionExecuting
OnActionExecutingAsync 来实现对请求的拦截,过滤等等。最后通过Action标记,或者通 Global.asax 中进行全局注册。就可以实现MVC的请求拦截与自定义的逻辑管理了。
看看它的庐山真面目。定义如下:
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IFilter
可以看到,它是一个抽象类,继承自FilterAttribute,同时实现了IActionFilter,IFilter两个接口。(不再往里面扒了,有兴趣你可以自己瞧瞧,也可以整本ASP.NET MVC的技术书看看。)

下面是部分核心代码的实现(参考:System.Web.OData项目源码的EnableQueryAttribute对象定义)
/// <summary>
/// 标记Action返回结果为分页数据对象。
/// Action本身必须返回IQueryable<T>
/// -------------------------------------
/// add by hotboy 2015-5-14 11:32:27
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class ODataPagedAttribute : System.Web.Http.Filters.ActionFilterAttribute{

private const char CommaSeparator = ',';
private const string PageSizeKey = "$pagesize";
private const int DefaultPageSize = 20;

// validation settings
private ODataValidationSettings _validationSettings;
private string _allowedOrderByProperties;

// query settings
private ODataQuerySettings _querySettings;

/// <summary>
/// Enables a controller action to support OData query parameters.
/// </summary>
public ODataPagedAttribute()
{
_validationSettings = new ODataValidationSettings();
_querySettings = new ODataQuerySettings();
}
//... more than code here ....//
}

//
// IQeruyable静态方法,参考:System.Web.OData.Extension的QueryableExtensions
// 用于查询分页数据以及数据记录总数。
public class QueryableExtensions
{
private static MethodInfo _limitResultsGenericMethod = typeof(QueryableExtensions).GetMethod("LimitResults");
internal static IQueryable LimitResults(IQueryable queryable, int limit, out bool resultsLimited, out int total)
{
MethodInfo genericMethod = _limitResultsGenericMethod.MakeGenericMethod(queryable.ElementType);
object[] args = new object[] { queryable, limit, null, null };
IQueryable results = genericMethod.Invoke(null, args) as IQueryable;
resultsLimited = (bool)args[2];
total = (int)args[3];
return results;
}

/// <summary>
/// Limits the query results to a maximum number of results.
/// </summary>
/// <typeparam name="T">The entity CLR type</typeparam>
/// <param name="queryable">The queryable to limit.</param>
/// <param name="limit">The query result limit.</param>
/// <param name="resultsLimited"><c>true</c> if the query results were limited; <c>false</c> otherwise</param>
/// <returns>The limited query results.</returns>
public static IQueryable<T> LimitResults<T>(IQueryable<T> queryable, int limit, out bool resultsLimited, out int total)
{
total = queryable.Count();
TruncatedCollection<T> truncatedCollection = new TruncatedCollection<T>(queryable, limit);
resultsLimited = truncatedCollection.IsTruncated;
return truncatedCollection.AsQueryable();
}
}

// Type管理辅助Helper
internal static class TypeHelper {
internal static Type GetImplementedIEnumerableType(Type type)
{
// get inner type from Task<T>
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task<>))
{
type = type.GetGenericArguments().First();
}

if (type.IsGenericType && type.IsInterface &&
(type.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
type.GetGenericTypeDefinition() == typeof(IQueryable<>)))
{
// special case the IEnumerable<T>
return GetInnerGenericType(type);
}
else
{
// for the rest of interfaces and strongly Type collections
Type[] interfaces = type.GetInterfaces();
foreach (Type interfaceType in interfaces)
{
if (interfaceType.IsGenericType &&
(interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
interfaceType.GetGenericTypeDefinition() == typeof(IQueryable<>)))
{
// special case the IEnumerable<T>
return GetInnerGenericType(interfaceType);
}
}
}

return null;
}
private static Type GetInnerGenericType(Type interfaceType)
{
// Getting the type T definition if the returning type implements IEnumerable<T>
Type[] parameterTypes = interfaceType.GetGenericArguments();

if (parameterTypes.Length == 1)
{
return parameterTypes[0];
}

return null;
}
}


下一篇文章,将介绍怎么样使用它,以及项目中需要注意事项与项目源代码下载地址。

本文出自 “莴笋Ho” 博客,请务必保留此出处http://oceanho.blog.51cto.com/8826994/1651277
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐