在 Razor Pages 应用程序中获取 url 到 web api 控制器方法?

Get url to web api controller method in the Razor Pages app?

我在 /Pages 文件夹下有 index.cshtml。和同一文件夹中的网络 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");

但它不起作用(return 空值)!以及我尝试过的所有其他选项:

 var apiUri3 = Url.Action(action: "GetValue", controller: "ValuesController");

如何在 CORE 3(4 和 5)中强制 Url.Action 为 Web api 控制器工作?

这是 IActionDescriptorCollectionProvider.ActionDescriptors.Items 信息:

项目结构(实际上是核心网络应用程序):

命令window结果:

>? 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
>

对于那些减去“明显”(我猜)的人,自己测试一下:

  1. [ApiController] 注释掉(控制器未标记为 ApiController); [Route("api/[controller]/[action]")] 添加;没有端点。* 修改 - 控制器是“可路由的”吗? (回答“否”)
  2. 仍然不是 [ApiController] 但现在我们添加 endpoints.MapControllerRoute("default", "api/[controller]/[action]"); - 控制器是“可路由的”吗? (回答“是”)
  3. 现在我们另外要 (2) 注释掉 [Route("api/[controller]/[action]")] - 控制器是“可路由的”吗? (回答“否”)
  4. 现在 return [Route("api/[area]/[controller]/[action]")] 但还要添加 [ApiController] 并添加 [Area("myarea") ] 控制器是“可路由的”吗? (回答“否”)

它不起作用的原因是 Api控制器的路由不同。

在你的例子中:

[Route("api/[controller]")]
[ApiController]
public class ValuesController: ControllerBase
{
    [HttpGet]
    public IEnumerable<string> GetValue(){
        return new string[] { "value1", "value2" };
    }
}

假设这在本地主机

真正的意思是路由是“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 的文件夹中。

这个 post 中的另一个答案似乎“有效”,但是一旦您向 API 控制器添加另一个操作,您就会意识到它在 [=34] 上产生了错误的 url =] 调用,因为在 Api 控制器中,路由不会通过“方法名称”发生