Mvc View and HttpPost have different Culture Values - asp.net-mvc

In my View the culture value is right. But in my ajax HttpPost method the culture is wrong. My goal is check url lang if empty check cookie if it is again empty I get the language from client(English,German,Turkish) default is TUrkish if client have another lang. I try to explain with example. My framework is 4.7.2
Here is my OnActionExecuting:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.HttpMethod == "GET")
{
var domainLang = RouteData.Values["lang"] as string;
if (!string.IsNullOrEmpty(domainLang) && !string.IsNullOrWhiteSpace(domainLang))
{
//CurrentInfo is my class it is getting values from DB for once
bool avaibleLang = CurrentInfo.AvailableLanguages.Count(x => x.DilKey == domainLang) > 0;
if (avaibleLang)
{
var langCookie = CurrentInfo.CurrentLang;
if (domainLang != langCookie.DilKey)
{
ClientCookieManagement.CreateCookie(CookieEnum.Language.GetStringValue(), domainLang, 7);
}
}
else
{
domainLang = CurrentInfo.CurrentLang.DilKey;
}
}
Thread.CurrentThread.CurrentUICulture = new CultureInfo(domainLang ?? CurrentInfo.CurrentLang.DilKey);
}
base.OnActionExecuting(filterContext);
}
I check my culture in view and it is right.
#Thread.CurrentThread.CurrentUICulture
#Thread.CurrentThread.CurrentCulture
But if I submit or post something with ajax the culture is wrong
CultureInfo.CurrentUICulture
My webconfig
<globalization culture="tr-TR" -uiCulture="tr-TR"/> Default lang is TR
PROBLEM:
I need get the right value in my controller if I submit or anything else. What am I doing wrong?

Related

How to make website go under maintenance by writing a code in global.asps files using start time and end time key from web.config

i'm writing a code for making a site under maintenance.Can anyone help me please.the requirements are as follows.i have a project code i need to make that website go under maintenance from a specific time to specific time like example from 18 to before 8 it should be under maintenance and it should be done in global.asax file and start and end time should be like keys whose value is present webconfig file as shown below can any one please help me out??
code for global.aspx should be like dis...................
// Clear the response stream
var httpContext = HttpContext.Current;
httpContext.Response.Clear();
httpContext.ClearError();
httpContext.Response.TrySkipIisCustomErrors = true;
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", action);
// Call error Controller and pass the routeData.
using (var controller = new ErrorController())
{
((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}
the key should be as follows...
<add key="StartTime" value="8"/>
<add key="EndTime" value="18"/>
the logic i have taken is as follows
public class UnderMaintenanceAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var requestTimestamp = filterContext.HttpContext.Timestamp;
if (IsUnderMaintenance(requestTimestamp))
{
filterContext.Result = new RedirectToRouteResult(
// create your controller/action/view to display your message
new RouteValueDictionary
{
{ "controller", "Undermaintenance" },
{ "action", "Index" }
});
}
}
private bool IsUnderMaintenance(DateTime requestTimestamp)
{
bool isUnderMaintenance = requestTimestamp.Hour >= 18 || requestTimestamp.Hour < 13;
return isUnderMaintenance;
}
}
but i have written that in route config my manager wants me to write it in global.aspx with start key and end key

Changing culture only changing the language of model items

I have implemented the culture in my Asp.net application. But what I want is to change the language of the entire page but it's changing only model items language.
CultureHelper.cs
public class CultureHelper
{
protected HttpSessionState session;
public CultureHelper(HttpSessionState httpSessionState)
{
session = httpSessionState;
}
public static int CurrentCulture
{
get
{
switch (Thread.CurrentThread.CurrentUICulture.Name)
{
case "en": return 0;
case "hi-IN": return 1;
default: return 0;
}
}
set
{
if (value == 0)
{
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
}
else if(value==1)
{
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("hi-IN");
}
else
{
Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InvariantCulture;
}
Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture;
}
}
}
BaseController.cs
protected override void ExecuteCore()
{
int culture = 0;
if (this.Session == null || this.Session["CurrentCulture"] == null)
{
int.TryParse(System.Configuration.ConfigurationManager.AppSettings["Culture"], out culture);
this.Session["CurrentCulture"] = culture;
}
else
{
culture = (int)this.Session["CurrentCulture"];
}
// calling CultureHelper class properties for setting
CultureHelper.CurrentCulture = culture;
base.ExecuteCore();
}
protected override bool DisableAsyncSupport
{
get { return true; }
}
My model class
[Display(Name="Name",ResourceType =typeof(Resource))]
Language only changing for the model class properties. But I want to change the language for static/nonmodel properties too. Like I want to change button text too. I have added all contents in the resource file. How can I achieve this?
Add a resource file for every culture you want to support, e.g.
Resources.en.resx
Resources.hi-IN.resx
The framework will resolve which file to use based on the set CurrentCulture.
Resources.resx (without culture name) will be used as fallback if no culture specific file can be found.
Use the resource file to retrieve your translated strings, e.g. in your View.cshtml:
#using MyProject.Resources
<button type="submit">
#Resources.Submit #* this retrieves the translation for the key "Submit" *#
</button>

