URL.Action does not generate URL correctly in ASP.NET Core 7 MVC web application

253 views Asked by At

I have a web application divided into some modules. One of those modules is called Authenticate (which contains all authentication implementations of the whole application).

I have a login page which is accessed using this URL:

https://localhost:44375/Authenticate/Security/Login

Where Authenticate is the name of the module, Security is the controller and Login is the action.

Inside the corresponding view, Login.cshtml, I have this markup:

@Url.Action("Login", new { ReturnUrl = ViewBag.ReturnUrl })'

That code generates the URL this way:

/Authenticate/Authenticate/Security/Login?ReturnUrl=%2F

If I add the controller in the Url.Action code, this way:

@Url.Action("Login", "Security", new { ReturnUrl = ViewBag.ReturnUrl })

the same happens.

How can I solve it? For some reason, the module name is duplicated in the actual URL that is created.

Thanks

Jaime

1

There are 1 answers

0
jstuardo On BEST ANSWER

Finally, I created the following extension method:

    public static string ModuleAction(this IUrlHelper urlHelper, string action, string controller, string module, object? values = null)
    {
        ArgumentNullException.ThrowIfNull(urlHelper);

        var oldPathBase = urlHelper.ActionContext.HttpContext.Request.PathBase;
        urlHelper.ActionContext.HttpContext.Request.PathBase = oldPathBase.Value == $"/{module}" ? new PathString() : new PathString($"/{module}");
        var url = urlHelper.Action(action, controller, values) ?? string.Empty;
        urlHelper.ActionContext.HttpContext.Request.PathBase = oldPathBase;
        return url;
    }

Since Action method uses PathBase to get the first part of the link, I am changing it momentarily to use the path corresponding to the module.

What I am not sure, why I needed to use the oldPathBase.Value == $"/{module}" check. If I am browsing a page in the same module I am generating the URL to, Action method already includes the module path prepended.

Consider, for example, the logout link, present in every page in the site, should be:

https://server/authenticate/security/logout

That URL is generated by a call to Url.ModuleAction("Logout", "Security", "Authenticate") in the view.

If I didnĀ“t use that check, the generated URL was https://server/authenticate/authenticate/security/logout

If someone can explain why that happens, please comment.

You can see a sample project at https://github.com/jaimestuardo/MultiAssemblyWeb.