Ok .. another suggestion.
To make sure I understand, you want ..
- Every Action needs to be able to figure out what the LanguageCode is?
- If an invalid languageCode is provided, then it needs to be reset to a valid default one.
if so .. this answer has three parts:-
- Add the route. (this is cut-paste from my previous answer).
global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}",
new { favicon = @"(.*/)?favicon.ico(/.*)?" });
routes.MapRoute(
"Question-Answer", // Route name
"{languageCode}/{controller}/{action}", // URL with parameters
new {controller = "home", action = "index"} // Parameter defaults
);
}
Update (based on comments)
So, if you want to have the route http://www.mywebsite.com/sv/account/logon
then the above route will work.
LanguageCode
== sv (or en or fr or whatever language you're supporting)
account
== the controller: AccountController
login
== action.
the fact that i've said controller = "home"
and action="index"
only mean that those two parameters are defaulted to those values IF none were provided. So, if you goto http://www.mywebsite.com/sv/account/logon
then the MVC framework is smart enough to know (based on that route) that the languageCode paramters == sv, controller == action and action (method) == index.
NOTE: The order of your routes is IMPORTANT. critically important. This route needs to be one (if not the) of the first routes (after the IgonoreRoute's) when you register your routes.
- You need to create a custom ActionFilter which will get called BEFORE the action is executed. here's my quick attempt...
.
using System.Linq;
using System.Web.Mvc;
namespace YourNamespace.Web.Application.Models
{
public class LanguageCodeActionFilter : ActionFilterAttribute
{
// This checks the current langauge code. if there's one missing, it defaults it.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
const string routeDataKey = "languageCode";
const string defaultLanguageCode = "sv";
var validLanguageCodes = new[] {"en", "sv"};
// Determine the language.
if (filterContext.RouteData.Values[routeDataKey] == null ||
!validLanguageCodes.Contains(filterContext.RouteData.Values[routeDataKey]))
{
// Add or overwrite the langauge code value.
if (filterContext.RouteData.Values.ContainsKey(routeDataKey))
{
filterContext.RouteData.Values[routeDataKey] = defaultLanguageCode;
}
else
{
filterContext.RouteData.Values.Add(routeDataKey, defaultLanguageCode);
}
}
base.OnActionExecuting(filterContext);
}
}
}
- Now you'll need to make a BaseController, which all your controllers inherit from. This will then create an easily accessabily property which all your actions can access .. and then display whatever they want, based on that value.
here we go ... (pesduo code again....)
public abstract class BaseController : Controller
{
protected string LanguageCode
{
get { return (string) ControllerContext.RouteData.Values["LanguageCode"]; }
}
}
So then we decorate our controllers like this :)
[LanguageCodeActionFilter]
public class ApiController : BaseController
{
public ActionResult Index()
{
if (this.LanguageCode == "sv") ... // whatever.. etc..
}
}
Notice how i've decorated the class .. not just each action. this means ALL actions in the class will be affected by the ActionFilter :)
Also, you might want to add a new route in the global.asax that handles NO languageCode .. and hardcode default that value ...
like (also untested) ...
routes.MapRoute(
"Question-Answer", // Route name
"{controller}/{action}", // URL with parameters
new {controller = "home", action = "index", languageCode = "sv"} // Parameter defaults
);
Does this help?