如何将Web API控制器添加到现有的ASP.NET Core MVC中?

28

我使用默认的ASP.NET Core MVC模板创建了一个项目。我希望也能在/api/{Controller}下创建一个RESTful API。我添加了一个新的Web API控制器(标准的Web API控制器类模板),但是我不能调用它。我收到了一个页面找不到的错误。我尝试在Startup.cs中添加路由,但它没有起作用:

app.UseMvc(routes =>
{
    routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
    routes.MapRoute(name: "api", template: "api/{controller=Admin}");
});

编辑:

就像我之前所说的,这都是默认模板。这是我添加的Web API控制器:

[Route("api/[controller]")]
public class AdminController : Controller
{                
    // GET api/values/5
    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "value";
    }

    // POST api/values
    [HttpPost]
    public void Post([FromBody]string value)
    {
    }

    // PUT api/values/5
    [HttpPut("{id}")]
    public void Put(int id, [FromBody]string value)
    {
    }

    // DELETE api/values/5
    [HttpDelete("{id}")]
    public void Delete(int id)
    {
    }
}

嗯,我不在我的家用电脑上,所以我可能错了,但我认为你不需要为API添加新路由。我认为你只需要从APIController基类继承,并从中派生自己的类。然后MVC应该会为你处理路由。此时,在你的路由中,你唯一拥有的就是默认路由,而MVC将为你处理API路由。 - Alex Moreno
这正是我所想象的,但导航到 http://localhost:27891/api/Admin 结果显示 ERR_CONNECTION_REFUSED。 - Alex G.
向下滚动到大约一半的位置,找到ProductsController。它继承自ApiController,而不是Controller。 - Alex Moreno
那已经过时了。他们合并了Controller和ApiController,现在两者之间没有实质性的区别:https://dev59.com/9VwY5IYBdhLWcg3wq5Qd?rq=1 - Alex G.
7个回答

11

两件事。

首先,在使用基于约定的路由时,更具体的路由应该放在更通用的路由之前,以避免路由冲突。

app.UseMvc(routes =>
{
    routes.MapRoute(name: "api", template: "api/{controller=Admin}");
    routes.MapRoute(name: "default", template: "{controller=Home}/{action=Index}/{id?}");
});

其次,您已经在控制器上使用属性路由,因此应该已经能够路由到控制器,除非您没有在控制器上拥有一个路由模板来接受 /api/{Controller}。这将需要一个默认路由。

[Route("api/[controller]")]
public class AdminController : Controller {
 
    [HttpGet("")] //Matches GET api/admin <-- Would also work with [HttpGet]
    public IActionResult Get() {
        return Ok();
    }

    [HttpGet("{id}")] //Matches GET api/admin/5
    public IActionResult Get(int id) {
        return Ok("value");
    }    

    //...other code removed for brevity
}

我的第一个想法是不要触碰app.UseMvc中的路由。然而,开箱即用,它不起作用。[Route("api/[controller]")]还不够。我按照您的建议添加了特定路由和通用路由之前的路由,就像上面一样。如果我尝试导航到https://localhost:27891/api/Admin,它仍然不起作用。令人惊讶的是,如果我去https://localhost:27891/[WHATEVER],它会触发AdminController中的Get()方法并将[WHATEVER]作为参数传递。这真的很奇怪。 - Alex G.

11

我用v3.1时做这件事很顺利:

将文件夹Controllers添加到项目中。在该文件夹下添加名为 TestController 的控制器(Controller)。 然后在 Startup.cs 中添加以下内容:

services.AddControllers();

public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddControllers();
    }

并且:

endpoints.MapControllers();
app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllers();
        });

然后我能够调用 /api/Test。


这对我有用!使用我的现有项目,我创建了模板dot net core API项目,并复制了控制器和类,这两行代码是唯一缺少的东西。 - TheMooCows237
在我的dotnetcore v5.0中有效。 - Daniel Szabo
你值得一百万个赞,天啊!比微软文档还好用。在.NET5中也适用。 - leat

8

如果有人在将WebAPI添加到.NET Core MVC时仍然遇到问题,只需在类之前插入[ApiController][Route("api/[controller]")]属性即可解决问题:

[Route("api/[controller]")]
[ApiController]
public class ListController
{ ... }

我没有在Startup.cs中添加路由映射,但它仍然可以正常工作。我使用的 .net 版本是 2.1.402。


3
更新到最新版本的ASP.NET Core,即v2.0.1(需要VS2017),问题得以解决。我认为这可能是旧版本中的一个错误或不足之处。

0

尝试将名称设置为“Admin”

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "Admin",
                template: "api/{controller=Admin}");
        });

不起作用。文档说路由的名称并不重要,除了用于URL生成。 - Alex G.

0

运行现有的 .net core MVC:

1

为了将API控制器添加到现有的.NET Core 6 MVC应用程序中, 打开Program.cs文件, 添加以下代码:
//for apis
builder.Services.AddRazorPages();
builder.Services.AddControllers();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
});

现在可以继续添加一个新的控制器:

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    //endpoint: http://localhost:5207/api/test/strings
    [HttpGet("strings")]
    public IActionResult TestMethod()
    {
        return Ok(new string[]{ 
        "23", "24"});
    }
}

在这里测试端点

2

这在我的 .net core 6 中有效


欢迎来到Stack Overflow。这个答案已经在2年前这里给出了。在发布新答案之前,请阅读所有其他答案。重复的答案对网站没有任何价值。 - JHBonarius

0

我尝试调用https://localhost:7052/api/TranslationsJS/GetAll,但是遇到了404找不到错误。

所以我的问题是在操作中出现了拼写错误。我定义了一个路由名称而不是路由模板(路径)。

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class TranslationsJSController : ControllerBase
{
    [HttpGet(Name = "GetAll")] // this didn't work because it is route name
    [HttpGet("GetAll")] // this worked because it is route template(path)
    public ActionResult<Dictionary<string, string>> GetAll()
    {
        var resourceSet = TranslationsJS.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
        var translationsJs = new Dictionary<string, string>();
        foreach (DictionaryEntry entry in resourceSet)
        {
            translationsJs.Add(entry.Key.ToString(), entry.Value.ToString());
        }
        return translationsJs;
    }
}

在 program.cs 文件中
builder.Services.AddControllersWithViews();

...

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

更多信息:

https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-7.0#route-name

https://csharp-video-tutorials.blogspot.com/2017/02/generating-links-using-route-names-in.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接