1

I'm trying to make my url seo friendly. I need to make url with this structure

www.domainname.com/article123.

And with this route

routes.MapRoute(
        "articlename", // Route name
        "aaaa/{articleID}", // URL with parameters
         new {action="DetailsByName",controller="Article"},
        new string[] { "bssnew.Controllers" } // Parameter defaults);

It doesn't work. MY route link looks like this

 @Html.RouteLink("aaa ","articlename", new {articleID="CentralPark",},new { @class = "item-link" })

But when I add controller and action in route it works

 routes.MapRoute(
        "articlename", // Route name
        "aaaa/{controller}/{action}/{articleID}", // URL with parameters
         new {action="DetailsByName",controller="Article"},
        new string[] { "bssnew.Controllers" } // Parameter defaults);
James
  • 80,725
  • 18
  • 167
  • 237
VirtuoZ
  • 163
  • 2
  • 5
  • 14

5 Answers5

2

If you need an ID only specific route, the following should work

routes.MapRoute(
    "articlename", // Route name
    "{articleID}", // URL with parameters
    new { action="DetailsByName",controller="Article" }, // parameter defaults 
    new[] { "bssnew.Controllers" } // controller namespaces
);

Assuming you have a controller which looks like

namespace bssnew.Controllers
{
    public class Article : Controller
    {
        public ActionResult DetailsByName(string articleID)
        {
            ...
        }
    }
}
James
  • 80,725
  • 18
  • 167
  • 237
  • But where should I put it over or under the default route, because when I put over default route, that routes for other routes, and if I put it under default It doesn't work, even If I specified route name in route link – VirtuoZ Jun 30 '13 at 09:48
  • @James, I don't want to be nitpicker but the comment line `// Parameter defaults` should actually go on a previous line. The last line is namespaces registration. :-) – Huske Jun 30 '13 at 09:48
  • @user1278119, Put it above the default route configuration, however, because James explicitly named the route, you should be able to call `@Html.RouteLink` action method to generate James' route regardless of the position. The route will be searched by name and not in a sequential order. – Huske Jun 30 '13 at 09:51
  • 1
    @HuseinRoncevic I just copied & pasted the OP's definition hence it looked like it was on the next line :) Updated so it's clear. You need to place this route *before* the default one so it get's processed first, then if it doesn't match it will fall back to the default. – James Jun 30 '13 at 09:52
  • And How should I register namespace? And If I explicit call it by route name In route link, why it works only when it is over default one? It seems like it doesn;t function name calling?? – VirtuoZ Jun 30 '13 at 09:54
  • Are you calling `Html.RouteLink("Link name", "articlename", new {controller = "Article", action = "DetailsByName", articleId = yourArticleId})` This should generate a link to a named route. – Huske Jun 30 '13 at 10:03
  • @user1278119 see update. It all depends on your site, it could be a number of factors, however, if you setup a default site and put the above route in it should work, I assume you have a `DetailsByName` action in the `Article` controller which expects an parameter named `articleID`? – James Jun 30 '13 at 10:05
  • It doesn't work for me, when I create route link like that and route put under default one it doesn't work – VirtuoZ Jun 30 '13 at 10:22
  • I know checked again but it seems like he is not get good controller and action from @html.routelink, because when I put it over default route it works when I put it under it doesn't work 404 error.But in both case he is reaching good route(I know that by prefix). Any help please I'm really desperate. – VirtuoZ Jun 30 '13 at 11:04
  • @user1278119 what does the generated URL look like? Is it correct but just not routing to the correct controller/action? – James Jun 30 '13 at 11:09
1

I was responding to you via James' comment. One problem could be is that you route looks like this:

routes.MapRoute(
    "articlename", // Route name
    "{articleID}", // URL with parameters
    new { action="DetailsByName",controller="Article" }, // parameter defaults 
    new[] { "bssnew.Controllers" } // controller namespaces
);

When a route is generated (not using named route) your link should look like: http://www.example.com/Article/DetailsByName?articleId=123 where 123 is your article ID.

THe condition for the above link to be generated like this is to place it before "Default" route. Also, check if the namespace registration is causing a problem for you. Try first removing the namespace if it is not needed.

Here is a quick sample which I created based on your question. The result was that even after putting named route below the default one I managed to generate a proper route. Here is the contents of the RouteConfig.cs:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
            name: "CalculationRoute", // Note that it is below the default route
            url: "{controller}/{action}/{x}/{y}", // using both controller and action
            defaults: new { controller = "Home", action = "Calculate"}
        );
    }
}

In my HomeController I added the following action:

public ActionResult Calculate(int x, int y)
{
    return Content(String.Format("x:{0} + y:{1} = {2}", x, y, (x + y)));
}

Now, here is the contents of the Index view

