gco*_*828 4 api rest asp.net-web-api
我对微软的REST和WebAPI比较陌生.我们正在实现一个中心REST服务,它将容纳几种类型的对象获取和设置.作为该项目的领导者,我的任务是提出我们正在进行的适当的Uri设计.我想知道关于战争的想法更好.是的,我没有使用"标准"这个词专门定期.
以下是我的团队和我目前正在娱乐的选项:
Http://servername/API/REST/Ldap/AD/employees?username=jsmith
Http://servername/API/REST/Ldap/AD/employee/UserName?searchTerm=jsmith (this seems RPC to me)
Http://servername/API/REST/Ldap/AD/employees/getusername?searchterm?jsmith
Run Code Online (Sandbox Code Playgroud)
我们也在创建一个Soap版本,因此其余的在Uri.
感谢您的投入
Opp*_*nal 17
我建议你看看Brian Mulloy的Web API设计.在搜索和过滤方面,他有几个建议.
简化关联 - 扫描'?'下的复杂性
大多数API都具有超出资源基础级别的复杂性.复杂性可以包括可以更新,更改,查询的许多状态,以及与资源相关联的属性.通过在HTTP问号后面添加可选的状态和属性,使开发人员可以轻松使用基本URL.通过在HTTP问号的地毯下简化资源之间的关联,扫描参数和其他复杂性,保持API的直观性.
搜索提示
虽然简单搜索可以建模为资源丰富的API(例如,dog /?q = red),但跨多个资源的更复杂搜索需要不同的设计.如果您想跨资源进行全局搜索,建议您按照Google模式进行操作:
全球搜索
/搜索Q =蓬松+毛皮
在这里,搜索是动词; ?q代表查询.
搜索范围
要为搜索添加范围,可以在搜索范围之前添加.例如,搜索资源ID为5678的狗
/老板/ 5678 /狗?Q = +蓬松皮草
请注意,显式搜索已从URL中删除,而是依赖于参数"q"来指示范围查询.
分页和部分回应
通过在逗号分隔列表中添加可选字段来支持部分响应.
/狗?域=名称,颜色,位置
使用限制和偏移使开发人员可以轻松地对对象进行分页.
/狗?限制= 25&偏移量= 50
对于反对派的评论,这是我前段时间整理的。
https://groups.google.com/d/msg/servicestack/uoMzASmvxho/CtqpZdju7NcJ
public class QueryBase
{
public string Query { get; set; }
public int Limit { get; set; }
public int Offset { get; set; }
}
[Route("/v1/users")]
public class User : IReturn<List<User>>
{
public string Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
public class RequestFilterAttribute : Attribute, IHasRequestFilter
{
#region IHasRequestFilter Members
public IHasRequestFilter Copy()
{
return this;
}
public int Priority
{
get { return -100; }
}
public void RequestFilter(IHttpRequest req, IHttpResponse res, object requestDto)
{
var query = req.QueryString["q"] ?? req.QueryString["query"];
var limit = req.QueryString["limit"];
var offset = req.QueryString["offset"];
var user = requestDto as QueryBase;
if (user == null) { return; }
user.Query = query;
user.Limit = limit.IsEmpty() ? int.MaxValue : int.Parse(limit);
user.Offset = offset.IsEmpty() ? 0 : int.Parse(offset);
}
#endregion
}
[Route("/v1/users/search", "GET")]
[RequestFilter]
public class SearchUser : QueryBase, IReturn<PagedResult<User>> { }
public class UsersService : Service
{
public static List<User> UserRepository = new List<User>
{
new User{ Id="1", FirstName = "Michael", LastName = "A", Email = "michaelEmail" },
new User{ Id="2", FirstName = "Robert", LastName = "B", Email = "RobertEmail" },
new User{ Id="3", FirstName = "Khris", LastName = "C", Email = "KhrisEmail" },
new User{ Id="4", FirstName = "John", LastName = "D", Email = "JohnEmail" },
new User{ Id="4", FirstName = "Lisa", LastName = "E", Email = "LisaEmail" }
};
public PagedResult<User> Get(SearchUser request)
{
var query = request.Query;
var users = request.Query.IsNullOrEmpty()
? UserRepository.ToList()
: UserRepository.Where(x => x.FirstName.Contains(query) || x.LastName.Contains(query) || x.Email.Contains(query)).ToList();
var totalItems = users.Count;
var totalPages = (int)Math.Ceiling((decimal)totalItems / (decimal)request.Limit);
var currentPage = request.Offset;
users = users.Skip(request.Offset * request.Limit).Take(request.Limit).ToList();
var itemCount = users.Count;
return new PagedResult<User>
{
TotalItems = totalItems,
TotalPages = totalPages,
ItemCount = itemCount,
Items = users,
CurrentPage = currentPage
};
}
}
Run Code Online (Sandbox Code Playgroud)