I'm working on a asp.net web application and one of the requirements is that the user has to be able to select the language they want. I"m using Resx files to store the locals. What my question is do I need to change the CurrentCulture of the thread every time a page is loaded or is there a way to have it handled automatically when a logged in user moves from one page to the next.
Yes, I believe you need to set it every time. To make it even worse, you have to do it by overriding the InitializeCulture method of the Page class. I created a SitePage that all pages in my project inherit from instead of Page to do this.
public class SitePage : Page
{
protected override void InitializeCulture()
{
base.InitializeCulture();
// Set both the CurrentCulture (for currency, date, etc) conversion, and the CurrentUICulture for resource file lookup.
Thread.CurrentThread.CurrentCulture = whatever;
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
}
}
Further reading: http://msdn.microsoft.com/en-us/library/bz9tc508.aspx
Related
I created my new custom property for User in ASP.NET project ("DarkTheme").
I have a problem (see below). I can access User.Identity.Name without any ViewModels. I can access User.Identity.IsInRole() and so on. But I cannot access my new property ("DarkTheme"). I do not want to use viewmodels (I would have to rewrite the whole application). Is there a way to go to the place where ASP.NET makes User.Identity.Name accessible without any ViewModels and add "DarkTheme" property?
I didn't find the answer to this problem, but I have a workaround.
I used User.IsInRole("DarkTheme") attribute to pass the value to the view (and load different css files depending on the value). It is the only role that user can assign to himself without manager permission.
You could use OnActionExecuted method in your controller in combination with dynamic ViewBag
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (Request.IsAjaxRequest() || filterContext.IsChildAction) return; // you don't need styling for ajax requests which return json
base.OnActionExecuted(filterContext);
YourUser user = ... // get user from db/claims or get theme from cookies etc.;
ViewBag.DarkTheme = user.DarkTheme;
}
and in view it will be invoked simply by #ViewBag.DarkTheme, no namespace needed
I am creating a website that will be multilingual in nature.
I am providing a functionality whereby the user can select desired language by selecting it from the drop down.
Now my problem starts here (when a language is selected from the drop down). I am currently implementing 2 languages English and Arabic.
Problem is when the user select Arabic from the drop down on the login page the page is refreshed and the browser loads all the content in Arabic.
But...
When i select English back again, the page refreshes but the language content does not change !!
i have check the code and the values (culture name value) are being applied correctly!!
Any clues as to what is wrong and where...
Here is my code...
protected override void InitializeCulture()
{
String selectedLanguage = string.Empty;
if (Request.Form["ddlLanguage"] != null)
{
selectedLanguage = Request.Form["ddlLanguage"];
CultureInfo ci = new CultureInfo(selectedLanguage);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
base.InitializeCulture();
}
Any help will be great !!
Thanks
The Culture settings must set on each request. It's not enough to set the Thread cultures once when the selection changes.
In order to set the culture according to the user selection on each request, there are several possible ways.
Set the culture in (for instance) the Page_Init event of the master page.
Create custom base page (maybe MyBasePage) for the content pages and override the InitializeCulture method of that class. Then make all the content pages derive from the class instead of directly from Page.
Add code for setting the culture in a suitable event in Global.asax.
Probably there are several other possible ways to handle this as well.
Regardless of which method you will use, the culture that the user has chosen must be available to the code that is going to set the culture on the thread. So when the user changes his/her selection, you must save that selection in a place where you can access it in the coming requests. This can also be solved in several possible ways. Here are some options:
If you are using a ProfileProvider, you could save the selection to the user's profile.
Alternatively you can store it in a cookie.
You could possibly store it in the Session although that would mean that the user must re-select it whenever the Session has been reset.
You could use some other custom way to store the selection (database, some file on disk etc).
For a more detailed exmple of how this could be done using Global.asax and a cookie, have a look over here.
Check this article - How to create ASP.NET MVC multilingual web application ?
We will see mainly two approaches-
Approach 1: Using Static Pages
Approach 2: Using Dynamic page with localized data at runtime
At the moment I have a master page and a content page. My master page consists of a dropdownlist, from which I need to select a child from. The content page loads according the child chosen. How should I store the dropdownvalue chosen?
I don't think I can use the session, since I would like the user to be able to open multiple tabs and watch different children contents at the same time. If I can use the session in this case, I'm not sure how.
I don't think I can use the viewstate since, although it solves my multiple tabs problem, the master page and content page have a different view state.
At the moment I am using a public static variable on the content page, and I set it in the master page. But from what I've heard static variables have their values stored throughout ALL the current sessions on the site.
Question:
Can any one help me by suggesting which technology should I use?
I have also heard about the 'Application' object but I don't think it makes sense to use it.
Current working Code:
(content page)
public static string Child
{
get
{
if (child == null)
return "-1";
return child;
}
set
{
child = value;
}
}
(master page)
protected void ddlChooseChild_IndexChanged(object sender, EventArgs e)
{
ContentPage.Child = ddlChooseChild.SelectedValue;
}
The best way to share data between different controls is to make use of the "Items" collection (which is a property of the HttpContext class). The collection is a Hashtable and can be accessed from your Page and User Controls like so:
Context.Items["Child"] = ddlChooseChild.SelectedValue;
Unless you are restricting session by using PageID or something similar, Sessions are available on multiple tabs.
Check out this article, Master Content Page interaction
I have an ASP.NET website application on .NET 4.0. There is one Masterpage that contains the header and footer for all the aspx pages. The content comes from the individual aspx pages. I have BasePage.cs which all the aspx pages inherit from.
Now to the problem:
I have a HTML Select control on the masterpage, whose value I am trying to retrieve in the BasePage.cs using the below code
string language = ((System.Web.UI.HtmlControls.HtmlSelect)Master.FindControl("cmbLanguage")).Value;
I am using this inside the InitializeCulture method, which would set the Culture info for the website.
protected override void InitializeCulture()
{
string language = ((System.Web.UI.HtmlControls.HtmlSelect)Master.FindControl("cmbLanguage")).Value;
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(language);
Thread.CurrentThread.CurrentUICulture = new
CultureInfo(language);
base.InitializeCulture();
}
While debugging, I can see that the expected value is set in the language variable. The problem is when the page renders, the content inside the ContentPlaceHolder for the aspx page is not being rendered.
I can see that it is the code involving FindControl which is the cause, because if I set the language to a string, everything works as expected.
string language = "de-DE";
What am I doing wrong?
UPDATE:
If there is some content on the ContentPlaceHolder on the MasterPage, then it gets rendered instead of the page ContentPlaceHolder.
InitializeCulture is called before even PreInit in the page life cycle, which means the controls haven't been setup, and the Value of that control is likely coming through as an empty string.
You need to likely change how the culture is read, through a cookie, session value, or some other method. I'm not familiar with doing it, so i don't have a great suggestion or best practice.
As Doozer correctly noted that control is unlikely to have the correct value set up into it at the time of InitializeCulture. I will suggest that you read the value from POST data in the request and back it via some default value. For example,
string language = Request.Form[Master.FindControl("cmbLanguage")).UniqueID];
language = string.IsNullOrWhiteSpace(language) ? "de-DE" : language;
In order to access MasterPage controls its better to use MasterType directive. When used you are going to be able to access master page in a strongly typed way. In this case you will be able to create a property on master page like this:
public string SelectedCulture
{
get
{
return cmbLanguage.Value
}
}
And on page itself you will be able to run code like this:
protected override void InitializeCulture() {
string language = this.Master.SelectedCulture;
}
What is the last point in the asp.net page loading pipeline that I can change the culture of a page by doing the following?
Thread.CurrentThread.CurrentCulture = << new culture >>;
Thread.CurrentThread.CurrentUICulture = << new culture >>;
I am changing the culture in my code and want to know at what point is the last point in which I can change the pages culture so that the correct resource files etc are picked up.
Is the Page PreInit too late in the pipeline to change the culture? I am aware there is an InitialiseCulture method in the Page class but I am working outside of this.
As per MSDN documentation, correct way is to use InitialiseCulture - it gets called very early in page life-cycle before even controls are created. And that is even before PreInit event.
Said that, people have set the culture information as late as Page_Load event. For example, see this KB article or this code project article. So I guess that PreInit event should be ok.
There are two relevant properties - Culture and UICulture. AFAIK, UICulture is used for loading correct local (page specific)/global resources and that would be done at rendering stage - so should not be an issue. The culture info from thread get used by many frameworks methods and you need to be careful using any code that is dependent on the culture information before you sets the culture in page life cycle - example of such code can be formatting of data or parsing from request data etc.
See my comment to your original post too.
protected override void InitializeCulture()
{
UICulture = "en";
Culture = "en-US";
}
http://msdn.microsoft.com/en-us/library/bz9tc508.aspx