gpt4 book ai didi

c# - asp.net core 2 中基本通用 Controller 类的 HttpGet 属性名称的路由名称

转载 作者:可可西里 更新时间:2023-11-01 07:57:22 25 4
gpt4 key购买 nike

我有一个通用 Controller ,它有几个派生 Controller 类。但我不知道如何处理 HttpGet 的路由名称,因为它需要常量。

[HttpGet("{id}", Name ="should not hard coded here for derived class")]
public virtual async Task<IActionResult> Get(int id)

我需要路由名称,因为在我的 HttpPost 函数中我想返回 CreatedAtRoute(),它需要 HttpGet 的路由名称

路由名称不能硬编码,因为所有派生类都需要有不同的路由名称。

这是基本 Controller

public abstract class BaseController<TEntity, TContext> : Controller where TEntity : BaseOptionType, new() where TContext : DbContext
{
private readonly IGenericRepository<TEntity, TContext> _repository;
private readonly ILogger<BaseGenericOptionTypesController<TEntity, TContext>> _logger;
public BaseController(IGenericRepository<TEntity, TContext> repository, ILogger<BaseController<TEntity, TContext>> logger)
{
_repository = repository;
_logger = logger;
}

[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[HttpGet("{id}", Name = "should not hard code here for derived class")]
public virtual async Task<IActionResult> Get(int id)
{
var optionType = await _repository.FindByIdAsync(id);
if (optionType == null)
{
_logger.LogInformation($"[ID not found]");
return NotFound();
}
return Ok(optionType);
}
}

这是派生 Controller

[Route("api/v1/DerivedControllerA")]
public class DerivedControllerA : BaseController<TimeOff, HRContext>
{
public DerivedControllerA(IGenericRepository<TimeOff, HRContext> repository, ILogger<DerivedControllerA> logger)
: base(repository, logger)
{

}
}

如有任何帮助,我们将不胜感激。

最佳答案

我不会与 NightOwl888 争论在 MVC 中使用基本 Controller 。有利也有弊,我处理过一些可以证明使用基本 Controller 的项目。

至于原始问题,似乎解决此问题的最简单方法是使用 CreatedAtAction 而不是 CreatedAtRouteCreatedAtAction 不需要您命名您的路线,您可以只使用来自基本 Controller 的 Get Action 名称。如果从 DerivedControllerA 调用 CreatedAtAction,它将为 DerivedControllerA 中的 Get 操作生成 URL,如果它被调用从 DerivedControllerB,它将为 DerivedControllerB 中的 Get 操作生成 URL。因此,似乎转向 CreatedAtAction 可以很好地涵盖您的用例。

这是对 CreatedAtAction 的示例调用:

[HttpPost]
public virtual IActionResult Post(/* ... */)
{
// Create and save an instance in repository
// var createdObject = ...;

return CreatedAtAction(nameof(Get), new
{
// Put actual id here
id = 123
}, createdObject);
}

常见的错误是使用 2 个参数调用 CreatedAtAction 的重载。此版本将创建的对象作为响应主体,而不是路由值,这通常会导致 No route matches the supplied values 错误。如果您不想在响应中返回创建资源的表示,您可以将 null 作为第三个参数传递:

    return CreatedAtAction(nameof(Get), new
{
// Put actual id here
id = 123
}, null);

如果出于某种原因你想坚持使用 CreatedAtRoute 调用,我想到的唯一可能的解决方案是在每个派生类中都有不同的操作,这些派生类只使用实际逻辑调用基方法:

[Route("api/v1/DerivedControllerA")]
public class DerivedControllerA : BaseController<TimeOff, HRContext>
{
// ...

[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[HttpGet("{id}", Name = "RouteForDerivedControllerA")]
public virtual Task<IActionResult> Get(int id)
{
return base.Get(id);
}
}

public abstract class BaseController<TEntity, TContext> : Controller where TEntity : BaseOptionType, new() where TContext : DbContext
{
// ...

public virtual async Task<IActionResult> Get(int id)
{
// Actual logic goes here
}
}

事实上,这种解决方案贬低了 BaseController 的使用。

关于c# - asp.net core 2 中基本通用 Controller 类的 HttpGet 属性名称的路由名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48633939/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com