【问题标题】:How can i have multiple GET methods in single Controller如何在单个控制器中有多个 GET 方法
【发布时间】:2016-08-24 07:22:38
【问题描述】:
namespace EmployeeApi.Controllers
{
    public class EmployeeDetailsController : ApiController
    {
        // GET api/employeedetails
        public IEnumerable<Employee> Get()
        {


        }


        public IEnumerable<Details> Get(int id)
        {

        }

        public IEnumerable<Team> GetTeamMember()
        {

        }
        public IEnumerable<Details> GetTid(int id)
        {


        }
}


I would like to have my webApi something like this:

1)  IEnumerable<Employee> Get()         -> api/employeedetails
2)  IEnumerable<Details> Get(int id)    -> api/employeedetails/id
3)  IEnumerable<Team> GetTeamMember()   -> api/employeedetails/id/teammember
4)  IEnumerable<Details> GetTid(int id) -> api/employeedetails/id/teammember/tid

我尝试对路由进行更改,但由于我是新手,不太了解。所以,请有人帮助我理解并指导我应该如何做。 提前谢谢..:)

【问题讨论】:

    标签: c# asp.net-mvc-4 asp.net-web-api


    【解决方案1】:

    您可以使用Attribute Routing 执行此操作。 我更喜欢使用它们,因为它们可以简单地概述在阅读控制器方法时如何配置路由。

    namespace EmployeeApi.Controllers
    {
        public class EmployeeDetailsController : ApiController
        {
            // GET api/employeedetails
            [Route("api/employeedetails")]
            [HttpGet]
            public IEnumerable<Employee> Get()
            {
    
            }
    
            // GET api/employeedetails/1
            [Route("api/employeedetails/{id}")]
            [HttpGet]
            public IEnumerable<Details> Get(int id)
            {
    
            }
    
            // GET api/employeedetails/id/teammember
            [Route("api/employeedetails/id/teammember")]
            [HttpGet]
            public IEnumerable<Team> GetTeamMember()
            {
    
            }
    
            // GET api/employeedetails/id/teammember/1
            [Route("api/employeedetails/id/teammember/{tid}")]
            [HttpGet]
            public IEnumerable<Details> GetTid(int tid)
            {
    
    
            }
    }
    

    您还可以在控制器顶部使用 RoutePrefix 来指定控制器路由的前缀,在您的情况下为“api/employeedetails”。您可以在链接中的“路由前缀”部分找到更多详细信息

    【讨论】:

    • 我收到此错误...XmlDocumentationProvider 没有实现接口成员 GetDocumentation
    • @MahekMerchant 试试这个链接中的解决方案stackoverflow.com/questions/22295078/…
    • 如何删除控制器名称...我想要 api/Get 而不是 api/employeedetails/Get
    • @MahekMerchant 在路由中这样写:[Route("api/Get")]
    【解决方案2】:

    在相关 cmets 列表增加后,我现在将重组我原来的答案。

    如果您无法按照 Marcus 的回答中的建议使用属性路由(请参阅底部的更新声明),您需要配置您的路由(可能在 App_Start/RouteConfig.cs 文件中)。您可以在那里尝试以下代码:

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                name: "GetEmployeeDetails",
                url: "api/employeedetails",
                defaults: new { controller = "EmployeeDetails", action = "GetEmployees" }
            );
    
            routes.MapRoute(
                name: "GetEmployeeDetailsById",
                url: "api/employeedetails/{employeeId}",
                defaults: new { controller = "EmployeeDetails", action = "GetDetails", employeeId = UrlParameter.Optional }
            );
    
            routes.MapRoute(
                name: "GetTeamMember",
                url: "api/employeedetails/{employeeId}/teammember",
                defaults: new { controller = "EmployeeDetails", action = "GetTeams", employeeId = UrlParameter.Optional }
            );
    
            routes.MapRoute(
                name: "GetTeamMemberById",
                url: "api/employeedetails/{employeeId}/teammember/{teamId}",
                defaults: new { controller = "EmployeeDetails", action = "GetDetailsForTeam", employeeId = UrlParameter.Optional, teamId = UrlParameter.Optional }
            );
        }
    }
    

    可能会有更多路由(例如通用默认路由)以及要忽略的路由,但这超出了此问题的范围。

    这些路由对应于控制器类中的以下操作方法:

    public class EmployeeDetailsController : Controller
    {
        public IEnumerable<Employee> GetEmployees()
        {
            // Get your list of employees here
    
            return ...;
        }
    
        public IEnumerable<Detail> GetDetails(int employeeId = 0)
        {
            // Get your list of details here
    
            return ...;
        }
    
        public IEnumerable<Team> GetTeams(int employeeId = 0)
        {
            // Get your list of teams here
    
            return ...;
        }
    
        public IEnumerable<Detail> GetDetailsForTeam(int employeeId = 0, int teamId = 0)
        {
            // Get your list of details here
    
            return ...;
        }
    }
    

    您可能不需要GetDetailsForTeam() 方法的employeeId 参数,因为teamId 可能足以获得所需的信息。如果是这种情况,您可以从操作方法中删除参数相应的路由。

    这些路线配置非常简单。每条路由都需要一个唯一的名称,否则最终会出现运行时错误。 url - 好吧 - 包含路由应该处理的 url。之后,您可以指定控制器名称、要调用的操作方法(这些是您的Get 方法)及其各自的参数。

    关于命名约定的一两个词:在名为EmployeeDetailsController 的控制器中,我希望每个“通用命名”操作方法都返回一个或多个EmployeeDetails 对象(或它们各自的ActionResults)。因此,一个简单的Get() 方法应该返回一个或多个EmployeeDetails 对象。

    如果您想返回不同类型的对象,我会选择特定的名称(如我上面的代码中所建议的那样)。在您的情况下,这将是 GetEmployees() 方法、GetDetails(int employeeId = 0) 方法、GetTeams(int employeeId = 0) 方法和 GetDetailsForTeam(int employeeId = 0, int teamId = 0) 方法。注意这里的可选参数。

    如果您有这些方法,我将从路由开始。您需要确保每条路由都可以连接到一个确切的操作方法;这就是为什么我要求在其中一个 cmets 中提供完整的 URL。如果您不断收到“找到多个操作”错误,则说明您的路由 URL 未以这种方式配置。

    另外请注意,路线顺序确实很重要,尽管在您的示例中我没有看到任何冲突的路线。

    更新: 作为替代方案,您可以使用属性路由,将所需路由直接放入控制器内的操作方法的属性中。但要使其与 ASP.NET MVC 4 一起使用,您需要安装 AttributeRouting NuGet package

    【讨论】:

    • GetTid 函数只需要 tid 作为单个参数
    • 那么您可能必须在函数声明中将该参数重命名为tid。但是id 在两个teammember URL 中呢?那些不是有实际值的ID吗?
    • 层次结构应该是这样 1)emloyeedetails 应该显示 empid 列表,2)employeedetails/id 应该显示特定 empid 的详细信息 3)employeeddetails/id/teammember 应该显示该 empid 是否有团队成员
    • 4)employeedetails/id/teammember/tid 应该显示该empid的团队成员的详细信息
    • 所以您的GetTid 函数是否 需要idtid 参数,对吗?您还能如何获得所需的信息?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 2021-04-06
    • 1970-01-01
    相关资源
    最近更新 更多