Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

masterpage initializeculture no suitable method found to override error?

Tags:

c#

calendar

I'm trying to develop a MultiLanguage web site using ASP.NET with C# My problem is: I want to make my MasterPage support switching among languages, but when i put the "InitializeCulture()" inside the masterpage.cs, I got this error.

this is my code:

public partial class BasicMasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
    if (e.Day.IsToday)
    {
        e.Cell.Style.Add("background-color", "#3556bf");
        e.Cell.Style.Add("font-weight", "bold");
    }
}
Dictionary<string, System.Globalization.Calendar> Calendars =
    new Dictionary<string, System.Globalization.Calendar>()
    {
        {"GregorianCalendar", new GregorianCalendar()},
        {"HebrewCalendar", new HebrewCalendar()},
        {"HijriCalendar", new HijriCalendar()},
        {"JapaneseCalendar", new JapaneseCalendar()},
        {"JulianCalendar", new JulianCalendar()},
        {"KoreanCalendar", new KoreanCalendar()},
        {"TaiwanCalendar", new TaiwanCalendar()},
        {"ThaiBuddhistCalendar", new ThaiBuddhistCalendar ()}
    };

protected override void InitializeCulture()
{
    if (Request.Form["LocaleChoice"] != null)
    {
        string selected = Request.Form["LocaleChoice"];
        string[] calendarSetting = selected.Split('|');
        string selectedLanguage = calendarSetting[0];

        CultureInfo culture = CultureInfo.CreateSpecificCulture(selectedLanguage);

        if (calendarSetting.Length > 1)
        {
            string selectedCalendar = calendarSetting[1];
            var cal = culture.Calendar;
            if (Calendars.TryGetValue(selectedCalendar, out cal))
                culture.DateTimeFormat.Calendar = cal;
        }

        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    }
    base.InitializeCulture();
}
}

How can I create a Base class?

like image 695
Nuha_IT Avatar asked Aug 04 '12 04:08

Nuha_IT


2 Answers

The method InitializeCulture() exists only on the Page class, not the MasterPage class, and that's why you get that error.

To fix this, you could create a BasePage that all your specific pages inherit:

  1. Create a new Class (not Webform), call it BasePage, or whatever you want.
  2. Make it inherit System.Web.UI.Page.
  3. Make all your other pages inherit the BasePage.

Here's an example:

public class BasePage : System.Web.UI.Page
{
    protected override void InitializeCulture()
    {
        //Do the logic you want for all pages that inherit the BasePage.
    }
}

And the specific pages should look something like this:

public partial class _Default : BasePage //Instead of it System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //Your logic.
    }

    //Your logic.
}
like image 141
Aske B. Avatar answered Sep 27 '22 22:09

Aske B.


There is an alternate solution that DOES NOT require you to create a BasePage.

The problem with 'Culture' is that it gets set very very early on the page life cycle, so the Page.InitializeCulture event is one of the early events on the page (if not the only one) where we can hook up to change the Thread.CurrentThread.CurrentUICulture. But what if we do that even earlier, as soon as the Request begins on the server.

I do that on the Application_BeginRequest event on the Global.asax file which is called on every request.

protected void Application_BeginRequest(Object sender, EventArgs e)
{
  HttpCookie cookie = Request.Cookies["langCookie"];
  if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
  {
    Thread.CurrentThread.CurrentUICulture = new CultureInfo(cookie.Value);
  }
}

There I check for the existence of a cookie that holds the culture I want to use. If there's no cookie, then the default culture will be used.

To change the language on my application I just need a control that changes the cookie value client-side and then do a simple postback to the server. It doesn't matter if such control is on the Content Page or in the Master Page, it doesn't even need any code on the server-side, because all the processing is done on the method above, and the cookie gets set on the client-side even before the page is posted.

I've used a simple LinkButton (which is styled as a Mexican Flag), but you can use any other control that do a postback when clicked/changed.

<asp:LinkButton ID="btnSpanish" runat="server" OnClientClick="SetLanguageCookie('es')" CausesValidation="false" CssClass="mxFlag" />

Right before this button posts back to the server, it runs the client-side click event which updates the cookie value I want to set, and voila!

I have the javascript code that sets the cookie at the Master Page head section:

function SetLanguageCookie(selectedLanguage) {
  var expDate = new Date();
  expDate.setDate(expDate.getDate() + 20); // Expiration 20 days from today
  document.cookie = "langCookie=" + selectedLanguage + "; expires=" + expDate.toUTCString() + "; path=/";
};

That's it!! The Thread.CurrentThread.CurrentUICulture gets changed and no BasePage class is needed nor overriding the Page.InitializeCulture method. There's even the side effect that the language selected is remembered on following visits since it's stored on a cookie.

If you want to use a DropDownList instead of a LinkButton, just make sure to set the AutoPostBack="true" and, since there is no OnClientChanged property for the DropDownList, you must hardcode the onchange attribute on the DropDownList and pass the selected value to the same javascript function.

<asp:DropDownList ID="ddlLanguage" runat="server" AutoPostBack="true" onchange="SetLanguageCookie(this.options[this.selectedIndex].value)">
  <asp:ListItem Text="English" Value="en" />
  <asp:ListItem Text="Español" Value="es" />
  <asp:ListItem Text="Français" Value="fr" />
</asp:DropDownList>

The onchange attribute is not part of the DropDownList properties, however, since the DropDownList is an analog control of the <select> control, the attribute is just placed 'as is' when the rendering happens, and it's rendered before the postback mechanism code. Here's the HTML rendered by the DropDownList above:

<select name="ctl00$cph1$ddlLanguage" onchange="SetLanguageCookie(this.options[this.selectedIndex].value);setTimeout(&#39;__doPostBack(\&#39;ctl00$cph1$ddlLanguage\&#39;,\&#39;\&#39;)&#39;, 0)" id="cph1_ddlLanguage">
  <option value="en">English</option>
  <option value="es">Español</option>
  <option value="fr">Français</option>
</select>

Hope someone finds this approach as useful as I do. :)

like image 28
alonso.torres Avatar answered Sep 28 '22 00:09

alonso.torres