c# - 在 Razor Pages 应用程序中获取 Web api 控制器方法的 URL?
问题描述
我在 /Pages 文件夹下有 index.cshtml。和同一文件夹中的 web api 控制器:
[Route("api/[controller]")]
[ApiController]
public class ValuesController: ControllerBase
{
[HttpGet]
public IEnumerable<string> GetValue(){
return new string[] { "value1", "value2" };
}
}
现在我预计这段代码应该可以工作(因为它在 Asp Core 2 中工作):
var apiUri = Url.Action(action: "GetValue", controller: "Values");
var apiUri2 = Url.ActionLink(action: "GetValue", controller: "Values");
但它不起作用(返回空值)!以及我尝试过的所有其他选项:
var apiUri3 = Url.Action(action: "GetValue", controller: "ValuesController");
如何强制Url.Action
CORE 3(4 和 5)中的 web api 控制器工作?
这是IActionDescriptorCollectionProvider.ActionDescriptors.Items
信息:
项目结构(实际上是核心网络应用程序):
命令窗口结果:
>? Url.Action(action: "GetValue", controller: "Values");
null
>? Url.Action(action: "GetValue", controller: "ValuesController");
null
>? Url.Action(action: "Value", controller: "ValuesController");
null
>? Url.Action(action: "Value", controller: "Values");
null
>
对于那些减去“明显”(我猜)的人,测试自己:
- [ApiController] 注释掉(控制器没有标记为 ApiController);[Route("api/[controller]/[action]")] 添加;没有端点。* 修改 - 控制器是否“可路由”?(回答“不”)
- 仍然不是 [ApiController] 但现在我们添加 endpoints.MapControllerRoute("default", "api/[controller]/[action]"); - 控制器是“可路由的”吗?(回答“是”)
- 现在我们另外 (2) 注释掉 [Route("api/[controller]/[action]")] - 控制器是“可路由的”吗?(回答“不”)
- 现在返回 [Route("api/[area]/[controller]/[action]")] 但还要添加 [ApiController] 并添加 [Area("myarea")] 控制器是否“可路由”?(回答“不”)
解决方案
它不起作用的原因是 ApiController 的路由工作方式不同。
在您的示例中:
[Route("api/[controller]")]
[ApiController]
public class ValuesController: ControllerBase
{
[HttpGet]
public IEnumerable<string> GetValue(){
return new string[] { "value1", "value2" };
}
}
假设这在 localhost
真正意味着路由是“http://localhost/api/Values”
例如,如果您想要“http://localhost/api/Values/GetValue”,您需要执行以下操作:
[Route("api/[controller]")]
[ApiController]
public class ValuesController: ControllerBase
{
[HttpGet("GetValue")]//notice the extra piece of route we added here
public IEnumerable<string> GetValue()
{
return new string[] { "value1", "value2" };
}
[HttpGet("GetAnotherValue")]//notice the extra piece of route we added here
public IEnumerable<string> GetValue()
{
return new string[] { "value1", "value2" };
}
}
至于使用 Url.Action 你可能会使用类似的东西:
///api/Values/GetValue"
var apiUri1 = Url.Action(action: "GetValue", controller: "Values");
///api/Values/GetAnotherValue"
var apiUri2 = Url.Action(action: "GetAnotherValue", controller: "Values");
最后,您需要确保映射了 api 控制器路由
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers(); // Map attribute-routed API controllers
//endpoints.MapDefaultControllerRoute(); // Map conventional MVC controllers using the default route
endpoints.MapRazorPages();//map razor pages
});
最后,您的“ApiController”控制器不需要位于“Pages”文件夹中。Api 控制器按属性路由,而不是按“文件夹位置”。我建议您将它们放在项目根目录中名为 Controllers 的文件夹中。
这篇文章中的另一个答案似乎“有效”,但是一旦您向 API 控制器添加另一个操作,您就会意识到它会在 Url.Action 调用中产生错误的 url,因为在 ApiControllers 中,路由不会通过“方法名称”发生"
推荐阅读
- javascript - 带有标题和正文的 axios 发布请求不起作用
- reactjs - 如何在反应表中添加不区分大小写的排序?
- php - FPDF FPDI 如何从不同的 FPDF 类导入页面?
- sql - 我想在 oracle SQL 中查找所有经理姓名及其所有经理姓名
- java - 为什么每个请求都调用@InitBinder 方法?
- javascript - 在 Promise.prototype.then() 中传递参数
- google-maps - Google Maps API 和 duration_in_traffic
- java - 如何让用户决定按钮的特定颜色
- node.js - Firebase 功能 - 数据库缓存?
- python - 我需要 sqlite3 的提示