ASP.NET: Changing a site's culture programmatically - asp.net

i'm trying to set my website's culture programmatically, so when a user clicks a button they can change the text on the page from english to spanish. here's my code:
protected void btnChangeLanguage(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("es");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("es);
}
<asp:Label ID="lblDisplay" runat="server" meta:ResourceKey="lblDisplay" />
<asp:Button ID="btnChangeLanguage" runat="server" Text="Change Language"
OnClick="btnChangeLanguage_Click" />
i have a Default.aspx.resx file with a key/value of: lblDisplay.text/English
and a Default.aspx.es.resx file with a key/value of: lblDisplay.text/Espanol
i can't get my Label's text to change from "English" to "Spanish". anyone see what i'm doing wrong?

ASP.Net threads are used for the lifetime of one request, not a user's entire session. Worse, sometimes the framework will recycle the same thread to handle additional requests rather than return it to the pool and get a new one (it's not that big a deal because the next request will initialize the culture again, but still).
Instead, you need to override the InitializeCulture() method for your page. See this link for more detail:
http://msdn.microsoft.com/en-us/library/bz9tc508.aspx

Create Session variable called "CurrentUI". and change it on link buttons event
eg:
Here i have two link buttons for each language
protected void EnglishLinkButton_Click(object sender, EventArgs e) {
Session["CurrentUI"] = "en-US";
Response.Redirect(Request.Url.OriginalString);
}
protected void SinhalaLinkButton_Click(object sender, EventArgs e) {
// සිංහල (ශ්‍රී ලංකා)
Session["CurrentUI"] = "si-LK";
Response.Redirect(Request.Url.OriginalString);
}
Now you need to override the InitializeCulture() in the base class of page
protected override void InitializeCulture() {
if (Session["CurrentUI"] != null) {
String selectedLanguage = (string)Session["CurrentUI"];
UICulture = selectedLanguage;
Culture = selectedLanguage;
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new
CultureInfo(selectedLanguage);
}
base.InitializeCulture();
}
Note that I used
//Response.Redirect(Request.Url.OriginalString);
after assigning culture key into the session in order to create a second post back to the page.
Because InitializeCulture() happens before the event and change will be applicable in the next request only.

Related

Can't change month using ASP.NET globalisation

I am learning Asp.Net globalisation and localisation, and I found this example.
The example is working fine, but when I change the month in the calendar, the calendar text is automatically changing to English.
I tried it with
<asp:Calendar ID="Calendar1" runat="server" AutoPostBack="True"
OnSelectedIndexChanged="language_Drp_SelectedIndexChanged">
</asp:Calendar>
But I am still having a problem. Can anyone help me?
The example you found is not a very good one. The correct place to set the culture in ASP.NET is to override the method InitializeCulture. I normally implement that method in a common base class for all my web forms.
You could implement something like this:
protected override void InitializeCulture()
{
if (Session["locale"] != null)
{
string selectedLanguage = Session["locale"];
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(selectedLanguage);
}
base.InitializeCulture();
}
Somewhere you have to store the selected language in the Session variable, e.g. like this:
Session["locale"] = langDropdown.SelectedValue;
I don't think the example is correct. This
protected void language_Drp_SelectedIndexChanged(object sender, EventArgs e)
{
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(this.language_Drp.SelectedValue);
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(this.language_Drp.SelectedValue);
Label1.Text = System.DateTime.Now.ToString();
}
should be changed to this
protected override void InitializeCulture()
{
if (this.language_Drp.SelectedValue != null)
{
UICulture = this.language_Drp.SelectedValue ;
Culture = this.language_Drp.SelectedValue ;
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new
CultureInfo(selectedLanguage);
}
base.InitializeCulture();
}
This code came from here. I haven't tested it and may require some tweaking but it should at least get you on your way.
it seems to be a problem of postback treatment. HTTP connections are by nature stateless.
Sorry for the previous response, it was just a test. I´ve just recalled the postback issue.
By using slfan´s code and changing the drop box event interception method to:
protected void language_Drp_SelectedIndexChanged(object sender, EventArgs e)
{
Session["locale"] = this.language_Drp.SelectedValue;
InitializeCulture();
}
It seems to work fine, keeping the selected culture even when selecting a specific date.

