DEV Community

Aleksander Wons
Aleksander Wons

Posted on

Symfony 7 vs. .NET Core 8 - Routing; part 3

Disclaimer

This is a tutorial or a training course. Please don't expect a walk-through tutorial showing how to use ASP.NET Core. It only compares similarities and differences between Symfony and ASP.NET Core. Symfony is taken as a reference point, so if features are only available in .NET Core, they may never get to this post (unless relevant to the comparison).

This is the continuation of the second post: Symfony 7 vs. .NET Core 8 - Routing; part 2

Generating URLs

Symfony

The generation of URLs is straightforward. We either have access to the request context or not, depending on the context. If we use URL generation from within a service or a controller that extends the AbstractController, we will have access to the request context. Therefore, the absolute URLs will have the correct domain and protocol. If we use it from within a command, we must provide the protocol or define defaults in a configuration. All generated URLs are absolute unless we want only the path.

// Controller
$userProfilePage = $this->generateUrl('user_profile', [
    'username' => $user->getUserIdentifier(),
]);
Enter fullscreen mode Exit fullscreen mode
// Service
$userProfilePage = $this->router->generate('user_profile', [
    'username' => $user->getUserIdentifier(),
]);
Enter fullscreen mode Exit fullscreen mode
// Command
$userProfilePage = $this->urlGenerator->generate('user_profile', [
    'username' => $user->getUserIdentifier(),
]);
Enter fullscreen mode Exit fullscreen mode

In all cases, the generator implements the UrlGeneratorInterface interface.

One important aspect of URL generation is that route conditions are not considered. In the following example, the condition that checks if the post ID is lower than 1000 will not be checked when generating the URL. This contrasts with .NET Core, where even custom conditions will be checked to see if the route matches.

#[Route(
    '/posts/{id}',
    name: 'post_show',
    "params" variable
        condition: "params['id'] < 1000"
    )]
Enter fullscreen mode Exit fullscreen mode

.NET Core

Even though the rules governing the URL-generating process are more complicated than in Symfony, on the surface, everything looks very similar.

We can use the LinkGenerator service directly (not that we need to pass the HttpContext object manually):

public IActionResult Index()
{
    var indexPath = _linkGenerator.GetPathByAction(HttpContext, values: new { id = 17 })!;

    return Content(indexPath);
}
Enter fullscreen mode Exit fullscreen mode

We can use a built-in method of the controller:

public class GadgetController : ControllerBase
{
    public IActionResult Index() =>
        Content(Url.Action("Edit", new { id = 17 })!);
}
Enter fullscreen mode Exit fullscreen mode

In the preceding example, we can generate a URL relative to the current controller by specifying the action. This does not work in Symfony, where we must provide a route name.

We could even provide both the controller and the action:

var subscribePath = _linkGenerator.GetPathByAction("Subscribe", "Home", new { id = 17 })!;
Enter fullscreen mode Exit fullscreen mode

As we can see, the .NET's URL generation seems more sophisticated.

Signing generated URLs

Symfony

Symfony has an interesting feature that allows us to sign a URL.

$url = 'https://example.com/foo/bar?sort=desc';
$signedUrl = $this->uriSigner->sign($url);
Enter fullscreen mode Exit fullscreen mode

We can even define an expiration time:

signedUrl = $this->uriSigner->sign($url, new \DateTimeImmutable('2050-01-01'));
Enter fullscreen mode Exit fullscreen mode

Such URLs can be later checked like this:

$uriSignatureIsValid = $this->uriSigner->check($signedUrl);
Enter fullscreen mode Exit fullscreen mode

or like this:

$uriSignatureIsValid = $this->uriSigner->checkRequest($request);
Enter fullscreen mode Exit fullscreen mode

.NET Core

There is no such thing in .NET Core. The only way to achieve this is by writing some customer code.

What's next?

We will continue controllers. We have already seen a glimpse of how controllers work with regard to routing, but we will dive deeper into that topic.

Thanks for your time!
I'm looking forward to your comments. You can also find me on LinkedIn, X, or Discord.

Top comments (0)