C# 为什么WebApi路由配置默认值不包括操作参数?

C# 为什么WebApi路由配置默认值不包括操作参数?,c#,asp.net-mvc,asp.net-web-api,C#,Asp.net Mvc,Asp.net Web Api,我对WebApi有点陌生,所以也许有人可以向我解释一下,为WebApi添加的默认路由是: config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); 因此,给定一个如下所示的Ap

我对WebApi有点陌生,所以也许有人可以向我解释一下,为WebApi添加的默认路由是:

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
因此,给定一个如下所示的ApiController:

public class LookupController : ApiController
{

    [HttpGet] 
    public IHttpActionResult GetCountries()
    { 
        // do stuff
        return Ok();
    }

    [HttpGet] 
    public IHttpActionResult GetStates()
    { 
        // do stuff
        return Ok();
    }

}
它如何知道调用哪个操作?这不对吗

默认路线不应该更像:

        config.Routes.MapHttpRoute(
            name: "ApiWithAction",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

或者每个ApiController应该只有一个GET/UPDATE/DELETE等?这确实不能满足某些场景的需要…

严格地说,您的控制器不应该是这样的。开箱即用的思想是,控制器处理单个实体(如客户)的请求,并且映射到HTTP谓词的操作针对该实体进行操作。因此,在正常情况下,您的控制器看起来如下所示(针对简单的模型类使用脚手架创建,为简洁起见,省略了方法体):


Web API根据路由数据确定要调用的方法。您不需要指定操作,因为Web API将使用请求的动词(GET、POST、DELETE等)

如果希望在控制器中有多个GET操作,可以为每个操作指定一个路由

[Route("api/lookup/countries"]
[HttpGet] 
    public IHttpActionResult GetCountries()
    { 
        // do stuff
        return Ok();
    }

[Route("api/lookup/states"]
    [HttpGet] 
    public IHttpActionResult GetStates()
    { 
        // do stuff
        return Ok();
    }

此处提供了更多信息

默认路由允许您使用由其名称定义的操作。例如,
Get
将是一个HTTP Get,
Put
将是一个HTTP Put等。我看到的问题是,当您有多个操作与同一实体相关时,将它们拆分为单独的控制器没有多大意义。我想有两种get方法可能会起作用,但路由也不适用,建议怎么做?在这种情况下,您会收到一条错误消息,说
找到了与请求匹配的多个操作
,此时您需要设置不同的路由。@shenku,我不确定是否理解您的评论。如果多个操作与同一实体相关,则它们将位于同一控制器中,而不是单独的控制器中。正如我发布的示例所示,您有几个与客户实体相关的操作,它们都在同一个控制器中。@CraigW。我想他说的是,例如,你有两个动作,比如
public List GetCustomers()
public List GetDeadCustomers()
,那么它是如何工作的呢。我对此的评论是,如果没有进一步的路由更改,它将不会发生。@DavidG你是对的,这正是我的意思。你不必严格要求每个动作都有一个路由,你可以添加另一个路由,允许你将动作名称指定为@shenku在他的问题中提出的。
config.Routes.MapHttpRoute(
    name: "RestApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
    name: "RpcApi",
    routeTemplate: "rpc/{controller}/{action}"
);
[Route("api/lookup/countries"]
[HttpGet] 
    public IHttpActionResult GetCountries()
    { 
        // do stuff
        return Ok();
    }

[Route("api/lookup/states"]
    [HttpGet] 
    public IHttpActionResult GetStates()
    { 
        // do stuff
        return Ok();
    }