title: How to create ASP.NET Core Web API controller method with similar but different parameter
body: <p>I created a simple Web API with ASP.NET Core. I have the following API:</p>
  
  <ul>
  <li>GET /api/messages - get all messages </li>
  <li>GET /api/messages/{id} - get a message by id </li>
  <li>POST /api/messages - add a new message </li>
  <li>PUT /api/messages/{id} - update an existing message </li>
  <li>DELETE /api/messages/{id} - delete a message</li>
  </ul>
  
  <p>Now, I want another API to get all messages by message owner's name.</p>
  
  <p><strong>What I tried</strong>:</p>
  
  <p>I tried to create this API, but it doesn't work because it conflicts with GET /api/messages/{id}:</p>
  
  <ul>
  <li><p>GET /api/messages/{name} &lt;- (doesn't work due to conflicting API)</p>
  
  <pre><code>// GET: api/messages/{name}
  [HttpGet("{name}")]
  public IEnumerable&lt;Message&gt; GetMessagesByName(string name)
  {
      return _repository.GetMessages().Where(m =&gt; m.Owner == name);
  }
  </code></pre></li>
  </ul>
  
  <p>Here is my Message model <strong>Message.cs</strong>:</p>
  
  <pre><code>public class Message
  {
      [Key]
      [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
      public long Id { get; set; }
      public string Owner { get; set; }
      public string Text { get; set; }
  }
  </code></pre>
  
  <p>Here is my Messages controller <strong>MessagesController.cs</strong>: </p>
  
  <pre><code>[Route("api/[controller]")]
  public class MessagesController : Controller
  {
      private readonly IMessageRepository _repository;
  
      public MessagesController(IMessageRepository repository)
      {
          _repository = repository;
      }
  
      // GET: api/messages
      [HttpGet]
      public IEnumerable&lt;Message&gt; 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();
      }
  }
  </code></pre>
  
  <p><strong>Question</strong>:</p>
  
  <p>How can I create an API method to get all messages by message owner's name?</p>
  
  <p>Ideally, I would like the API to look like GET /api/messages/{name}, but don't think its possible since it conflicts with GET /api/messages/{id}.</p>
  
  <p>I'm thinking of creating the API like this, but I'm not sure how.</p>
  
  <ul>
  <li>GET /api/messages/name/{name} &lt;- (or something along that line)</li>
  </ul>
  
  <p><strong>Solution</strong>:</p>
  
  <p>To have GET /api/messages/{name} working without conflicting with GET /api/messages/{id}, change attribute <code>[HttpGet("{id}", Name="GetMessage")]</code> to <code>[HttpGet("{id:long}", Name="GetMessage")]</code> for <code>public IActionResult GetById(long id)</code> method.</p>
  
  <p>To also have GET /api/messages/name/{name} working, add <code>[Route("name/{name}")]</code> attribute to <code>public IEnumerable&lt;Message&gt; GetMessagesByName(string name)</code> method.</p>