Web Api 忽略路由属性

Posted

技术标签:

【中文标题】Web Api 忽略路由属性【英文标题】:Web Api Ignoring Route Attribute 【发布时间】:2021-11-26 21:16:14 【问题描述】:

我正在处理一个 Web API 项目,当我运行它并尝试将路由用于控制器时,它不起作用,而是引发 404 错误。为什么 Web API 会忽略路由属性?

我将在下面留下代码:

[ApiController]
[Route("api/[controller]")]

public class Controller3 : ControllerBase

    private readonly IServiceContract3 _interest;
    public Controller3(IServiceContract3 interest)
    
        _interest = interest;
    

    [HttpGet]
    [Route("[action]")]
    [Route("api/Interest/GetInterests")]
    public IEnumerable<Interest> GetEmployees()
    
        return _interest.GetInterests();
    

    [HttpPost]
    [Route("[action]")]
    [Route("api/Interest/AddInterest")]
    public IActionResult AddInterest(Interest interest)
    
        _interest.AddInterest(interest);
        return Ok();
    

    [HttpPost]
    [Route("[action]")]
    [Route("api/Interest/UpdateInterest")]
    public IActionResult UpdateInterest(Interest interest)
    
        _interest.UpdateInterest(interest);
        return Ok();
    

    [HttpDelete]
    [Route("[action]")]
    [Route("api/Interest/DeleteInterest")]
    public IActionResult DeleteInterest(int id)
    
        var existingInterest = _interest.GetInterest(id);
        if (existingInterest != null)
        
            _interest.DeleteInterest(existingInterest.Id);
            return Ok();
        
        return NotFound($"Employee Not Found with ID : existingInterest.Id");
    

    [HttpGet]
    [Route("GetInterest")]
    public Interest GetInterest(int id)
    
        return _interest.GetInterest(id);
    


对于我的 Startup.cs

    public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    
        services.AddControllers();
        services.AddDbContextPool<DatabaseContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DB")));
    

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DatabaseContext context)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        

        context.Database.Migrate();

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        
            endpoints.MapControllers();
        );
    

如何修复路由?每次我尝试在浏览器中执行此操作时,例如 https://localhost:44316/api/Interest/GetInterests,我都会收到 404 错误。为什么会这样?

【问题讨论】:

当你转到http 地址时会发生什么? IServiceContract3 在哪里注册依赖注入? 【参考方案1】:

webapi 的控制器通常是这样定义的:

[ApiController]
[Route("api/[controller]")]
public sealed class InterestController : ControllerBase

    private readonly IServiceContract3 _interest;

    public InterestController(IServiceContract3 interest)
    
        _interest = interest;
    

    [HttpGet, Route("GetInterests")]
    public IActionResult GetEmployees()
    
        // this is located at: GET api/Interest/GetInterests
        return Ok(_interest.GetInterests());
    


    [HttpPost, Route("AddInterest")]
    public IActionResult AddInterest([FromBody] Interest interest)
    
        // this is located at: POST api/Interest/AddInterest
    

    [HttpPost, Route("UpdateInterest")]
    public IActionResult UpdateInterest([FromBody] Interest interest)
    
        // this is located at: POST api/Interest/UpdateInterest
    

    [HttpDelete, Route("DeleteInterest/id")]
    public IActionResult DeleteInterest([FromRoute] int id)
    
        // this is located at: DELETE api/Interest/DeleteInterest/id
    

    [HttpGet, Route("GetInterest/id")]
    public IActionResult GetInterest([FromRoute] int id)
    
        // this is located at: GET api/Interest/GetInterest/id
        return Ok(_interest.GetInterest(id));
    

首先,您要为控制器命名一个相关的名称,该名称将贯穿控制器的其余部分。所以,在这种情况下,我将Controller3 更改为InterestController。由于控制器的路由是"/api/[Controller]",所以会转换成"api/Interest"

接下来,删除[Action] 属性。在这种情况下您不需要它们。

然后,确保您的路线正确。如果您要传递 ID,请使用 id 在路由中定义您的 ID,并设置 [FromRoute] 属性以清楚起见。此外,使用[FromBody] 定义将来自正文的参数。其中很多是“默认”的(意味着您不需要添加它们),但它有助于清晰。

最后,如果您使用IActionResult 模式,请通过您的控制器坚持使用它。不要跨端点混合/匹配返回类型,因为这会混淆维护。

最后一件事: 您的控制器端点名称有些多余。例如,您可以这样做:

    [HttpGet, Route("")]
    public IActionResult GetEmployees()
    
        // this is located at: GET api/Interest
        return Ok(_interest.GetInterests());
    


    [HttpPut, Route("")]
    public IActionResult AddInterest([FromBody] Interest interest)
    
        // this is located at: PUT api/Interest/
    

    [HttpPost, Route("")]
    public IActionResult UpdateInterest([FromBody] Interest interest)
    
        // this is located at: POST api/Interest/
    

    [HttpDelete, Route("id")]
    public IActionResult DeleteInterest([FromRoute] int id)
    
        // this is located at: DELETE api/Interest/id
    

    [HttpGet, Route("id")]
    public IActionResult GetInterest([FromRoute] int id)
    
        // this is located at: GET api/Interest/id
        return Ok(_interest.GetInterest(id));
    

即:使用“HTTP 动词”来区分操作。

【讨论】:

【参考方案2】:

您必须通过使 api 成为根来修复您的路线。将“api”替换为“~/api”。恕我直言,您应该从操作中删除 [action] 并将其添加到控制器中。同时修复控制器名称

    [ApiController]
    [Route("~/api/[controller]/[action]")]
    public class  InterestController : ControllerBase

    [HttpGet("~/api/Interest/GetInterests")]
    public IEnumerable<Interest> GetEmployees()
     ....

   
    [HttpPost("~/api/Interest/AddInterest")]
    public IActionResult AddInterest(Interest interest)
    ...

    
    [HttpPost("~/api/Interest/UpdateInterest")]
    public IActionResult UpdateInterest(Interest interest)
     ...

    
    [HttpDelete("~/api/Interest/DeleteInterest/id")]
    public IActionResult DeleteInterest(int id)
    ....

    [HttpGet("~/api/Interest/GetInterest/id")]
    public Interest GetInterest(int id)

【讨论】:

以上是关于Web Api 忽略路由属性的主要内容,如果未能解决你的问题,请参考以下文章

忽略某些路由上的过期令牌

忽略某些路由上的过期令牌

在 Web 服务中忽略 DataMember 名称属性

Amazon Web服务Route 53忽略域名

在访问 Web 应用程序之前忽略对 Azure 应用服务的请求

忽略 ASP.net 中的 Javascript、CSS 和图像文件路由