<table>
    <thead>
        <tr>
            <th>Method used</th>
            <th>Result</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>@@Html.ActionLink("Sample link", "Calculate", "Home", new {x = 1, y = 2})</td>
            <td>@Html.ActionLink("Sample link", "Calculate", "Home", new {x = 1, y = 2})</td>
        </tr>
        <tr>
            <td>@@Html.RouteLink("Sample link", new {controller = "Home", action = "Calculate", x = 1, y = 2}, null)</td>
            <td>@Html.RouteLink("Sample link", new {controller = "Home", action = "Calculate", x = 1, y = 2}, null)</td>
        </tr>
        <tr>
            <td>@@Html.RouteLink("Sample link", "CalculationRoute", new {controller = "Home", action = "Calculate", x = 1, y = 2})</td>
            <td>@Html.RouteLink("Sample link", "CalculationRoute", new {controller = "Home", action = "Calculate", x = 1, y = 2})</td>
        </tr>
        <tr>
            <td>@@Url.RouteUrl(new {controller = "Home", action = "Calculate", x = 1, y = 2})</td>
            <td>@Url.RouteUrl(new {controller = "Home", action = "Calculate", x = 1, y = 2})</td>
        </tr>
        <tr>
            <td>@@Url.RouteUrl("CalculationRoute", new {controller = "Home", action = "Calculate", x = 1, y = 2})</td>
            <td>@Url.RouteUrl("CalculationRoute", new {controller = "Home", action = "Calculate", x = 1, y = 2})</td>
        </tr>
    </tbody>
</table>

The above code generates what is expected. For example (BTW I am using some dummy link as SO does not allow localhost to be used):

If I remove {controller}/{action} from my calculation route, it would generate the link (with named routes) as http://www.example.com/1/2.

So to summarize, if you plan to use named route to generate SEO friendly URLs, configure your route with {controller}/{action}/{articleId}. If it is not too important then generate your routes with RouteLink but do not specify route name.

UPDATE: If you don't plan to use {controller}/{action} in your route and only {articleId}, you should place your route before the Default and do not use named route when generating links. In my example above that would look like:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "", // Note that it is below the default route
            url: "{x}/{y}", // using both controller and action
            defaults: new { controller = "Home", action = "Calculate"}
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Now when you generate a link using @Html.RouteLink you would do it this way:

@Html.RouteLink("My Link", new {controller = "Home", action = "Calculate", x = 1, y = 2 })

and this will generate something like:

http://www.VirtuoZ.com/Home/Calculate?x=1&y=2

UPDATE 2: Regarding you request about other routes, you can always rely on Default route to generate information, however, you cannot have generated routes like you state in a comment:

http://www.example.com/abc for articles and http://www.example.com/def for products

The problem is that the routes are the same and routing system will pick the first route that can serve your request. It can happen that both requests are served by the same route. You need to distinguish between the two routes. So, for your articles use your new route that you defined and for other things where one parameter is expected you would use the Default route.

Huske
  • 9,186
  • 2
  • 36
  • 53
  • Thanks a lot for Your effort but in Your example, when I remove from secound route action and controller from routes.MapRoute( name: "CalculationRoute", // Note that it is below the default route url: "{x}/{y}", // using both controller and action defaults: new { controller = "Home", action = "Calculate" } ); like this and when i click on third link this @Html.RouteLink("Sample link", "CalculationRoute", new {controller = "Home", action = "Calculate", x = 1, y = 2}) I don't get error 404 – VirtuoZ Jun 30 '13 at 11:29
  • Try removing the namespace configuration from your route just to see if it works. Also, could you update your question to show how you are generating the links and the result of one link being generated? – Huske Jun 30 '13 at 12:02
  • but in Your example there is no namespaces, in Your example when I remove {controller}/{action} from route I'm getting 404 error, Iremoved it from secound route – VirtuoZ Jun 30 '13 at 12:17
  • If You can just upadte your example with route withour controller and action that redirects to proper action? That is all that I need. Thanks in advance – VirtuoZ Jun 30 '13 at 12:22
  • but I need url www.something.com/abc ? and to call it by name because I'll have simillar action for other objects – VirtuoZ Jun 30 '13 at 13:57
  • I am not sure what do you mean. Could you elaborate? – Huske Jun 30 '13 at 15:02
  • I need to produce url www.something.com/abc to select article with name abc, but I also need url www.something.com/def to select product with name def. can You post that example, that would solve my problemm I currently deserate :) So I need routing mechanism that will have one default route and 2 or 3 others that will recieve only one parameter ? – VirtuoZ Jun 30 '13 at 15:22
  • But is there possibility to create special route for for artical and special on e for pruduct and to call them by name from route link? – VirtuoZ Jul 01 '13 at 06:23
  • Yes it. You can multiple routes, give them any name and use them as such when you need to generate a link. – Huske Jul 01 '13 at 07:43
  • But that doesn't work when I try to make that. I just need example with 2 routes and 2 html.routelink that acssess those routes, and those routes should create url www.something.com/abc. – VirtuoZ Jul 01 '13 at 08:07
  • @VirtuoZ, I think you need to get the hang of routes. Have a look at my blog. There is a three part article on routing http://mvcdeveloper.wordpress.com – Huske Jul 01 '13 at 10:17
0

[Named Routes with ASP.NET MVC][1]

http://dotnet.dzone.com/articles/named-routes-aspnet-mvc

ibrahim ozboluk
  • 421
  • 5
  • 10
0

Try this:

routes.MapRoute(
"articlename", // Route name
"", // URL with parameters
new { action="DetailsByName",controller="Article" id="articleID"}, // parameter defaults 
new[] { "bssnew.Controllers" } // controller namespaces
);
CLoren
  • 298
  • 2
  • 5
  • 10
0

I got it working like this. I think the implementation is a little cleaner and easier to understand this way (using parameter names and no namespaces). The route code appears above the default route like so:

routes.MapRoute(
  name: "BlogPost",
  url: "{postId}",
  defaults: new { action = "Index", controller = "Blog" });

And the controller looks like this:

public class BlogController : Controller
{
    public ActionResult Index(string postId)
    {
        ...
    }
}
craftworkgames
  • 9,437
  • 4
  • 41
  • 52