How to dynamically set the Title of SiteMap from MasterPage?

In My Web.sitemap I have the following:
<siteMapNode url="~/Groups/ViewGroups.aspx" urlRoute="groups/{PostId}/{PostTitle}" />
</siteMapNode>
In my MasterPage I have implemented the ItemDataBound event to try and set the title of each page that implements the master page dynamically but for some reason the title is not being set.
protected void SiteMapPath1_ItemDataBound(object sender, SiteMapNodeItemEventArgs e)
{
string CurrentNodeTitle = GetTitleFromDatabase();
if (e.Item.ItemType == SiteMapNodeItemType.Current) {
e.Item.SiteMapNode.Title = CurrentNodeTitle;
}
}
I also tried this in the ItemCreated event but still it did NOT work.
If I set the title in the Web.sitemap then it works perfectly but when I set it using e.Item.SiteMapNode.Title = CurrentNodeTitle; the title is nto being set.
Try this.
private string currentKey = SiteMap.CurrentNode.Key
protected void SiteMapPath1_ItemDataBound(object sender, MenuEventArgs e)
{
string CurrentNodeTitle = GetTitleFromDatabase();
if (e.Item.DataPath == currentKey){
e.Item.Text = CurrentNodeTitle;
}
}
Edit note:
it should be MenuEventArgs
This question is about 6 years old now, and the one answer is completely wrong and should probably be deleted. I had a hard time finding the answer - it's not nearly as straight forward as I would have expected it to be, but the answer is pretty simple nonetheless.
Using the static SiteMap classes SiteMapResolve event from the System.Web namespace (NOT your instance of SiteMapPath!) you can manipulate the URL and Title on the fly.
In my case, I have a custom localization method that retrieves the localized strings from a database. The sitemap title's contain the key used to identify the string. This is the code behind for my Master Page:
protected void Page_Load(object sender, EventArgs e)
{
// ...
SiteMap.SiteMapResolve += (o, args) =>
{
if (SiteMap.CurrentNode == null)
return null;
SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
currentNode.Title = SessionObject.LocalizeText(currentNode.Title);
SiteMapNode tempNode = currentNode;
while (tempNode.ParentNode != null)
{
tempNode = tempNode.ParentNode;
tempNode.Title = SessionObject.LocalizeText(tempNode.Title);
}
return currentNode;
};
// ...
}
Then in your Master Page ASPX (or presumably any ASPX page that utilizes this Master Page), you can add <asp:SiteMapPath runat="server" ... /> and it should be processed by the SiteMapResolve event.

Propagting the resource culture change in master page to the content web pages

