Symfony 7 vs. .NET Core 8 - Routing; part 3
Tags: symfony, dotnetcore, routing
Published: 2024-06-09 13:25:30

## 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](https://dev.to/awons/symfony-7-vs-net-core-8-routing-part-2-1pdn)

## 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.

```php
// Controller
$userProfilePage = $this->generateUrl('user_profile', [
    'username' => $user->getUserIdentifier(),
]);
```

```php
// Service
$userProfilePage = $this->router->generate('user_profile', [
    'username' => $user->getUserIdentifier(),
]);
```

```php
// Command
$userProfilePage = $this->urlGenerator->generate('user_profile', [
    'username' => $user->getUserIdentifier(),
]);
```

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.

```php
#[Route(
    '/posts/{id}',
    name: 'post_show',
    "params" variable
        condition: "params['id'] < 1000"
    )]
```

### .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):

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

    return Content(indexPath);
}
```

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

```c#
public class GadgetController : ControllerBase
{
    public IActionResult Index() =>
        Content(Url.Action("Edit", new { id = 17 })!);
}
```

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:

```c#
var subscribePath = _linkGenerator.GetPathByAction("Subscribe", "Home", new { id = 17 })!;
```

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.

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

We can even define an expiration time:

```php
signedUrl = $this->uriSigner->sign($url, new \DateTimeImmutable('2050-01-01'));
```

Such URLs can be later checked like this:

```php
$uriSignatureIsValid = $this->uriSigner->check($signedUrl);
```

or like this:

```php
$uriSignatureIsValid = $this->uriSigner->checkRequest($request);
```

### .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](https://www.linkedin.com/in/aleksanderwons/), [X](https://x.com/AleksanderWons), or [Discord](https://discordapp.com/users/601775386233405470).