引用自专业 ASP.NET MVC 4 书
要接受来自请求的传入值,您可以将参数放在您的操作上,就像 MVC 一样,Web API 框架会自动为这些操作参数提供值。与 MVC 不同,HTTP 正文中的值与从其他地方(如 URI)获取的值之间有一条明确的界限。
默认情况下,Web API 将假定简单类型的参数(即内在类型、字符串、日期、时间和任何带有字符串类型转换器的东西)取自非正文值和复杂类型(其他所有类型)取自身体。还有一个额外的限制:只有一个值可以来自正文,并且该值必须代表整个正文。
所以你有两个选择。如果您只想拥有简单的过滤器,那么从查询字符串中获取它就足够了。更好的选择是编写一个类,它将从 JSON 请求正文映射其属性。我将提供一个示例,我如何从查询字符串映射过滤器数据,因为我想让我的用户通过查询字符串查询数据。我写了一个与 ModelBinder 绑定的过滤器类。
1。查询字符串
HttpResponseMessage response = await client.GetAsync("api/actors/?oscarWinner=true");
对应的动作方法
// GET: api/Actors
public IQueryable<Actor> GetActors(bool oscarWinner = false)
{
return db.Actors.Where(actor=>actor.OscarWinner == oscarWinner);
}
2。模型绑定器
条件过滤器类
/// <summary>
/// Condition Filter
/// </summary>
public class ConditionFilter
{
/// <summary>
/// Oscar Winner
/// </summary>
public bool? OscarWinner { get; set; }
/// <summary>
/// Page you want to get. Counting from 0.
/// </summary>
public int? Page { get; set; }
/// <summary>
/// Number of jobs on page. Default page size 1000.
/// </summary>
public int? PageSize { get; set; }
}
条件过滤绑定器
public class ConditionFilterBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof (ConditionFilter))
{
return false;
}
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (val == null)
{
return false;
}
var queryString = HttpUtility.ParseQueryString(val.RawValue.ToString());
var conditionFilter = new ConditionFilter
{
Page = queryString.GetValueFromQueryString<int>("page"),
PageSize = queryString.GetValueFromQueryString<int>("pageSize"),
OscarWinner = queryString.GetValueFromQueryString<bool>("oscarWinner")
};
bindingContext.Model = conditionFilter;
return true;
}
}
}
并将其与您的操作方法一起使用
public List<Actor> GetActors([ModelBinder(BinderType = typeof(ConditionFilterBinder))] ConditionFilter conditionFilter = null)
{
//just to be sure, that we will not take some huge amount of data from database
const int MAX_ACTOR_COUNT = 1000;
var page = 0;
var pageSize = MAX_ACTOR_COUNT;
var actors = db.Actors;
if (conditionFilter != null)
{
if(conditionFilter.OscarWinner.HasValue && conditionFilter.OscarWinner.Value)
{
actors = actors.Where(actor => actor.OscarWinner)
}
if (conditionFilter.Page.HasValue)
{
page = conditionFilter.Page.Value;
}
if (conditionFilter.PageSize.HasValue)
{
pageSize = conditionFilter.PageSize.Value > MAX_ACTOR_COUNT ? MAX_ACTOR_COUNT : conditionFilter.PageSize.Value;
}
}
return actors.Skip(page * pageSize).Take(pageSize);
}
使用此实现,您可以像这样调用您的操作方法
HttpResponseMessage response = await client.GetAsync("api/actors?oscarWinner=true&page=3&pageSize=100");
为了完整起见,这是我的 GetValueFromQueryString 助手类
/// <summary>
/// Extension method for name value collection
/// </summary>
public static class NameValueCollectionExtensions
{
/// <summary>
/// Get typed value from query string
/// </summary>
/// <param name="queryString"></param>
/// <param name="value"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T? GetValueFromQueryString<T>(this NameValueCollection queryString, string value) where T : struct, IConvertible
{
if (queryString[value] != null)
{
var thisType = default(T);
var typeCode = thisType.GetTypeCode();
switch (typeCode)
{
case TypeCode.Boolean:
{
bool queryStringValue;
if (bool.TryParse(queryString[value], out queryStringValue))
{
return (T)Convert.ChangeType(queryStringValue, typeCode);
}
}
break;
case TypeCode.Int32:
case TypeCode.Int64:
{
if (typeof(T).IsEnum)
{
var numberValue = queryString.GetValueFromQueryString<int>(value);
if (numberValue.HasValue && Enum.IsDefined(typeof(T), numberValue.Value))
{
return (T)(object)numberValue;
}
else
{
T queryStringValueForEnum;
if (Enum.TryParse(queryString[value], true, out queryStringValueForEnum))
{
return queryStringValueForEnum;
}
}
}
int queryStringValue;
if (int.TryParse(queryString[value], out queryStringValue))
{
return (T)Convert.ChangeType(queryStringValue, typeCode);
}
}
break;
case TypeCode.DateTime:
{
DateTime queryStringValue;
if (DateTime.TryParse(queryString[value], out queryStringValue))
{
return (T)Convert.ChangeType(queryStringValue, typeCode);
}
break;
}
}
}
return null;
}
/// <summary>
/// Get string value from query string
/// </summary>
/// <param name="queryString"></param>
/// <param name="value"></param>
/// <returns></returns>
public static string GetValueFromQueryString(this NameValueCollection queryString, string value)
{
return queryString[value];
}
}