简体   繁体   English

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

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

I have the index.cshtml under the /Pages folder.我在 /Pages 文件夹下有 index.cshtml。 And the web api controller in the same folder:和 web api controller 在同一文件夹中:

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

Now I'm expected that this code should work (as it works in Asp Core 2):现在我预计这段代码应该可以工作(因为它在 Asp Core 2 中工作):

var apiUri = Url.Action(action: "GetValue", controller: "Values");
var apiUri2 = Url.ActionLink(action: "GetValue", controller: "Values");

But it doesn't work (return nulls): As well as all other options I have tried :但它不起作用(返回空值):以及我尝试过的所有其他选项:

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

How to force Url.Action work for web api controller in CORE 3 (4 and 5)?如何强制Url.Action为 web api Z594C103F2C6E04C3D8AB059F031 工作?

Here is the IActionDescriptorCollectionProvider.ActionDescriptors.Items information:这是IActionDescriptorCollectionProvider.ActionDescriptors.Items信息: 在此处输入图像描述

Project structure (actually core web app):项目结构(其实是核心web app):

在此处输入图像描述

Command window results:命令 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
>

For those who minus as "obvious" (I guess), test youself:对于那些减去“明显”(我猜)的人,测试自己:

  1. [ApiController] commented out (controller is no marked as ApiController); [ApiController] 注释掉(控制器没有标记为 ApiController); [Route("api/[controller]/[action]")] added; [Route("api/[controller]/[action]")] 添加; no endpoints.* modifications - is the controller "routable"?没有端点。* 修改 - controller “可路由”吗? (answer "no") (回答“不”)
  2. still not [ApiController] but now we add endpoints.MapControllerRoute("default", "api/[controller]/[action]");仍然不是 [ApiController] 但现在我们添加 endpoints.MapControllerRoute("default", "api/[controller]/[action]"); - is the controller "routable"? - controller 是“可路由的”吗? (answer "yes") (回答“是”)
  3. now we additionaly to (2) comment out [Route("api/[controller]/[action]")] - is the controller "routable"?现在我们另外 (2) 注释掉 [Route("api/[controller]/[action]")] - controller 是“可路由的”吗? (answer "no") (回答“不”)
  4. now return [Route("api/[area]/[controller]/[action]")] but also add [ApiController] and add [Area("myarea")] is the controller "routable"?现在返回 [Route("api/[area]/[controller]/[action]")] 但还添加 [ApiController] 并添加 [Area("myarea")] 是 controller “可路由”吗? (answer "no") (回答“不”)

The reason it does not work its because the routing for ApiController works different.它不起作用的原因是 ApiController 的路由工作方式不同。

In your example:在您的示例中:

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

Assuming that this in localhost假设这在 localhost

Really means the route is "http://localhost/api/Values"真正意味着路由是“http://localhost/api/Values”

if you want for example "http://localhost/api/Values/GetValue" you need to do:例如,如果您想要“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" };
    }
}

As for using Url.Action you might get away with using something like:至于使用 Url.Action 你可能会使用类似的东西逃脱:

///api/Values/GetValue"
var apiUri1 = Url.Action(action: "GetValue", controller: "Values");

///api/Values/GetAnotherValue"
var apiUri2 = Url.Action(action: "GetAnotherValue", controller: "Values");

Finally you need to make sure you mapped the api controller routes最后,您需要确保映射了 api controller 路线

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
});

Finally your "ApiController" controllers do not need to be in the "Pages" folder.最后,您的“ApiController”控制器不需要位于“Pages”文件夹中。 Api controllers route by Attributes not by "folder location". Api 控制器按属性而不是“文件夹位置”路由。 I suggest you put them inside a folder called Controllers in the root of your project.我建议您将它们放在项目根目录中名为 Controllers 的文件夹中。

The other answer in this post seems to "work" but as soon as you add another action to the the API controller you will realize it produces the wrong urls on the Url.Action calls because in ApiControllers the routing does not happen by "Method Name"这篇文章中的另一个答案似乎“有效”,但是一旦您向 API controller 添加另一个操作,您就会意识到它会在 Url 中产生错误的 URL,因为方法调用 AController 不会发生。 "

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM