Skip to main content
 首页 » 编程设计

c#之ASP.Net Core WebApi 中的非属性路由

2024年02月27日31arxive

我需要构建项目,实现由供应商应用程序(将使用它)预定义的 REST API - 大约有数千个 REST 资源,其中一些操作由不同的 HTTP-Verb(POST、GET、PUT、DELETE、等..)。

因此,理想情况下,对于每个资源,我应该有一个像这样的类:

public class SomethingController 
{ 
  public Something Post(string name, DateTime time) 
  { 
     // ... 
  } 
 
  public int PostStrange(string text) 
  { 
     // ... 
  } 
 
  public Something Put([FromBody]Something item) 
  { 
     // ... 
  } 
 
  public void Delete(int id) 
  { 
     // ... 
  } 
} 

在以前的版本中,我可以在注册路由时调用 MapHttpRoute,从 ApiController 继承这样的类 - ASP.NET Web Api 将按照我的需要执行...但在 .NET Core 中我可以找不到像 MapHttpRoute/ApiController 这样的东西。现在有路由和 http-verb 属性,我需要为每个类/方法明确定义所有内容:

[Route("api/[controller]")] 
public class SomethingController : Controller 
{ 
    [HttpPost] 
    public Something Post(string name, DateTime time) 
    { 
        // ... 
    } 
 
    [HttpPost("api/[controller]/strange")] 
    public int PostStrange(string text) 
    { 
        // ... 
    } 
 
    [HttpPut] 
    public Something Put([FromBody]Something item) 
    { 
        // ... 
    } 
 
    [HttpDelete] 
    public void Delete(int id) 
    { 
        // ... 
    } 
} 

为数千个 REST 资源中的每一个编写此属性非常无聊且容易出错...

我在这里错过了什么吗?与旧的 ASP.NET 相比,为什么在相当新的和现代的 ASP.NET Core 中,构建 REST-Api 这样非常常见和重要的事情变得如此复杂?

请您参考如下方法:

有 nuget 包 Microsoft.AspNetCore.Mvc.WebApiCompatShim 其主要目标是使从 web api 到核心的迁移更容易。它还提供了一种方法来执行基于约定的路由到您需要的操作。所以,首先安装那个包,然后在启动时:

public void ConfigureServices(IServiceCollection services) { 
    // add conventions here 
    services.AddMvc().AddWebApiConventions();                 
} 
 
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { 
    app.UseMvc(routes => { 
        // map one global route 
        routes.MapWebApiRoute("WebApi", "api/{controller}"); 
    }); 
} 

在这个小的配置之后,你可以从 ApiController 继承你的 Controller ,它被添加到上面的包中以方便从 web api 迁移,或者原生的 asp.net 核心 Controller。 ApiController 示例:

public class SomeController : ApiController { 
    // maps to GET /api/Some 
    // note - no routing attributes anywhere 
    public HttpResponseMessage Get() { 
        return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
 
    // maps to POST /api/Some 
    public HttpResponseMessage Post() { 
        return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
} 

native asp.net 核心 Controller :

// mark with these attributes for it to work 
[UseWebApiRoutes] 
[UseWebApiActionConventions] 
public class TestController : Controller { 
    // maps to GET /api/Test 
    // no routing attributes, but two "conventions" attributes 
    public IActionResult Get(string p) { 
        return new ObjectResult(new { Test = p }); 
    } 
} 

您还可以使用这些属性标记您的基本 Controller :

[UseWebApiRoutes] 
[UseWebApiActionConventions]     
public class BaseController : Controller { 
 
} 
 
public class TestController : BaseController { 
    // maps to GET /api/Test 
    // no attributes 
    public IActionResult Get(string p) { 
        return new ObjectResult(new { Test = p }); 
    } 
} 

如果您不是从网络 API 迁移 - 我建议使用 native Controller。 ApiController 具有不同的结构(类似于 asp.net web api ApiController),因此没有太多理由将其用于预期目标(从 web api 迁移)以外的任何用途。