views:

1755

answers:

3

Create an MVC project, and its "Scripts" folder will include MicrosoftAjax.js (release and debug versions).

In Visual Web Developer 2008 Express Edition at least, the Scripts folder does not contain any of the Globalization scripts, i.e. the 205 files (e.g. "af-ZA.js") that define and set up '__cultureInfo' for that culture.

They are also missing from the MVC project template Zip file.

I guess you can download them separately, but...

What is the MVC way to do script globalization, with MsAjax's __cultureInfo being tailored to the browser's preferred language?

+4  A: 

OK... well... turns out you have to do it yourself.

The following code tells you how to get the globalization scripts and install them. Plus it gives you a handy extension method that allows you to inject a reference to MS AJAX on your View or Master Page, with or without script globalization enabled.

Features:-

  • inject MS AJAX onto View with minimal effort
  • Debug or Release version chosen according to whether assembly is compiled in Debug or Release mode
  • optionally enable script globalization
  • optionally inject call to the Sys.Application.initialize() function
  • optionally inline the code to enable script globalization, like the ScriptManager does (requires conditional compilation symbol); by default a reference to the globalization script file is injected.

Enjoy!

//
// Include Microsoft Ajax In Your ASP.NET MVC Projects, Optionally With Script Globalization Enabled
// -------------------------------------------------------------------------------------------------
//
// Written by Andrew Webb, 4th May 2009.
//
// Feel free to use in your ASP.NET MVC projects.
// Written for ASP.NET MVC 1.0 and .NET Framework 3.5 SP1.
//
// With thanks to Bertrand LeRoy and Steven Sanderson.
// http://weblogs.asp.net/bleroy/
// http://blog.codeville.net/
//
// Example usage of 'IncludeMicrosoftAjax':-
//    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" Culture="auto" UICulture="auto" %>
//    <%@ Import Namespace="AspNetMvcHelper" %>
//    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
//    <html xmlns="http://www.w3.org/1999/xhtml" >
//    <head runat="server">
//      <!-- Include Ms Ajax, with script globalization enabled -->
//      <%= Html.IncludeMicrosoftAjax (true, false) %>
//      <!-- other script references here, e.g. jQuery -->
//    </head>
//    etc.
//
// Note: for script globalization, the method in this file gets the current thread's current culture.
// The Culture="auto" setting in the Page directive (above) causes this to be set to the browser's
// preferred language.  Alternatively you can set the current thread's current culture manually.
//
// NOTA BENE: for script globalization, the 205 globalization scripts from the MS AJAX Library must be
// obtained from Microsoft and added to your ASP.NET MVC project, as follows:
// 1) Download the Microsoft AJAX Library 3.5 from:
//    http://www.asp.net/ajax/downloads/
//
// 2) Extract all files from the Zip, and locate the "Globalization" folder.  It should have 205 script files
// in it, from "af-ZA.js" to "zu-ZA.js".  Copy this folder inside your website/project, under the "Scripts"
// folder.  Rename the folder to "MsAjaxGlobalization".  The resulting structure should be:
//   <project>\
//     Scripts\
//       MsAjaxGlobalization\
//         <205 files>
//       <jQuery, Ms Ajax and Ms Mvc Ajax files>
//
// Be sure to include the "MsAjaxGlobalization" folder in your web project.  The easiest way is to click
// "Show All Files" button in the Solution Explorer's toolbar so that all files are shown, then right-click
// on "MsAjaxGlobalization" folder and select 'Include In Project' menu item.  You can now unshow all files
// again.
//

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using System.Text;
using System.IO;
using System.Threading;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;

