Asp.net core ASP.NET WebAPI传统路由是否可以在不指定操作和HTTP谓词约束的情况下工作?
在我们的经典ASP.NETWebAPI项目中,我们可以声明一个路由,框架将根据请求中的HTTP谓词选择正确的操作 然而,在.NETCoreWebAPI中,我尝试了以下路由配置Asp.net core ASP.NET WebAPI传统路由是否可以在不指定操作和HTTP谓词约束的情况下工作?,asp.net-core,routing,asp.net-core-webapi,Asp.net Core,Routing,Asp.net Core Webapi,在我们的经典ASP.NETWebAPI项目中,我们可以声明一个路由,框架将根据请求中的HTTP谓词选择正确的操作 然而,在.NETCoreWebAPI中,我尝试了以下路由配置 app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapControllerRoute( name: "DefaultRoute", pattern: "{controller}/{id?}"
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方法约束,以使其正常工作
这个问题只是关于传统路由,建议切换到属性路由并不是答案。路由负责将请求URL映射到端点,它有两种类型:传统路由和属性路由 从您的问题来看,您期望使用默认路由的常规路由,您可以使用下面的代码行实现它
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]属性来装饰控制器,那么您必须使用属性路由,并且在启动类中定义的任何常规路由都将被覆盖。请查看更多详细信息
这是否意味着对于传统路由,我们需要添加具有相同模式的多个路由,并带有默认操作和HTTP方法约束,以使其正常工作
是的,在asp.net core web api中,如果要使用常规路由,需要先删除[ApiController]属性和[Route]属性,然后使用以下带有默认操作的路由
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=WeatherForecast}/{action=Get}/{id?}");
});
指
更新:使用Url重写
您可以随时编写自己的url重写规则以满足您的要求。请参阅下面的演示,该演示将处理url-like/weatherforecast:
创建重写规则:
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?}"
);
});
我在ASP.NET Core中的经典ASP.NET WebAPI中发现了一个试图模拟此行为的问题: 这个例子在.NETCore2和MVC中都有,但在.NETCore3WebAPI中尝试它的效果是一样的 答案似乎是否定的,在ASP.NET Core WebAPI中,如果路由模式中没有操作,并且没有HTTP方法约束,则框架不会自动尝试与请求中基于HTTP谓词的操作匹配。
为了实现这一点,需要添加具有默认操作和动词约束的多个路由。那么,如果请求是POST或PUT,但url是/weatherforecast,会发生什么情况?在这种情况下,它将执行Get方法,因为这是默认操作,即使Http动词不是Get?@stormtrooper No,上面的配置只是一个示例。它还遵循规则/controller/action处理所有请求,因此它应该是/weatherforecast/post.Ok,您的意思是对于上面的配置,带有url/weatherforecast的POST请求将返回404?这意味着为了使带有URL/weatherforecast的POST请求能够工作,需要配置一个带有HttpMethod约束的额外路由,不是吗?@Stormthoper不太可能,要做的一个技巧是添加{controller=weatherforecast}/{action=POST}/{id}上面的代码对MVC的作用是相同的。为什么不想在url中使用动作名称?@Stormthoper我尝试用url重写,也许这是一个解决方法。请参阅我编辑的答案。