I'm a noob when it comes to web applications. But i'm trying my best to learn it using ASP.NET 2.0 and sorry for the long post.
I have a master page(M1) and 3 different content pagesC1,C2,C3 which basically use the master page M1 for filling its respective contents in the content placeholder.
All the web-forms are localized and appropriate language resource strings are added in the resource (xml) files ex: Resource.en-US.xml,Resource.de-DE.xml and so on.Finally the resources are referred in the code after setting up the appropriate current culture and current uiculture.
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
//where the btnSubmit is a control on the form
btnSubmit.Text = rm.GetString("Submit", Thread.CurrentThread.CurrentCulture);
Now comes the question, I have included an option of changing the display language in the master page available to the user as an asp:linkbutton with an asp:image. Whenever the user clicks the linkbutton for the desired language, the content page controls shall display the whole content strings corresponding to the culture selected.
How do i achieve this ?
Do i have to implement Session variables to include the selected
language ? Or storing in Cookie would also do the job ?
What i tried
On master page load event. I tried calling a method SetCultureSpecificInformation, which basically sets the culture and uiculture properties of CurrentThread and store the selected language inside a session variable.
Also a similar implementation on the asp:linkbutton OnClick eventhandler. In this case it modifies the session variable.
Finally refer the session variable on the content web page OnPage_Load event.
But somehow the above approach is not yielding desired results. The switching of language is not consistent. Anyone out there who can help me out with a good enough design approach for implementing the same.
Thanks in advance
Add Global.asax file: write this piece of code
void Application_BeginRequest(Object sender, EventArgs e)
{
// Code that runs on application startup
HttpCookie cookie = HttpContext.Current.Request.Cookies["CultureInfo"];
if (cookie != null && cookie.Value != null)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(cookie.Value);
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cookie.Value);
}
else
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en");
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en");
}
}
And on Masterpage page
protected void ddlanguage_SelectedIndexChanged(object sender, EventArgs e)
{
Session["language"] = ddlanguage.SelectedValue;
//Sets the cookie that is to be used by Global.asax
HttpCookie cookie = new HttpCookie("CultureInfo");
cookie.Value = ddlanguage.SelectedValue;
Response.Cookies.Add(cookie);
//Set the culture and reload for immediate effect.
//Future effects are handled by Global.asax
Thread.CurrentThread.CurrentCulture = new CultureInfo(ddlanguage.SelectedValue);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(ddlanguage.SelectedValue);
if (cookie.Value == "en")
{
Session["ddindex"] = 0;
}
else if (cookie.Value == "fr")
{
Session["ddindex"] = 1;
}
else if (cookie.Value == "de")
{
Session["ddindex"] = 2;
}
Server.Transfer(Request.Path);
}
}
In my case used a couple of buttons for setting culture from the master page, then used this code in the master page's code behid:
protected void IdiomButton_Click(object sender, ImageClickEventArgs e)
{
ImageButton theButton = (ImageButton)sender;
Session["culture"] = theButton.ID == "ItalianButton" ? CultureInfo.CreateSpecificCulture("it-IT") : CultureInfo.CreateSpecificCulture("en-US");
Response.Redirect(Request.RawUrl);
}
Then in every child page I used :
protected override void InitializeCulture()
{
if (Session["culture"] != null)
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(Session["culture"].ToString());
else
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("it-IT");
}

ASP.net passing data between pages

I have a .aspx web page, with a html form within it, this also has two input boxes.
Whats the best way to take the input box data and pass it to a new .aspx page where it is dealt with by the request method.
Assuming that the data is not sensitive then the best method to pass it to your new page using Response.Redirect and the querystring using:
protected void MyFormSubmitButton_Click(Object sender, EventArgs e)
{
string value1 = txtValue1.Text;
string value2 = txtValue2.Text;
// create a querystring
string queryString = "x=" + value1 + "&y=" + value2;
// redirect to the encoded querystring
Response.Redirect("NewPage.aspx?" + Server.URLEncode(queryString));
}
This web page has a lot of information which you can use for passing the values from page to page.
http://msdn.microsoft.com/en-us/library/6c3yckfw.aspx#Y1100
Try Server.Transfer:
Terminates execution of the current
page and starts execution of a new
page by using the specified URL path
of the page. Specifies whether to
clear the QueryString and Form
collections.
If you set the preserveForm parameter
to true, the target page will be able
to access the view state of the
previous page by using the
PreviousPage property.
Your main page:
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
// ThreadAbortException occurs here.
// See http://support.microsoft.com/kb/312629 for more details.
Server.Transfer("AnotherPage.aspx", true);
}
}
"AnotherPage.aspx":
protected void Page_Load(object sender, EventArgs e)
{
if (PreviousPage != null)
{
// Accessing previous page's controls
}
}

Prevent Page Refresh in C#

