0

I'm experimenting with a different REST API design. I created a new .Net 5 app with one model and two controllers

public sealed record Todo(string Title, string OwnedBy, bool IsDone = false);

public sealed class TodoQueriesController : ControllerBase
{
    [HttpGet("my-todo-by-title/{title}")]
    [ActionName(nameof(GetTodoFromAuthenticatedUserByTitle))]
    public ActionResult<Todo> GetTodoFromAuthenticatedUserByTitle([FromRoute] string title)
    {
        string authenticatedUsername = "foo";
        
        return Ok(new Todo(title, authenticatedUsername));
    }
}

public sealed class TodoCommandsController : ControllerBase
{
    [HttpPost("assign-todo-to-me")]
    public ActionResult<Todo> AssignTodoToAuthenticatedUser([FromBody] string title)
    {
        string authenticatedUsername = "foo";
        
        return CreatedAtAction("???", new { title }, new Todo(title, authenticatedUsername));
    }
}

Currently I don't know what to pass in as an action name for the CreatedAtAction (to replace "???")

I tried

  • nameof(TodoQueriesController.GetTodoFromAuthenticatedUserByTitle)
  • "GetTodoFromAuthenticatedUserByTitle"
  • "my-todo-by-title"
  • $"my-todo-by-title/{title}"

but unfortunately I always got a 500 with

System.InvalidOperationException: No route matches the supplied values.

How can I reference the endpoint action from another controller?

Question3r
  • 2,166
  • 19
  • 100
  • 200

1 Answers1

1

You can use the CreatedAtAction overload with the controllerName parameter.

CreatedAtActionResult CreatedAtAction (string actionName, string controllerName, object routeValues, object value)

Check out the Docs here

René
  • 100
  • 1
  • 8
  • You mean like so? `CreatedAtAction(nameof(TodoQueriesController.GetTodoFromAuthenticatedUserByTitle), nameof(TodoQueriesController), new { title }, new Todo(title, authenticatedUsername));` That didn't work neither – Question3r Aug 18 '21 at 12:23
  • I just now realize that you are using the [FromRoute] attribute. This doesn't work with CreatedAtAction because there is no way to pass the title from route. I think you will need to use CreatedAtRoute in this case and append the title value to the route string like so: CreatedAtRoute(nameof(TodoQueriesController.GetTodoFromAuthenticatedUserByTitle) + title, nameof(TodoQueriesController), new Todo(title, authenticatedUsername)); – René Aug 18 '21 at 12:46
  • sorry, this method provides no overload for the controller name. I also tried `CreatedAtRoute(nameof(TodoQueriesController.GetTodoFromAuthenticatedUserByTitle), new Todo(title, authenticatedUsername));` and `CreatedAtRoute(nameof(TodoQueriesController.GetTodoFromAuthenticatedUserByTitle) + title, new Todo(title, authenticatedUsername));` – Question3r Aug 18 '21 at 14:33
  • you can specify the controller in the route parameters. see [here](https://stackoverflow.com/questions/23417559/createdatroute-routing-to-different-controller) – René Aug 18 '21 at 16:22