如何使用相似但不同的参数创建 ASP.NET Core Web API 控制器方法
How to create ASP.NET Core Web API controller method with similar but different parameter
我用 ASP.NET 核心创建了一个简单的 Web API。我有以下 API:
- GET /api/messages - 获取所有消息
- GET /api/messages/{id} - 通过 id
获取消息
- POST /api/messages - 添加一条新消息
- PUT /api/messages/{id} - 更新现有消息
- DELETE /api/messages/{id} - 删除一条消息
现在,我想要另一个 API 按消息所有者的姓名获取所有消息。
我试过的:
我试图创建这个 API,但它不起作用,因为它与 GET /api/messages/{id}:
冲突
GET /api/messages/{name} <-(由于冲突 API 而无效)
// GET: api/messages/{name}
[HttpGet("{name}")]
public IEnumerable<Message> GetMessagesByName(string name)
{
return _repository.GetMessages().Where(m => m.Owner == name);
}
这是我的消息模型Message.cs:
public class Message
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string Owner { get; set; }
public string Text { get; set; }
}
这是我的消息控制器MessagesController.cs:
[Route("api/[controller]")]
public class MessagesController : Controller
{
private readonly IMessageRepository _repository;
public MessagesController(IMessageRepository repository)
{
_repository = repository;
}
// GET: api/messages
[HttpGet]
public IEnumerable<Message> Get()
{
return _repository.GetMessages();
}
// GET api/messages/{id}
[HttpGet("{id}", Name = "GetMessage")]
public IActionResult GetById(long id)
{
var message = _repository.GetMessage(id);
if (message == null)
{
return NotFound();
}
return new ObjectResult(message);
}
// POST api/messages
[HttpPost]
public IActionResult Post([FromBody]Message message)
{
if (message == null)
{
return BadRequest();
}
_repository.AddMessage(message);
return CreatedAtRoute("GetMessage", new { id = message.Id }, message);
}
// PUT api/messages/{id}
[HttpPut("{id}")]
public IActionResult Put(long id, [FromBody]Message message)
{
if (message == null || message.Id != id)
{
return BadRequest();
}
var messageToUpdate = _repository.GetMessage(id);
if (messageToUpdate == null)
{
return NotFound();
}
messageToUpdate.Owner = message.Owner;
messageToUpdate.Text = message.Text;
_repository.UpdateMessage(messageToUpdate);
return new NoContentResult();
}
// DELETE api/messages/{id}
[HttpDelete("{id}")]
public IActionResult Delete(long id)
{
var message = _repository.GetMessage(id);
if (message == null)
{
return NotFound();
}
_repository.RemoveMessage(id);
return new NoContentResult();
}
}
问题:
如何创建一个 API 方法来通过邮件所有者的姓名获取所有邮件?
理想情况下,我希望 API 看起来像 GET /api/messages/{name},但认为这不可能,因为它与 GET /api/messages/{id} 冲突}.
我正在考虑像这样创建 API,但我不确定如何创建。
- GET /api/messages/name/{name} <-(或类似的东西)
解决方案:
要让 GET /api/messages/{name} 工作而不与 GET /api/messages/{id} 发生冲突,请将 [=17= 的属性 [HttpGet("{id}", Name="GetMessage")]
更改为 [HttpGet("{id:long}", Name="GetMessage")]
]方法。
要让 GET /api/messages/name/{name} 正常工作,请将 [Route("name/{name}")]
属性添加到 public IEnumerable<Message> GetMessagesByName(string name)
方法。
你可以把参数类型放在路由中,所以你的代码方法应该是这样的:
// GET api/messages/{id}
[HttpGet("{id:long}", Name = "GetMessage")]
public IActionResult GetById(long id)
{
var message = _repository.GetMessage(id);
if (message == null)
{
return NotFound();
}
return new ObjectResult(message);
}
我认为,web api 会忽略路由中的参数类型,如果它们没有显式输入的话,所以在你的例子中它有两条这样的路由:api/messages/{object}
并且当你输入显式类型时,他们是这样的:api/messages/{object}
和 api/messages/{long}
我用 ASP.NET 核心创建了一个简单的 Web API。我有以下 API:
- GET /api/messages - 获取所有消息
- GET /api/messages/{id} - 通过 id 获取消息
- POST /api/messages - 添加一条新消息
- PUT /api/messages/{id} - 更新现有消息
- DELETE /api/messages/{id} - 删除一条消息
现在,我想要另一个 API 按消息所有者的姓名获取所有消息。
我试过的:
我试图创建这个 API,但它不起作用,因为它与 GET /api/messages/{id}:
冲突GET /api/messages/{name} <-(由于冲突 API 而无效)
// GET: api/messages/{name} [HttpGet("{name}")] public IEnumerable<Message> GetMessagesByName(string name) { return _repository.GetMessages().Where(m => m.Owner == name); }
这是我的消息模型Message.cs:
public class Message
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string Owner { get; set; }
public string Text { get; set; }
}
这是我的消息控制器MessagesController.cs:
[Route("api/[controller]")]
public class MessagesController : Controller
{
private readonly IMessageRepository _repository;
public MessagesController(IMessageRepository repository)
{
_repository = repository;
}
// GET: api/messages
[HttpGet]
public IEnumerable<Message> Get()
{
return _repository.GetMessages();
}
// GET api/messages/{id}
[HttpGet("{id}", Name = "GetMessage")]
public IActionResult GetById(long id)
{
var message = _repository.GetMessage(id);
if (message == null)
{
return NotFound();
}
return new ObjectResult(message);
}
// POST api/messages
[HttpPost]
public IActionResult Post([FromBody]Message message)
{
if (message == null)
{
return BadRequest();
}
_repository.AddMessage(message);
return CreatedAtRoute("GetMessage", new { id = message.Id }, message);
}
// PUT api/messages/{id}
[HttpPut("{id}")]
public IActionResult Put(long id, [FromBody]Message message)
{
if (message == null || message.Id != id)
{
return BadRequest();
}
var messageToUpdate = _repository.GetMessage(id);
if (messageToUpdate == null)
{
return NotFound();
}
messageToUpdate.Owner = message.Owner;
messageToUpdate.Text = message.Text;
_repository.UpdateMessage(messageToUpdate);
return new NoContentResult();
}
// DELETE api/messages/{id}
[HttpDelete("{id}")]
public IActionResult Delete(long id)
{
var message = _repository.GetMessage(id);
if (message == null)
{
return NotFound();
}
_repository.RemoveMessage(id);
return new NoContentResult();
}
}
问题:
如何创建一个 API 方法来通过邮件所有者的姓名获取所有邮件?
理想情况下,我希望 API 看起来像 GET /api/messages/{name},但认为这不可能,因为它与 GET /api/messages/{id} 冲突}.
我正在考虑像这样创建 API,但我不确定如何创建。
- GET /api/messages/name/{name} <-(或类似的东西)
解决方案:
要让 GET /api/messages/{name} 工作而不与 GET /api/messages/{id} 发生冲突,请将 [=17= 的属性 [HttpGet("{id}", Name="GetMessage")]
更改为 [HttpGet("{id:long}", Name="GetMessage")]
]方法。
要让 GET /api/messages/name/{name} 正常工作,请将 [Route("name/{name}")]
属性添加到 public IEnumerable<Message> GetMessagesByName(string name)
方法。
你可以把参数类型放在路由中,所以你的代码方法应该是这样的:
// GET api/messages/{id}
[HttpGet("{id:long}", Name = "GetMessage")]
public IActionResult GetById(long id)
{
var message = _repository.GetMessage(id);
if (message == null)
{
return NotFound();
}
return new ObjectResult(message);
}
我认为,web api 会忽略路由中的参数类型,如果它们没有显式输入的话,所以在你的例子中它有两条这样的路由:api/messages/{object}
并且当你输入显式类型时,他们是这样的:api/messages/{object}
和 api/messages/{long}