【问题标题】:How to support both kinds of URLs如何同时支持这两种 URL
【发布时间】:2019-12-03 12:40:13
【问题描述】:

我希望两者都能调用 GET:

/api/Test/Test/1

/api/Test/Test?id=1

public class TestController : ApiController
{
    [HttpGet]
    public string Test(int id)
    {
        return "Test";
    }
}

如何配置路由?

我有默认的:

            config.MapHttpAttributeRoutes();

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

这会使“/api/Test/Test?id=1”工作,但不能工作“/api/Test/Test/1”

我尝试在操作上添加属性路由,这使得“/api/Test/Test/1”工作但现在“/api/Test/Test?id=1”不起作用:

        [HttpGet]
        [Route("api/test/test/{id}")]
        public string Test(string id)
        {
            return "a";
        }

【问题讨论】:

  • 您使用的 .NET 版本是什么?
  • 我在 ASP.NET 上,而不是 Core
  • 好的,所以我创建了一个新的 ASP.NET MVC 项目,但我无法重现您所描述的内容,尽管我可以发现一些差异,例如路线相似但不完全相同的。使用默认路由配置,您在上面描述的方法在这两种情况下都适用。您能否提供有关您的环境的更多详细信息?带有您问题的最小工作示例的 git repo 真的很有帮助。
  • @IraklisGkougkousis 这可能是因为您只是在没有任何其他修改的情况下运行。以下是具体步骤: 1. 创建一个新应用并选择“Web API”模板。 2. 在ValuesController 中,将Get 操作重命名为Test,并为其添加[HttpGet] 属性。调用“api/Values/Test?id=5”有效,但不能调用“api/Values/Test/5”
  • 这很有趣。创建默认 MVC 项目时,您想要的东西开箱即用,但在 API 项目模板上却不行!即使路线配置看似相同。我正在和朋友一起调查此事,我会尽快回复您。

标签: asp.net asp.net-web-api asp.net-mvc-routing


【解决方案1】:

使用 ASP.NET Web API 模板,我配置了这样的 WebApi 路由:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}"
);

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

您需要小心包含在控制器中的操作。例如,我有这样的ValuesController

public class ValuesController : ApiController
{
    [HttpGet]
    public string Test(string id = "")
    {
        return "test " + id;
    }
}

如上图配置路由,api会响应如下请求:

/api/values/2
/api/values/test/2
/api/values/test?id=2

但是,如果您在同一个控制器中添加第二个 HttpGet 操作,事情就会变得复杂。服务器在尝试响应映射到第一条路由 (DefaultApi) 的请求时,将无法确定要发送哪个 get 操作。 DefaultApi 路由类型依赖于控制器将只有一个操作来服务每种 HTTP 请求的约定。如果您添加第二个名为 TryHttpGet 操作:

[HttpGet]
public string Try(int id)
{
    return "try " + id;
}

服务器会响应如下:

/api/values/test/2    -> WORKS
/api/values/test?id=2 -> WORKS
/api/values/try/2     -> WORKS
/api/values/try?id=2  -> WORKS
/api/values/2         -> DOES NOT WORK, Multiple GET methods. server can't decide which to use

如果您打算在同一控制器中对每种类型的 HTTP 请求使用一种以上的方法,我建议删除 DefaultApi 路由并仅保留 ActionApi。另一个例子:

// Removed "DefaultApi"
config.Routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);
public class ValuesController : ApiController
{
    [HttpGet]
    public string Test(int id)
    {
        return "test " + id;
    }

    [HttpGet]
    public string Try(int id)
    {
        return "try " + id;
    }

    [HttpGet]
    public string Play(string str)
    {
        return "play " + str;
    }
}

现在,服务器将成功处理以下请求:

/api/values/test/3       -> WORKS
/api/values/test?id=3    -> WORKS
/api/values/try/3        -> WORKS
/api/values/try?id=3     -> WORKS
/api/values/play?str=3   -> WORKS

但是,这些都行不通:

/api/values/play/3       -> DOES NOT WORK
/api/values/play?id=3    -> DOES NOT WORK

“Play”方法的参数不称为“id”,服务器不知道你想要什么。回应:

<Error>
    <Message>
        No HTTP resource was found that matches the request URI 'https://localhost:44327/api/values/play/3'.
    </Message>
    <MessageDetail>
        No action was found on the controller 'Values' that matches the request.
    </MessageDetail>
</Error>
/api/values/3

服务器期望控制器名称之后的内容,在这种情况下为values,是一个控制器动作。 3 显然不是,所以服务器不知道如何处理请求。

<Error>
    <Message>
        No HTTP resource was found that matches the request URI 'https://localhost:44327/api/values/3'.
    </Message>
    <MessageDetail>
        No action was found on the controller 'Values' that matches the name '3'.
    </MessageDetail>
</Error>

我希望这篇文章能够为您提供足够的信息来配置您想要的 API。

【讨论】:

  • 所以我在定义路线时错过了 {action} ??‍♂️...哦,天哪。谢谢!
  • 如何在 .NET Core 3.0 api 中配置带有动作的路由?
  • 您应该使用适当的标签编写一个问题,并准确指定您希望路由如何工作。帮助我们帮助您。
猜你喜欢
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
  • 2014-08-26
  • 1970-01-01
  • 2013-05-19
  • 2011-05-03
  • 1970-01-01
  • 2012-08-30
相关资源
最近更新 更多