Make link creation typesafe using expressions
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
Currently there is no refactor-safe way to create links to actions or pages, it has to be done using magic strings that the compiler doesn't understand. For example, I have an `AboutController` with an `Index` action, then I can create a link using `Url.Action("Index", "About")`. But if I rename the action or controller then this will lead to a runtime exception, not a compile time exception. I could use `Url.Action(nameof(AboutController.Index), "About")`, but using `nameof()` only works for the action, not the controller, since it expects me to specify the name of the controller without the Controller suffix. This is further a problem for actions that take query parameters, where they are specified using an anonymous class with no type safety at all. That is, there is no verification that `Url.Action("Index", "Search", new {name, title, query})` will create a link that sends the correct query parameters to the `SearchController.Index` method.
My proposal is therefore a method that takes an expression, so that it can look like this:
```cs
//Given this controller...
public class AboutController
{
public IActionResult Index()
{
//...
}
public IActionResult Search(string name, string title, string query)
{
//...
}
[HttpPost]
public IActionResult Submit(string id, [FromBody] Model input)
{
//...
}
}
//Get url to action in another controller
Url.Action(c => c.Index()); // => /About/Index
//Inside a controller there would be an overload that is not generic, using the current controller as the basis
Url.Action(c => c.Index()); // => /About/Index
//Actions that have query parameters would also work
Url.Action(c => c.Search(name, title, query)); // => /About/Search?name=test&title=blabla&query=*
//For actions that work with Post or Put and take in a body, the body is ignored so we can pass in null values for the Post parameters
Url.Action(c => c.Submit(id, null)); // =>/About/Submit/1234
```
The `UrlHelper.Action` method would be defined as `public static string Action(this IUrlHelper helper, Expression> expression)` or something similar, and based on the expression passed into it enough information should be able to be gathered to create a url.
Contributor guide
Assessment
This issue has not been assessed yet.