我正在为一个应用程序构建一个WebAPI服务,我被困在十字路口,我理解SOLID原则,并希望按照这些原则实现我的WebAPI服务,但是我花了最近几天在实施中苦苦挣扎并希望得到社区的一些建议。
单一责任原则规定,每个班级都应对软件提供的单一功能负责(参见Solid Principles)
我目前有两个ApiControllers,但会有更多,两个目前有Get,Post和Put功能,但每个控制器也需要一个搜索功能,我的问题是应该将搜索方法转移到一个单独的ApiController,例如SearchController。
例如:
我有一个用户控制器
public class UserController : ApiController {
Get - returns a User
Post and Put - Add and update a User
}
我有一个与上面相同的患者控制器,如果我在每个控制器中有我的搜索方法,我应该有一个SearchController,例如。
public class SearchController : ApiController {
SearchUsers() - returns ICollection<User>
SearchPatients() - returns ICollection<Patient>
}
我意识到没有明确的答案,只想对最佳实践提出一些建议
答案 0 :(得分:2)
如果你对SRP感到疯狂并且没有找到适当的责任级别,那么你最终会无所事事。
我将用户控制器视为负责在用户资源API之间进行调解以及如何在应用程序内部实现该概念。在这种情况下,在单个控制器中进行所有api操作是有意义的。
那就是说我们遵循命令/查询分离,所以我们的控制器委托命令或查询来完成实际的工作。这样我们的控制器应该改变的唯一原因是我们想要改变我们提供的API。
答案 1 :(得分:1)
我会在相应的控制器上引入搜索作为操作,如果您想跟踪所有具有搜索操作的控制器,请在其上添加一个界面。
public interface ISearchable
{
IHttpActionResult Search(string q);
}
public class UsersController : ApiController, ISearchable
{
[Route("api/Users/Search")]
[HttpGet]
public IHttpActionResult Search([FromUri] string q)
{
var userRepo = new UserRepo();
//this search method can be as complex as needed
//search initials, middle names, phone numbers, whatever you need.
var results = userRepo.Search(q);
return this.Ok(results);
}
}
用法:
https://domain.com/api/Users/Search?q=smith
这使您的客户非常清楚,因为他们不必了解特定的SearchController,它基本上就是一堆RPC。如果您考虑搜索是什么,它基本上是一个不是标准http动词的动词,所以我们将它作为动作附加到路线上。我们仍然在处理Users集合,类似于针对集合的GET或POST。由于我们没有将SEARCH作为有效的HTTP方法,因此动作是下一个最佳选择。
参考SOLID。这使您的控制器保持简单的控制器。它的工作(IMO)是控制请求并将其路由到逻辑。在这种情况下,它采用了路由,将其映射到UserRepo并执行了搜索方法。搜索不是控制器的工作,你有另一个班级做那个繁重的工作。控制器只是根据请求处理应该执行的逻辑。即使返回的数据也会通过序列化器推迟到管道中的后期,因此SOLID应该在控制器上保持为真。