How can I use an action filter to redirect the output of a controller action in MVC3

I have the following in my code:
if (Session["CurrentUrl"] != null)
{
var ip = new Uri((string)Session["CurrentUrl"]);
var ipNoPort = string.Format("{0}://{1}/{2}", ip.Scheme, ip.Host, ip.PathAndQuery);
return Redirect(ipNoPort);
}
return Home();
It checks if a Session variable is set and then redirects to that URL or lets the action return to the Home method.
Does anyone have an example of how I could convert this into an action filter?
Also can I provide the action filter with the parameter of "Home" so it knows where to go to next?
Here is an example for ActionFilter that does redirect
public class TheFilter: ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
if (controllerName !="TopSecert")
return;
var redirectTarget = new RouteValueDictionary
{{"action", "ActionName"}, {"controller", "ControllerName"}};
filterContext.Result = new RedirectToRouteResult(redirectTarget);
// Or give a url (the last in this example):
filterContext = new RedirectResult(filterContext.HttpContext.Request.UrlReferrer.AbsolutePath);
// The session you can get from the context like that:
var session = filterContext.HttpContext.Session;
}
}
Edit: change from Executing to Executed and added session handling.

ASP.NET MVC to ignore ".html" at the end of all url

I am new to asp.net mvc and now struggling with url routing. I'm using asp.net mvc 3 RC2.
How can I create a url routing that IGNORES the very end extension in url. the extension can be: .html, .aspx, .php, .anything.
For example, these urls:
/Home.html
/Home.en
/Home.fr
/Home
should go to Home controller?
one more example:
/Home/About.html
/Home/About.en
/Home/About.fr
/Home/About
should go to Home controller and About action.
thank you :)
I'm not sure if you're using IIS7, but if so, then I would recommend a rewrite rule which checks for urls ending in .xyz and then doing a rewrites for them without the .xyz.
Something like this:
<rewrite>
<rules>
<rule name="HtmlRewrite">
<match url="(.*)(\.\w+)$" />
<action type="Rewrite" url="{R:1}" />
</rule>
</rules>
</rewrite>
This will handle the use cases you suggested. Anything that ends with an extension and some characters will be rewritten to a url without the extension. The benefit of this is that you will only need one route because everything goes into your application without one.
You just need to tweak the default route in Global.asax.cs, try this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}.{extension}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
The {extension} value from the url will be included in the route data, but you can just safely ignore it if you don't need it
Either create your own route class, or use this regex route implementation: http://blog.sb2.fr/post/2009/01/03/Regular-Expression-MapRoute-With-ASPNET-MVC.aspx
You could handle this in IIS instead of ASP.NET MVC using IIS Url rewriting. See for example: http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/
I started to work on this question as a weekend assignment :D
below code will work as requested in question. please refer below references
1] MyUrlRoute Class : RouteBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcIgnoreUrl
{
#region //References
// SO question /http://stackoverflow.com/questions/4449449/asp-net-mvc-to-ignore-html-at-the-end-of-all-url
// Implementing Custom Base entry - Pro Asp.Net MVc Framework
//- http://books.google.com/books?id=tD3FfFcnJxYC&pg=PA251&lpg=PA251&dq=.net+RouteBase&source=bl&ots=IQhFwmGOVw&sig=0TgcFFgWyFRVpXgfGY1dIUc0VX4&hl=en&ei=z61UTMKwF4aWsgPHs7XbAg&sa=X&oi=book_result&ct=result&resnum=6&ved=0CC4Q6AEwBQ#v=onepage&q=.net%20RouteBase&f=false
// SO previous Question on ihttphandler - http://stackoverflow.com/questions/3359816/can-asp-net-routing-be-used-to-create-clean-urls-for-ashx-ihttphander-handle
// phil haack's Route Debugger http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
#endregion
public class MyUrlRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//~/Account/LogOn
//~/Home.aspx - Works fine
//~/home/index.aspx -Works Fine
//http://localhost:57282/home/index/1/2/3 - Works fine
//http://localhost:57282/Account/Register http://localhost:57282/Account/LogOn - Works Fine
string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
//check null for URL
const string defaultcontrollername = "Home";
string[] spliturl = url.Split("//".ToCharArray());
string controllername = String.Empty;
string actionname = "Index";
if (spliturl.Length == 2) //for ~/home.aspx and ~/
{
if (String.IsNullOrEmpty(spliturl[1])) //TODO: http://localhost:57282/ not working - to make it working
{
controllername = defaultcontrollername;
}
else
{
controllername = spliturl[1];
if (controllername.Contains("."))
{
controllername = controllername.Substring(0, controllername.LastIndexOf("."));
}
}
}
else if (spliturl.Length == 3) // For #/home/index.aspx and /home/about
{
controllername = spliturl[1];
actionname = spliturl[2];
if (actionname.Contains("."))
{
actionname = actionname.Substring(0, actionname.LastIndexOf("."));
}
}
else //final block in final case sned it to Home Controller
{
controllername = defaultcontrollername;
}
RouteData rd = new RouteData(this, new MvcRouteHandler());
rd.Values.Add("controller", controllername);
rd.Values.Add("action", actionname);
rd.Values.Add("url", url);
return rd;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
}
in global.asax.cs add below code
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new MyUrlRoute()); // Add before your default Routes
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
working as expected.
possibly you can improve if/elseif code.
Using the Application_BeginRequest, will allow you to intercept all incoming requests, and allow you to trim the extension. Make sure to ignore requests for your content, such as .css, .js, .jpg, etc. Otherwise those requests will have their extensions trimmed as well.
protected void Application_BeginRequest(object sender, EventArgs e)
{
String originalPath = HttpContext.Current.Request.Url.AbsolutePath;
//Ignore content files (e.g. .css, .js, .jpg, .png, etc.)
if (!Regex.Match(originalPath, "^/[cC]ontent").Success)
{
//Search for a file extension (1 - 5 charaters long)
Match match = Regex.Match(originalPath, "\\.[a-zA-Z0-9]{1,5}$");
if (match.Success)
{
String modifiedPath = String.Format("~{0}", originalPath.Replace(match.Value, String.Empty));
HttpContext.Current.RewritePath(modifiedPath);
}
}
}
If you are using IIS 7, you should look at Dan Atkinson's answer.
I'm using IIS 6, so, in my case, I have the option to install isapi rewrite for IIS 6 or create custom route. I prefer to create my simple custom route class
AndraRoute.cs
// extend Route class,
// so that we can manipulate original RouteData
// by overriding method GetRouteDate
public class AndraRoute : Route
{
// constructor
public AndraRoute(
string url,
RouteValueDictionary defaults,
RouteValueDictionary constraints,
IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler)
{
}
// get original RouteData
// check if any route data value has extension '.html' or '.anything'
// remove the extension
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var data = base.GetRouteData(httpContext);
if (data == null) return null;
// from original route data, check
foreach (var pair in data.Values)
{
if (pair.Value.ToString().Contains('.'))
{
var splits = pair.Value.ToString().Split('.');
if (splits[1] == "html" || splits[1] == "anything")
{
data.Values[pair.Key] = splits[0];
}
break;
}
}
return data;
}
}
RouteCollectionExtensionHelper.cs
public static class RouteCollectionExtensionHelper
{
public static Route MapAndraRoute(this RouteCollection routes,
string name, string url, object defaults, object constraints,
string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
var route = new AndraRoute(url,
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints),
new MvcRouteHandler());
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens = new RouteValueDictionary();
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
}
RegisterRoutes method in Global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("Content/{*pathInfo}");
routes.MapAndraRoute(
"Product",
"product/{id}/{slug}",
new { controller = "product", action = "detail" },
null, null
);
routes.MapAndraRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "home", action = "index", id = UrlParameter.Optional },
null, null
);
}

