I get intermittent problems with MVC routing attributes which stop working on our Azure hosted site.
Controller action and attributes look like this:
[AllowAnonymous]
[RequireHttps]
[RoutePrefix("{lang}")]
public class HomeController : LocalizationController
{
[...]
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
[AllowAnonymous]
[Route("sl", Name = "SelectLanguage")]
public ActionResult SelectLanguage(LanguageVersions? id)
{
This is action is called from the View like this using BeginForm:
@using (Html.BeginForm("SelectLanguage", "Home", null, FormMethod.Post, new { @class = "form", role = "form" }))
{
Or like this:
@Html.ActionLink(@Resources.Shared.LY_LEARN_SPANISH, "SelectLanguage", "Home", routeValues: new { id = CommonItems.LanguageVersions.SpanishVersion }, htmlAttributes: new { title = @Resources.Shared.LY_TO_SPANISH })
The last 2-3 days this has intermittently stopped working and the URL gets written without the attributes, i.e. becomes:
Home/SelectLanguage/SpanishVersion
Which gives a 404 error (and re-routes to error page).
After restarting the server, the attributes start working again. I've done this a few times, but the problems seem to reappear after 10-20 hrs. It also happens with other controller actions in a similar way.
Any ideas?
EDIT:
This is the Localization controller:
public abstract class LocalizationController : Controller
{
/// <summary>
/// Gets/sets the current user culture.
/// </summary>
public string strLang { get; set; }
/// <summary>
/// Executed before an action is executed.
/// </summary>
/// <param name="filterContext">The current filter context</param>
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
// Check if there is a route data language version.
strLang = (string)ControllerContext.RouteData.Values["lang"];
// Check if there is a logged in user...
if (Request.IsAuthenticated == true)
{
// There is an ASP.NET User, get the culture from that User.
var UserManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
ApplicationUser myUser = UserManager.FindById(User.Identity.GetUserId());
// If there is a different culture than the route, we must set the value from the User
if (myUser.UserCulture != strLang)
{
strLang = myUser.UserCulture;
// Update the filter context to re - route using the "lang" - field.
SetFilterContext(filterContext);
}
else if ((myUser.UserCulture == strLang) && strLang == null)
{
// At rare occasions, both can be null. Then we use default and re route using default.
strLang = "en";
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture = new CultureInfo(strLang);
// Set and update the User's culture as well.
myUser.UserCulture = strLang;
UserManager.Update(myUser);
HttpContext.GetOwinContext().Get<ApplicationDbContext>().SaveChanges();
}
} else if (strLang == null)
{
// Get the language from the browser setting.
var userLanguages = Request.UserLanguages;
CultureInfo ci;
if (userLanguages.Count() > 0)
{
try
{
ci = new CultureInfo(userLanguages[0]);
}
catch (CultureNotFoundException)
{
ci = CultureInfo.InvariantCulture;
}
}
else
{
ci = CultureInfo.InvariantCulture;
}
strLang = ci.TwoLetterISOLanguageName;
// Update the filter context to re-route using the "lang"-field.
SetFilterContext(filterContext);
}
// Set culture...
try
{
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture = new CultureInfo(strLang);
}
catch (System.Exception e)
{
// Can't set this culture, select default...
strLang = e.Message;
strLang = "en";
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture = new CultureInfo(strLang);
}
base.OnActionExecuting(filterContext);
}
private void SetFilterContext(ActionExecutingContext filterContext)
{
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();
if (actionName == "ReRouteToIndex")
// Set up as a default
actionName = "Index";
// Move to the same action and controller, but with the "lang" parameter set...
var controller = (LocalizationController)filterContext.Controller;
filterContext.Result = controller.RedirectToAction(actionName, controllerName, new { lang = strLang });
}
Any help is much appreciated.