在我们经典的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方法约束的多个路由,以使其正常工作?
此问题仅与常规路由有关,建议切换到属性路由不是答案。
路由负责将请求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。
这是否意味着对于常规路由,我们需要添加具有相同模式,具有默认操作和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?}"
);
});