Duplicate of Asp.Net Button Event on refresh fires again??? GUID?
hello, ive a website and when a user click a button and the page postback, if the user refresh the Page or hit F5 the button method is called again.
any one know some method to prevent page refresh with out redirect the page to the same page again ?
something like if (page.isRefresh) or something... or if exist any javascript solution is better.
this seen to works.... but when i refresh it does not postback but show the before value in the textbox
http://www.dotnetspider.com/resources/4040-IsPageRefresh-ASP-NET.aspx
private Boolean IsPageRefresh = false;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["postids"] = System.Guid.NewGuid().ToString();
Session["postid"] = ViewState["postids"].ToString();
TextBox1.Text = "Hi";
}
else
{
if (ViewState["postids"].ToString() != Session["postid"].ToString())
{
IsPageRefresh = true;
}
Session["postid"] = System.Guid.NewGuid().ToString();
ViewState["postids"] = Session["postid"];
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (!IsPageRefresh) // check that page is not refreshed by browser.
{
TextBox2.Text = TextBox1.Text + "#";
}
}
Thanks for comments and sorry for my mistake,
I found this code in:
http://www.codeproject.com/KB/aspnet/Detecting_Refresh.aspx
And this time tested ;)
private bool _refreshState;
private bool _isRefresh;
protected override void LoadViewState(object savedState)
{
object[] AllStates = (object[])savedState;
base.LoadViewState(AllStates[0]);
_refreshState = bool.Parse(AllStates[1].ToString());
_isRefresh = _refreshState == bool.Parse(Session["__ISREFRESH"].ToString());
}
protected override object SaveViewState()
{
Session["__ISREFRESH"] = _refreshState;
object[] AllStates = new object[2];
AllStates[0] = base.SaveViewState();
AllStates[1] = !(_refreshState);
return AllStates;
}
protected void btn_Click(object sender, EventArgs e)
{
if (!_isRefresh)
Response.Write(DateTime.Now.Millisecond.ToString());
}
You can test for the Page.IsPostBack property to see if the page is responding to an initial request or if it's handling a PostBack such as your button click event. Here's a bit more information: w3schools on IsPostBack
Unfortunately that's not going to solve your problem since IsPostBack will be true when the user clicks the button as well as when they refresh the page after the button action has taken place.
If you're doing a task like performing CRUD on some data, you can Response.Redirect the user back to the same page when you're done processing and get around this problem. It has the side benefit of reloading your content (assuming you added a record to the DB it would now show in the page...) and prevents the refresh problem behavior. The only caveat is they still resubmit the form by going back in their history.
Postbacks were a bad implementation choice for the Asp.net and generally are what ruin the Webforms platform for me.
This doesn't solve the problem.
First of all, storing a token in the view state is not a good idea, since it can be disabled. Use control state instead. Although, a HttpModule is a better solution.
All in all, this will not work anyway. If you open another tab/window the session will be invalid for the previous tab/window. Therefore braking it. You must somehow store a unique value each time a page is first loaded. Use that to determine where the request came from and then check the "refresh ticket". As you may see, the object for one user might get pretty big depending on the amount of requests made, where and how long you store this information.
I haven't seen any solution to this I'm afraid, as it is pretty complex.
bool IsPageRefresh ;
if (Page.IsPostBack)
{
if (ViewState["postid"].ToString() != Session["postid"].ToString())
IsPageRefresh = true;
}
Session["postid"] = System.Guid.NewGuid().ToString();
ViewState["postid"] = Session["postid"];
I tried many ways and I ended up looking for the form data sent when the postback / refresh is triggered... I found that there is a Key for any VIEWSTATE created and you can just compare those Keys like...
I put that on my custom basepage to reuse it like an Property
public bool IsPageRefresh = false;
protected void Page_Init(object sender, EventArgs e)
{
if (IsPostBack)
{
var rForm = Request.Form;
var vw = rForm["__EVENTVALIDATION"].ToString();
var svw = Session["__EVENTVALIDATION"] ?? "";
if (vw.Equals(svw)) IsPageRefresh = true;
Session["__EVENTVALIDATION"] = vw;
}
}

Resources