我在数据库中有一个actors
的集合,我可以通过以下对webApi的调用获得:
HttpResponseMessage response = await client.GetAsync("api/actors");
这会在我的webapi-controller上触发以下方法:
// GET: api/Actors
public IQueryable<Actor> GetActors()
{
return db.Actors;
}
现在我们可以说,我在获取所有赢得奥斯卡奖的演员方面取得了成功。在没有webapi的情况下直接调用DB可能看起来像这样:
return db.actors.where(o=>o.OscarWinner==true);
但是如何使用webApi进行类似的调用呢? Api是否仅限于让我获取所有演员:
HttpResponseMessage response = await client.GetAsync("api/actors");
或一个特定的演员:
HttpResponseMessage response = await client.GetAsync("api/actors/1");
这一定是我认为的常见请求,能够根据某些条件获取对象列表吗?
编辑:
public IQueryable<Actor> GetUsers(int CountrId)
{
var list = db.Actors.Where(o => o.CountryId == CountryId);
return list;
}
答案 0 :(得分:0)
引用来自Professional ASP.NET MVC 4的书
要接受来自请求的传入值,您可以将参数放在您的操作上,就像MVC一样,Web API框架将自动为这些操作参数提供值。与MVC不同,HTTP主体的值和从其他地方(例如来自URI)获取的值之间存在强烈的界线。
默认情况下,Web API将假定简单类型的参数(即内部类型,字符串,日期,时间以及来自字符串的类型转换器的任何内容)取自非正文值和复杂类型(其他所有内容)是从身体中取出的。还有一个额外的限制:只有一个值可以来自身体,该值必须代表整个身体。
所以你有两个选择。如果您只想使用简单的过滤器,那么它就足以从查询字符串中获取它。更好的选择是编写一个类,它将从JSON请求体中映射其属性。我将提供一个示例,我如何从查询字符串中映射过滤器数据,因为我想允许我的用户通过查询字符串查询数据。我写了一个用ModelBinder绑定的过滤器类。
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);
}
条件过滤器类
/// <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];
}
}