MVC Custom Routing and Localization - model-view-controller

Okay guys, so I've been stuck for at least 2 days, with googling and checking out all other stack articles I could find.
I just want to check to see if the first parameter in my route is a valid culture name, and if it isn't modify the url/route before execution to include a culture value.
Is that so hard?! I don't think it should be.
I could just modify things in a basecontroller class, from which all other controllers inherit, and check there and then modify all route data and send it on its way. The problem lies with some other custom routes I have.
Okay, so here's the problem with my code, and why I think it would be easiest to do before execution of any controllers.
routes.MapRoute(
"Localization",
"{lang}/{controller}/{action}",
new { lang="en-US",controller="Home",action="Index"}
);
routes.MapRoute(
"Solutions",
"{lang}/Solutions/{controller}/{action}",
new { lang="en-US", controller = "WhatWeDo", action = "Index"}
);
routes.MapRoute(
"Default", // Route name
"{lang}/{controller}/{action}/{id}", // URL with parameters
new { lang = "en-US", controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
So, if I try to modify things, I run into this nasty /solutions/ custom route for certain solutions, and for other answers it requires a custom redirect (Yielding a permanently moved error), and checking to see if certain parameters are null.
Is there any way to extract the route data and modify my route/url in the global.asax file? It would be easiest there, and I really would like to just plop it in so that it's always there, and I can just route normally.
I'm probably not making a whole lot of sense, but I'm a bit frustrated. Any suggestions?

I am not totally sure about what you are trying to achieve, is it to "enforce" language in routes?
You could try writing your own RouteHandler to handle things?
I wrote about something similar on my blog.

Related

Codeigniter - custom routes

Lets say I have a controller 'standard' with an action 'main'.
If I go to www.myapp.com/standard/main it will invoke the main action in the standard controller.
Now if I want to change the URL I go into the routes.php and set sth like the following:
$route['welcome'] = "standard/main";
Now I can visit www.myapp.com/welcome and it will invoke the same action.
However it is still possible to visit www.myapp.com/standard/main. I now have two routes which lead to the same controller action.
Is this the usual way or should I somehow disable the now unwanted www.myapp.com/standard/main route? If so, how would I do that?
Thanks in advance.
That is completely for you to decide the default behavior. If you decide to disable the original url, you can write something like
$route['standard/main'] = 'standard/404';
Or any custom location, it depends on your project and how you wish it should look like, for example you can 'block' any method from being accessed directly:
$route['standard/(:any)'] = 'standard/404';
But bear in mind, if you route like you did $route['welcome'] = "standard/main";, then you should always remember that the function $this->uri->segment(n) will show different values, for example if I will go to url yoursite.com/welcome/123, the value of $this->uri->segment(2) will be 123, but if I visit the original URL yoursite.com/standard/main/123, it's value will change to main.
Bear that in mind and decide for yourself!
Assuming that this is a common structure you'll be using, for each action, you can check the segment's in the URL and then redirect appropriately. In the case of going from standard/main to welcome, you would have the following:
class Standard extends CI_Controller {
public function main() {
if($this->uri->segment(1) == 'standard') {
redirect('welcome', 'location', '301');
}
}
}
This would then check the first segment in the URL and if it sees that you've come to this URL, redirect you to the appropriate route. This can then be applied to each action you want to do the same thing for. Supplying a 301 signifies a permanent redirect.
Update
Just found a similar (the same?) question: Only allow URL's specified in routes to be seen in Codeigniter

URL rewriting in MVC3

I am working on a project for a local college using MVC3. I have came across a requirement at which I am stuck and can't find any wayout.
Let suppose my URL is www.abc.com
The requirement is that if we type teacher name after the URL we get the detailed view of the teacher, like:
www.abc.com/john
www.abc.com/smith
I asked for option like www.abc.com/teacher=john but it has been rejected.
Is this something relevant to URL rewriting or some other wayout, as there can be many teachers in database so I can't make methods in controllers for every teacher.
Can anyone please guide me for this scenario?
Kind Regards
MVC does this natively.
Just create a route for it:
routes.MapRoute(
"Teacher route",
"/{teacher}",
new { controller = "SomeController", action = "SomeAction" }
)
Note that this will conflict with any other /Whatever URLs (eg, /About); to avoid that, you can use my MapDefaultController() extension to map a route for a specific controller before this one.

Dynamically create sitemap and route it to the root level

I am trying to dynamically create a sitemap for my site and I wan't it to be (I believe it is necessary to have it) located at the root level, ie. Domain.com/sitemap.xml
So far I have an action result in the home controller like this:
public ActionResult SiteMap()
{
...
return this.Content(xml, "text/xml");
}
This works fine for creating the file but it is located at Domain.com/Home/Sitemap and my understanding is the the sitemap is supposed to be located at the root level. Is there a way to rewrite the url or add a new route for it in the Global.asax file? By default the Global.asax file contains this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
So it seems like this may be the place to add something like a check if the requested route is Sitemap.xml and just redirect it to Home/sitemap (or just serve the sitemap right there). I'm not sure how to do this, if it is possible, as I have never messed around with the RegisterRoutes section.
Another problem that may arise would be the extension .xml, I would think that IIS would think this is a file on the drive and ignore the route all together.
Am I going down the correct path, or is there a better way to do this? Or is it not possible and I have to just physically create the file?
Edit (Solved)
I just occurred to me that I have been thinking about this the wrong way. All I would have to do is have a method to create/update a sitemap file and save it to /sitemap.xml periodicity or every time a page is added. I can't believe this wasn't obvious to me.
You could add a route:
routes.MapRoute(
"sitemap",
"sitemap.xml",
new { controller = "Home", action = "SiteMap" }
);
and make sure that you put this route before your default route.
This might be slightly off topic, (but in the same breath, kind of close... I think) Have a look at MVCSitemapProvider.
It's simple enough to use in a project, I started using it lately and it works like a charm. I can add some code samples if you do end up wanting to go this route?

localized routes solution

I built a french/english app and I would like to use the same controller/view for both language but to have a different route that is map to the current language. Let say I have website.com/Account/Register that return to my Account controller and Register action, I would love to have a route that is website.com/Comptes/Inscription. I know that I can add a custom route in the RegisterRoute section like so :
routes.MapRoute(
"AccountFr", // Route name
"comptes/inscription", // URL with parameters
new { controller = "Account", action = "Register" } // Parameter defaults
);
But it will need a lot of [boring] code to write all the possibles routes and also, I think it won't work when I will use T4MVC as #Url.Action(MVC.Account.Register()) will return /Account/Register no mater if I'm in french or in english.
Anyone as suggestions/ideas for this problem?
Thanks!
EDIT
Since it does not seem to have a good solution using T4MVC does anyone have an other good solution?
Unfortunately, this won't easily work with T4MVC. The root of the problem is that when going through T4MVC, you can't pick a specific route. Instead, the route gets selected based on the Controller, action and parameters.

how to create Codeigniter route that doesn't override the other controller routes?

I've got a lot controller in my Codeigniter apps, ex: Signup, Profile, Main, etc..
Now I want to build "User" controller.
what I want:
if people goes to url: example.com/signup, I want use default route to "Signup" Controller
if people goes to url: example.com/bobby.ariffin, I want to reroute this to "User" Controller because the url not handled by any Controller in my apps.
I had create this in my config/routes.php:
$route['(:any)'] = "user";
but it's override all the route in my apps to "User" Controller.
Is there any simple route for Codeigniter that doesn't override the other controller routes?
Update---
I've got simple regex for this problem, from: Daniel Errante's Blog
$route['^(?!ezstore|ezsell|login).*'] = “home/$0″;
where ezstore, ezsell, and login are the name of controller in Your Apps.
You can also use a foreach statement for this. That way you can keep your controllers in a nice neat list.
$controller_list = array('auth','dashboard','login','50_other_controllers');
foreach($controller_list as $controller_name)
{
$route[$controller_item] = $controller_name;
}
$route['(:any)'] = "user/display/$1";
You're going to have to explicitly define all of those routes. Otherwise you will always end up at the "user_controller".
$route['signup'] = "signup";
$route['(:any)'] = "user/display/$1";
or something similar. They are ran in order, so what ever is defined first, is going to happen first. So if you catch (:any), you're going to send ANYTHING to that controller.
Also keep in mind that you can use regular expressions, so if you know there is always going to be a '.' in there, you could test for that.

Resources