0

This is probably stupid, but I can't seem to figure it out. I'm using Html.ActionLink to create links between master and child pages: Employees -> Employee.

I just noticed that the URL it's rendering is not "shaped" as the route it's supposed to match. For example the URL being generated is /Employee?EmployeeId=? when it's supposed to be /Employees/{EmployeeId}.

Am I missing something that's supposed to make it return that kind of a url? I was hand writing all the links up until 2 weeks ago when I switched to Html.ActionLink and I could have sworn it was working properly, but now I see this pattern everywhere on my app and I don't like it...

Url.Action and Html.RouteLink create the same URL as well.

Help would be appreciated.

UPDATE for @Darin

Here's how the route is registered:

Routes.MapRoute("QbNn7GFjJZBzYED7", Settings.EmployeeRoute, new {
    action = "Employee"
}, new {
    controller = new ControllerConstraint(Settings.AdministrationController),
    group = new GroupConstraint(Settings.CorporateGroup),
    EmployeeId = @"\d+"
});

Settings.EmployeeRoute = "{controller}/{group}/Employees/{EmployeeId}";
Settings.AdministrationController = "Administration";
Settings.CorporateGroup = "Corporate";

And before you ask why the route name is QbNn7GFjJZBzYED7, it's because I got tired of giving the routes names and because I never refer to the routes by their name, so I just started generating random strings to fill in the void.

UPDATE 2

The two constraints were essentially the same with different names. Thus, I merged it into one and here's what it looks like:

internal class NameConstraint : IRouteConstraint {
    private readonly string[] Names = new string[0];

    public NameConstraint(
        string Name) {
        this.Names = new string[1] {
            Name.ToLower()
        };
    }

    public NameConstraint(
        string[] Names) {
        this.Names = Names.Select(
            n =>
                (n.ToLower())).ToArray();
    }

    public bool Match(
        HttpContextBase HttpContextBase,
        Route Route,
        string Paramater,
        RouteValueDictionary RouteValueDictionary,
        RouteDirection RouteDirection) {
        string Param = ((string)RouteValueDictionary[Paramater]).ToLower();

        return this.Names.Contains(Param);
    }
}

Now, between this update and the previous one, the routes fixed themselves. The only change that happened was taking ControllerConstraint and GroupConstraint and merging them into NameConstraint and the subsequent rebuild.

How it decided to fix itself, I don't know, but it did. I don't think it was the merger of the constraints, and I doubt it was the rebuild.

Now both of these are generating the right routes:

Html.ActionLink(Employee.Name, "Employee", new { EmployeeId = Employee.EmployeeId })
Html.ActionLink(Employee.Name, "Employee", "Administration", new { group = "Corporate", EmployeeId = Employee.EmployeeId }, null)

In the end I'm not sure what the actual fix was...

1 Answer 1

1

If your route looks like this: {controller}/{group}/Employees/{EmployeeId}

routes.MapRoute(
    "CustomRoute",
    "{controller}/{group}/Employees/{EmployeeId}",
    new { 
        controller = "Foo", 
        action = "Bar", 
        EmployeeId = UrlParameter.Optional 
    }
);

in order to generate an action link matching this route you need this:

<%= Html.ActionLink(
    "some text", // link text
    "Bar", // action
    "Foo", // controller
    new { group = "123", EmployeeId = "456" }, // route values
    null // html attributes
) %>

Things to note:

  • Your route definition doesn't contain an {action} placeholder meaning that you need to specify the action exactly as the default value in your route.
  • The group parameter should be specified. It cannot be optional because it is not at the end of the route
Sign up to request clarification or add additional context in comments.

4 Comments

for a moment I had my hopes up, but sadly, it didn't work. Here's how I'm writing the helper: Html.ActionLink(Employee.Name, "Employee", "Administration", new { group = "Corporate", EmployeeId = Employee.EmployeeId }, null); and here's what it's producing: /Administration/Corporate/Employee?EmployeeId=8. I'm debating hand writing the routes (again) now that the helper doesn't seem to be working right..
How does your route look like? Is Employee the default action in your route definition? Look in my example. The default action in my route definition is Bar and that's the same that I am using in my ActionLink helper.
@Alex, what are those constraints you are having over there? Start by something simple as my example. Make sure that it works. Then gradually add complexity and constraints. This way you will isolate the problem and know why does your custom route doesn't match. Try removing ControllerConstraint and GroupConstraint from your route definition.
it seems to have been fixed on its' own. Sounds crazy, but it's what happened. Look at my second update above for my explanation. Anyway, thanks for the assistance!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.