aspnetcore: Url.Action doesn't respect constraints from IApplicationModelConvention

Describe the bug

I implemented localized routes using a ApplicationModelConvention. This works fine as long as I type the urls directly in the browser.

So, for example, german routes are only allowed in german culture. and routes from other languages are returning a 404. Exactly as expected.

But when I use Url.Action it doesn’t respect the constraints. so for example if i’m on the english domain i get russian links (depending on the order they are inserted)

What am I doing wrong?

Startup Code:

 services.AddMvc(o =>
            {
                o.Conventions.Insert(0, new LocalizedRouteConvention());
            })

Convention

public class LocalizedRouteConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            foreach (var action in controller.Actions)
            {
                var attributes = action.Attributes.OfType<RouteAttribute>().ToArray();
                if (!attributes.Any()) return;

                foreach (var attribute in attributes)
                {
                    SelectorModel defaultSelector = action.Selectors.First();

                    foreach (var localizedVersion in GetLocalized(attribute.Template))
                    {
                        if (!action.Selectors.Any(s => s.AttributeRouteModel.Template == localizedVersion.Template))
                        {
                            action.Selectors.Insert(0, new SelectorModel(defaultSelector)
                            {
                                AttributeRouteModel = localizedVersion,
                                ActionConstraints =
                                {
                                    new CultureActionConstraint { Culture = ((LocalizedRouteAttribute) localizedVersion.Attribute).Culture }
                                }
                            });
                        }
                    }
                }
            }
        }
    }
}

And here the constraint

    public class CultureActionConstraint : IActionConstraint
    {
        public string Culture { get; set; }

        public int Order => 0;

        public bool Accept(ActionConstraintContext context)
        {
            return CultureInfo.CurrentCulture.TwoLetterISOLanguageName == Culture;
        }
    }

Expected behavior

Url.Action should also only use the routes that are allowed.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 23 (18 by maintainers)

Most upvoted comments

@cypressious @BoasE let me try my last attempt to make workaround to your issue, hope to reply ASAP

To be precise, we want

http://your-domain.com/user for en culture http://your-domain.de/benutzer for de culture

Thanks guys for reproducing the issue, I will try to investigate on this soon