如何在单个Controller中使用多个GET方法

时间:2016-08-24 07:22:39

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

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

我尝试对路由进行更改,但由于我是新手,所以可以理解得太多。所以,有些人可以帮助我了解并指导我应该如何做。     在此先感谢.. :))

2 个答案:

答案 0 :(得分:2)

您可以使用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,指定控制器路由的前缀,在您的情况下为&#34; api / employeedetails&#34;。您可以在&#34;路线前缀&#34;中找到更多详细信息。链接中的部分

答案 1 :(得分:0)

在相关评论列表增加之后,我现在将重新构建我原来的答案。

如果您无法使用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 ...;
    }
}

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

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

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

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

如果你有这些方法,我会从路由开始。您需要确保每个路由只能连接到一个操作方法;这就是我在其中一条评论中要求提供完整网址的原因。如果您不断收到“发现多个操作”错误,那么您的路径网址就不会以这种方式配置。

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

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