【问题标题】:What is the best way to organize webapi controller?组织 webapi 控制器的最佳方法是什么?
【发布时间】:2017-03-02 09:52:48
【问题描述】:

我有一些课程,例如CustomerBookMovieGame。 我为每个实体创建了 4 个控制器来执行 CRUD 并为每个实体指定逻辑。 现在的问题是我想检索customerId 的游戏列表 我应该将方法操作放在CustomerController 还是GamesController 中? 路线会是这样"/api/customers/123/games" 书籍,电影也是如此。所以每个控制器 Book、Game、Movie 中的 3 个方法或 Customer 控制器中的 3 个方法 那么管理此问题的最佳方法是什么?

谢谢

【问题讨论】:

    标签: c# asp.net-web-api routes


    【解决方案1】:

    要理解的是,web api 很大程度上是基于 REST 的。并且 rest 是基于资源的,所以如果你返回资源 Games,那么你的 GamesController 应该处理它。简单

    让您的客户控制器返回游戏会很有趣。 默认情况下,您的 Games 控制器将具有以下内容:

    [HttpGet]
    [Route("api/games/{customerId}"]
    public List<Games> Get(int customerId)
    {
        // get games from repository
        return games;
    }
    

    举个例子:

    [RoutePrefix("api")]
    public class TripsController: ApiController
    {
        #region Fields
    
        private readonly IQueryDispatcher _queryDispatcher;
    
        #endregion
    
        #region Constructors
    
        /// <summary>
        /// Initializes a new instance of the <see cref="TripsController"/> class
        /// </summary>
        /// <param name="queryDispatcher">Query Dispatcher</param>
        public TripsController(IQueryDispatcher queryDispatcher)
        {
            if (queryDispatcher == null)
                throw new ArgumentNullException(nameof(queryDispatcher));
            _queryDispatcher = queryDispatcher;
        }
    
        #endregion
    
        #region Actions
    
        [HttpGet]
        [Route("trips", Name = "TripList")]
        public IHttpActionResult Get([FromUri]TripsQuery query)
        {
            try
            {
                if (query == null)
                    return BadRequest();
                var result = _queryDispatcher.Dispatch<TripsQuery, TripsQueryResult>(query);
                HttpContext.Current.Response.Headers.AddPaginationHeader(query, result, new UrlHelper(Request), "TripList");
    
                return Ok(result);
            }
            catch (Exception)
            {
                return InternalServerError();
            }
        }
    
        [HttpGet]
        [Route("trips/{tripId}")]
        public IHttpActionResult Get([FromUri]TripDetailsQuery query)
        {
            try
            {
                var result = _queryDispatcher.Dispatch<TripDetailsQuery, TripDetailsQueryResult>(query);
                return Ok(result);
            }
            catch (Exception)
            {
                return InternalServerError();
            }
        }
    
        #endregion
    }
    
    [RoutePrefix("api")]
    public class StopsController: ApiController
    {
        #region Fields
    
        private readonly IQueryDispatcher _queryDispatcher;
    
        #endregion
    
        #region Constructors
    
        /// <summary>
        /// Initializes a new instance of the <see cref="StopsController"/> class
        /// </summary>
        /// <param name="queryDispatcher">Query Dispatcher</param>
        public StopsController(IQueryDispatcher queryDispatcher)
        {
            if (queryDispatcher == null)
                throw new ArgumentNullException(nameof(queryDispatcher));
            _queryDispatcher = queryDispatcher;
        }
    
        #endregion
    
        [Route("trips/{tripId}/stops", Name = "StopList")]
        [HttpGet]
        public IHttpActionResult Get([FromUri]StopsQuery query)
        {
            try
            {
                if (query == null)
                    return BadRequest();
                var result = _queryDispatcher.Dispatch<StopsQuery, StopsQueryResult>(query);
                HttpContext.Current.Response.Headers.AddPaginationHeader(query, result, new UrlHelper(Request), "StopList");
                return Ok(result);
            }
            catch (Exception)
            {
                return InternalServerError();
            }
        }
    
        [Route("trips/{tripId}/stops/{stopId}")]
        [HttpGet]
        public IHttpActionResult Get([FromUri]StopDetailsQuery query)
        {
            try
            {
                if (query == null)
                    return BadRequest();
                var result = _queryDispatcher.Dispatch<StopDetailsQuery, StopDetailsQueryResult>(query);
                return Ok(result);
            }
            catch (Exception)
            {
                return InternalServerError();
            }
        }
    }
    

    所以你看,一次旅行可以有多个停靠点,但你检索停靠点的方式仍然在停靠点控制器中,但只是正确映射了路线

    【讨论】:

    • 嗨 Jinish,如果你把它放在 GameController 中,你的路线将是 api/games/123 => 这条路线通过 id 获取单个游戏,而不是通过客户获取列表游戏。我认为 CustomerController "api/customers/123/games" 中的路线应该是相同的。只需将其放在 CustomerController 或 GameController 中即可。
    • 没错。但唯一的区别是,如果我们根据 REST 及其代表的内容进行讨论,那么游戏应该由 GamesController 返回。您当然可以使用属性路由并拥有在其他任何地方返回游戏的端点。但是既然你问的是最好的方法(可能是最佳实践),所以我建议上面
    • 不,我的意思是把它放在 GameController 中是正确的,但从 [Route("api/games/{customerId}"] 更改为 [Route("api/customers/{customerId}/游戏”]
    • aah..right,对不起,我的错。路线应该类似于:[Route("customers/{customerId}/games")]。但它仍应进入 Games 控制器。
    • 是的,我同意它应该在 GameController 中。关于“api/customers/{customerid}/games”和“api/games/customers/{customerid}”之间的路线你怎么看
    猜你喜欢
    • 2021-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 2011-12-17
    • 2010-11-19
    • 2013-12-03
    • 1970-01-01
    相关资源
    最近更新 更多