我正在寻找一些建设性的建议。我试图映射多个控制器端点如何相互交互,这样我最终不会在多个控制器中编写相同的代码。请允许我用简单的看板示例进行说明。
我在想这里有两个(或三个)控制器:BoardController,CardController,SubCardController(未定)。现在让我们忽略卡可以组织成列表的事实,因为我们会在Board和Card控制器之间安装一个ListController。
董事会控制人:
public class BoardController : ApiController {
// among basic CRUD methods I have a method that returns single board
// implementation #1
// /api/board/getbyid?id=123
public HttpResponseMessage GetById(int id) {
var board = dataStore.GetById(id);
if (board == null)
return Request.CreateResponse(HttpStatusCode.NotFound);
return Request.CreateResponse(HttpStatusCode.OK, board);
}
// implementation #2
// /api/board/getbyid?id=123
public HttpResponseMessage GetById(int id) {
var board = GetById(id);
if (board == null)
return Request.CreateResponse(HttpStatusCode.NotFound);
return Request.CreateResponse(HttpStatusCode.OK, board);
}
[NonAction]
// normally methods like this one I declare as private
// but in this case CardController needs to call this method as well
public static Board GetById(int id) {
return dataStore.GetById(id);
}
}
请允许我澄清dataStore
是对另一个单独负责数据访问的控制器的引用。
卡控制器:
public class CardController : ApiController {
// among basic CRUD methods I might want to call BoardControllers GetById(id) method (to verify if board exists for example)
// implementation #1
public HttpResponseMessage GetAll(int boardId) {
// call BoardController.GetById(id) by issueing HTTP request
HttpRequestMessage _request = new HttpRequestMessage(HttpMethod.Get, requestUri);
HttpResponseMessage _response = Client.SendAsync(_request).Result;
Board board = _response.Content.ReadAsAsync<Board>().Result;
if (board == null /* || more condition(s) */)
return Request.CreateResponse(HttpStatusCode.NotFound);
// get cards and return
}
// implementation #2
public HttpResponseMessage GetAll(int boardId) {
// call BoardController.GetById(id) static method
var board = _boardCtrl.GetById(boardId);
if (board == null /* || more condition(s) */)
return Request.CreateResponse(HttpStatusCode.NotFound);
// get cards and return
}
}
这是我的两种替代解决方案。一方面实现#1不需要额外的静态方法,但另一方面,我认为从一个控制器动作发出HTTP请求以访问另一个控制器动作是不好的。
让我知道你们的想法。特别是如果有更整洁的替代品。
答案 0 :(得分:2)
根据需要创建服务并将其注入相关控制器。控制器应保持精益,不要关注实施问题。
public interface IBoardService {
Board GetById(int id);
//...other code removed for brevity
}
public class BoardController : ApiController {
readonly IBoardService dataSource;
public BoardController(IBoardService dataSource) {
this.dataSource = dataSource;
}
// /api/board/getbyid?id=123
public IHttpActionResult GetById(int id) {
var board = dataSource.GetById(id);
return board == null ? NotFound() : OK(board);
}
}
如果需要,电路板服务也可以重复使用,以便注入CardController
public class CardController : ApiController {
readonly IBoardService boardService;
readonly ICardService cardService;
public CardController(ICardService cardService, IBoardService boardService) {
this.cardService = cardService;
this.boardService = boardService;
}
public IHttpActionResult GetAll(int boardId) {
var board = boardService.GetById(boardId);
if (board == null /* || more condition(s) */)
return NotFound();
// get cards from card service and return
}
}
使用注入的服务方法允许在需要时重用它。
另外,尽量保持控制器的精益。
不需要控制器中的所有逻辑。
卡服务的实施可能取决于电路板服务,并且仅公开GetAllByBoardId(int id)
,这将减少示例中CardController
的逻辑。