0

Followed by this post on creating culture and adding prefix culture parameter in all url as follows

ASP.NET MVC 5 culture in route and url

I'm working on magazine (Arabic and English) and links for homepage as follows: localhost:1025/Blog/Home //Default Arabic localhost:1025/en/blog/home // for English

I added new action under Controller 'blog' called 'tag' to show posts for specific tag . already added in routeConfig code as this:

routes.MapRoute(
          name: "BlogListTag",
          url: "{controller}/{action}/{Name}/{page}/{pageNo}",
          defaults: new { controller = "Blog", action = "Tag", Name = UrlParameter.Optional, pageNo = UrlParameter.Optional, page = UrlParameter.Optional }

      );

So this must be prefixed by culture constraint parameter as the code applies that:

routes.LowercaseUrls = true;
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        // Call to register your localized and default attribute routes
        routes.MapLocalizedMvcAttributeRoutes(
            urlPrefix: "{culture}/",
             defaults: new { culture = "ar" },
            constraints: new { culture = new CultureConstraint(defaultCulture: "ar", pattern: "[a-z]{2}") }
        );

Now on Home action I'm listing articles links in Partial view So Each article has a couple of links for tag page. I used in partial view this code

@Html.ActionLink(@t.Name,"Tag",new { Name = t.NameEn.AddDashes() },new { title= Resources.Resource.Tag+":"+ @t.Name })

When I browse in arabic i get the link when i inspect in browser as this:

localhost:1025/blog/tag?Name=XYZ //in Arabic

When I switch to home page in english

localhost:1025/en/blog/tag?Name=XYZ //in English

it works fine and it catches the culture and include in links . But I don't want to show links with querystrings

here is the issue , when I replace the code by using Html.RouteLink instead of ActionLink , it follows the route from RouteConfig but doesn't take any prefix culture . so here is the link code line :

@Html.RouteLink(@t.Name, "BlogListTag", 
new { Name = t.NameEn.AddDashes(),action="tag" },
new { title= Resources.Resource.Tag+":"+ @t.Name })
//Note: I included action because it doesn't work without it 

the result link in both arabic and english page

localhost:1025/blog/tag/XYZ //in Arabic

localhost:1025/blog/tag/XYZ //in English 'Note: no culture prefix caught

My final try was to include culture as parameter like this only when culture is En

@Html.RouteLink(@t.Name, "BlogListTag", 
new { Name = t.NameEn.AddDashes(),action="tag",culture="en" },
new { title= Resources.Resource.Tag+":"+ @t.Name })
//Note: I included action because it doesn't work without it
//Note: this is only inside the if statement to check the culture as English

and it results the link in English page like this:

localhost:1025/blog/tag/XYZ?culture=en //in English 'Note: QueryString

All I wanted is to be like these:

localhost:1025/blog/tag/XYZ //in Arabic 'this works already in arabic

localhost:1025/en/blog/tag/XYZ //in English

All I want is that RouteLink to work by catching the prefix culture in arabic and English without any attempt to include culture as parameter and without seeing any query strings in the links

Appreciate your reply

Community
  • 1
  • 1

1 Answers1

0

You have several issues with this setup. You haven't setup a URL to accept culture. There must be some variable in the URL to tell it which culture you wish to view. You also have more than one UrlParameter.Optional, which is not allowed (or the URLs don't build correctly). There can only be one UrlParameter.Optional parameter per route.

A third potential issue is that you haven't constrained the route in any way, so it won't work if you have additional routes in your website. I am showing an example here of using literal segments, but do note there are many ways to constrain a route and route ordering is extremely important because the first match always wins.

// Localized route
routes.MapRoute(
      name: "BlogListTagWithPageLocalized",
      url: "{culture}/Blog/{action}/{Name}/{page}/{pageNo}",
      defaults: new { controller = "Blog", pageNo = UrlParameter.Optional },
      constraints: new { culture = new CultureConstraint(defaultCulture: "ar", pattern: "[a-z]{2}") }
);  

// Default culture route
routes.MapRoute(
      name: "BlogListTagWithPage",
      url: "Blog/{action}/{Name}/{page}/{pageNo}",
      defaults: new { culture = "ar", controller = "Blog", pageNo = UrlParameter.Optional }
);

// Localized route
routes.MapRoute(
      name: "BlogListTagLocalized",
      url: "{culture}/Blog/{action}/{Name}",
      defaults: new { controller = "Blog", Name = UrlParameter.Optional },
      constraints: new { culture = new CultureConstraint(defaultCulture: "ar", pattern: "[a-z]{2}") }
);

// Default culture route
routes.MapRoute(
      name: "BlogListTag",
      url: "Blog/{action}/{Name}",
      defaults: new { culture = "ar", controller = "Blog", Name = UrlParameter.Optional }
);

Also, if you setup multiple routes for a single page like this (which you need to do for localization), you can't use RouteLink with a name. You must exclude the route name or alternatively use ActionLink to build the URL so it is possible to match either the localized route or the non-localized route.

@Html.RouteLink(@t.Name, /*"BlogListTag", <-- Don't include this */
    new { Name = t.NameEn.AddDashes(),action="tag" },
    new { title= Resources.Resource.Tag+":"+ @t.Name })

Do note that if you want your URLs translated into different languages, the solution you linked to won't work (at least not without some modifications). However, there is an open source project RouteLocalization that might work for you (I haven't tried it).

The call to routes.MapLocalizedMvcAttributeRoutes() is only necessary if you are using attribute routing and you want your attribute routes localized.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212