namespace AspNetMvcHelper
{
  public static class ViewHelpers
  {
    /// <summary>
    /// Includes Microsoft Ajax in a View, optionally with script globalization enabled.
    /// </summary>
    /// <param name="helper">
    /// Unused.  Included because this method is an extension method of System.Web.Mvc.HtmlHelper.
    /// </param>
    /// <param name="enableScriptGlobalization">
    /// true to enable script globalization, else false.  If true, be sure to include the 205 globalization
    /// scripts in your project, in a subfolder called "MsAjaxGlobalization".  This must be a direct sub-
    /// folder of the "Scripts" folder, which in turn must live under the project root (which is the default
    /// for MVC projects).
    /// </param>
    /// <param name="initializeSysApplication">
    /// true to insert a call to 'Sys.Application.initialize', else false.  (Note sure if this should be
    /// done or not for MVC, so it's an option.)
    /// </param>
    /// <returns>
    /// Include-text that contains "script" tags that a) set up variable '_cultureInfo' (optional), b)
    /// cause the browser to load the Microsoft Ajax library (debug or release), and c) call function
    /// 'Sys.Application.initialize' (optional).
    /// </returns>
    [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId="helper")]
    public static String IncludeMicrosoftAjax (this HtmlHelper helper, Boolean enableScriptGlobalization,
                                               Boolean initializeSysApplication)
    {
      // Define INLINE_SETCULTUREINFO if you want to include the statement to set __cultureInfo in the HTML,
      // like the ScriptManager does.  Leave it undefined to have a script file reference instead (preferred).

#if INLINE_SETCULTUREINFO
      String setCultureInfoText = null;
#endif
      String globalizationScriptFileName = null;

      // Text length without the inline statement to set __cultureInfo.
      Int32 includeTextLength = 400;


      // If script globalization is enabled, get the statement that sets __cultureInfo, and add the
      // length of this statement to the overal length of the include-text.
      if (enableScriptGlobalization)
      {
        // Get the current thread's current culture.  Note: we could have a param that says whether to
        // use this or the UICulture.
        CultureInfo culture = Thread.CurrentThread.CurrentCulture;

        // Form the name of the globalization script file, "en-US.js".
        globalizationScriptFileName = culture.Name + ".js";

#if INLINE_SETCULTUREINFO
        // Read in the contents of this file.  Note that if this fails, the browser will be left with
        // __cultureInfo set to "en-US" (see file "MicrosoftAjax.debug.js", lines 6432 and 6433).
        try
        {
          setCultureInfoText = String.Empty;
          String path = HttpContext.Current.Server.MapPath ("~/Scripts/MsAjaxGlobalization/" +
                                                            globalizationScriptFileName);
          setCultureInfoText = File.ReadAllText (path);

          includeTextLength += setCultureInfoText.Length;
        }
        catch (System.ArgumentNullException)
        {
        }
        catch (System.ArgumentException)
        {
        }
        catch (System.IO.PathTooLongException)
        {
        }
        catch (System.IO.DirectoryNotFoundException)
        {
        }
        catch (System.IO.FileNotFoundException)
        {
        }
        catch (System.IO.IOException)
        {
        }
        catch (System.UnauthorizedAccessException)
        {
        }
        catch (System.NotSupportedException)
        {
        }
        catch (System.Security.SecurityException)
        {
        }
        catch (System.Web.HttpException)
        {
        }
#endif
      }


      // Create and initialize the StringBuilder in which we'll build up the include-text.
      StringBuilder sb = new StringBuilder (includeTextLength);
      sb.AppendLine ();


      // Get the application absolute path of the MS AJAX file (release or debug).  As you can see,
      // the folder and file names and locations are hardcoded.  Convention... but er, no configuration!
#if DEBUG
      String msAjaxScriptPath = VirtualPathUtility.ToAbsolute ("~/Scripts/MicrosoftAjax.debug.js");
#else
      String msAjaxScriptPath = VirtualPathUtility.ToAbsolute ("~/Scripts/MicrosoftAjax.js");
#endif

      // Add the globalization statement.
      if (enableScriptGlobalization)
      {
#if INLINE_SETCULTUREINFO
        sb.AppendLine ("<script type=\"text/javascript\">");
        sb.AppendLine ("//<![CDATA[");
        sb.AppendLine (setCultureInfoText);
        sb.AppendLine ("//]]>");
        sb.AppendLine ("</script>");
#else
        String path = VirtualPathUtility.ToAbsolute ("~/Scripts/MsAjaxGlobalization/" + globalizationScriptFileName);
        sb.AppendLine ("<script src=\"" + path + "\" type=\"text/javascript\"></script>");
#endif
      }

      // Add the MS AJAX library reference.      
      sb.AppendLine ("<script src=\"" + msAjaxScriptPath + "\" type=\"text/javascript\"></script>");

      // Add the call to initialize Sys.Application.
      if (initializeSysApplication)
      {
        sb.AppendLine ("<script type=\"text/javascript\">");
        sb.AppendLine ("//<![CDATA[");
        sb.AppendLine ("if (typeof (Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');");
        sb.AppendLine ("Sys.Application.initialize();");
        sb.AppendLine ("//]]>");
        sb.AppendLine ("</script>");
      }

      // Return the resulting include-text.      
      return (sb.ToString ());
    } 
  }
}
Andrew Webb
A: 

Nice work andrew, exactly what I was looking for. thanks! :)

ty
Please use the comment feature underneath the original answer for comments.
Abel
A: 

Hi there,

We've published the updated globalization scripts on the CDN. This blog post will walk you through how to take advantage of globalization with ASP.NET MVC client validation.

Haacked