Does .NET MVC have a strongly typed RedirectToAction?

Since I have decided to let RC go while staying with Beta for now, I have no way of knowing whether a strongly typed RedirectToAction has been added. Has anybody tried it and is there a strongly typed RedirectToAction (and maybe ActionLink) in RC?
This is also included in MVC Contrib as an extension method on your controller, along with a lot of other strongly typed goodies for ModelState handling, testing, etc. It's well worth taking on the extra dependency for what it offers.
No, it doesn't.
protected RedirectToRouteResult RedirectToAction<T>(Expression<Action<T>> action, RouteValueDictionary values) where T : Controller
{
var body = action.Body as MethodCallExpression;
if (body == null)
{
throw new ArgumentException("Expression must be a method call.");
}
if (body.Object != action.Parameters[0])
{
throw new ArgumentException("Method call must target lambda argument.");
}
string actionName = body.Method.Name;
var attributes = body.Method.GetCustomAttributes(typeof(ActionNameAttribute), false);
if (attributes.Length > 0)
{
var actionNameAttr = (ActionNameAttribute)attributes[0];
actionName = actionNameAttr.Name;
}
string controllerName = typeof(T).Name;
if (controllerName.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))
{
controllerName = controllerName.Remove(controllerName.Length - 10, 10);
}
RouteValueDictionary defaults = LinkBuilder.BuildParameterValuesFromExpression(body) ?? new RouteValueDictionary();
values = values ?? new RouteValueDictionary();
values.Add("controller", controllerName);
values.Add("action", actionName);
if (defaults != null)
{
foreach (var pair in defaults.Where(p => p.Value != null))
{
values.Add(pair.Key, pair.Value);
}
}
return new RedirectToRouteResult(values);
}
That should work.
You can use return RedirectToAction(nameof(Index));
If you don't want the full MvcContrib library, you can get just this feature by using the MvcNavigationHelpers NuGet package.

Resources