ASP.NET WebAPI常规路由是否可以在不指定操作和HTTP动词约束的情况下工作?

问题描述 投票:0回答:2

在我们经典的ASP.NET WebAPI项目中,我们可以声明一条路由,并且框架将基于请求中的HTTP动词选择正确的操作。

但是在.NET Core WebAPI中,我尝试了以下路由配置

app.UseEndpoints(endpoints =>
{
   endpoints.MapControllers();
   endpoints.MapControllerRoute(
      name: "DefaultRoute",
      pattern: "{controller}/{id?}"
   );
});

我的控制器有一种方法

public class WeatherForecastController : ControllerBase
{
   [HttpGet]
   public WeatherForecast Get()
   {
      //return weather forecast
   }
}

[尝试以下URL时,我得到404,而在类似的经典ASP.NET WebAPI项目中,它将自动执行Get方法。

https://localhost/weatherforecast

这是否意味着对于常规路由,我们需要添加具有相同模式,具有默认操作和HTTP方法约束的多个路由,以使其正常工作?

此问题仅与常规路由有关,建议切换到属性路由不是答案。

asp.net-core routing asp.net-core-webapi
2个回答
0
投票

路由负责将请求URL映射到端点,它具有两种类型的常规路由和属性路由。

并且从您的问题中,您期望使用默认路由的常规路由,可以使用下面的代码行实现它。NETCORE。

app.UseMvc(routes =>
{
    routes.MapRoute("default", "{controller=Search}/{action}/{id?}");
});

注意:但是请记住,如果使用[ApiController]属性装饰控制器,则对流路由将不起作用。

默认情况下,.NET CORE支持属性路由,因此您必须通过在控制器级别上放置[Route]属性来为路由添加前缀。请参见下面的示例

    [Route("api/[controller]")]
    [ApiController]
    public class SearchController : ControllerBase
    {

        [HttpGet("{company}")]
        public IActionResult Get(string company) 
        {
            return Ok($"company: {company}");
        }

        [HttpGet("{country}/{program}")]
        public IActionResult Get(string country, string program) 
        {
            return Ok($"country: {country} program: {program}");
        }
    }

上面的代码将按预期工作(属性路由)。

如果您要通过[ApiController]属性装饰控制器,则必须使用属性路由,并且启动类中定义的任何常规路由都将被覆盖。请查看更多详细信息here


0
投票

这是否意味着对于常规路由,我们需要添加具有相同模式,具有默认操作和HTTP方法约束的多个路由,以使其正常工作?

是的,在asp.net核心Web API中,如果要使用常规路由,则需要首先删除[ApiController]属性和[Route]属性,并使用以下具有默认操作的路由

app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=WeatherForecast}/{action=Get}/{id?}");
    });

参考Conventional Routing in ASP.NET Core API

更新:使用网址重写

您可以随时编写自己的url重写规则来满足您的要求。请参阅下面的演示,该示例处理类似于/weatherforecast的url:

创建重写规则:

public class RewriteRuleTest : IRule
    {
        public void ApplyRule(RewriteContext context)
        {
            var request = context.HttpContext.Request;
            var path = request.Path.Value;// path= "/weatherforecast" for example

            if(path !=null)
            {
                context.HttpContext.Request.Path = path + "/" + request.Method; 
                // "/weatherforecast/post"
            }
        }
    }

Startup.cs

app.UseRewriter(new RewriteOptions().Add(new RewriteRuleTest()));
app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapControllerRoute(
        name: "GetRoute",
        pattern: "{controller=WeatherForecast}/{action=Get}/{id?}"
    );
});
© www.soinside.com 2019 - 2024. All rights reserved.