3

I have inherited from a very small ASP.NET WebForms project, and my customer would like to add a second language to it.

For every "somepage.aspx", I'd like to support a "second language path" version of it, like "fr/somepage.aspx". I'd like to handle this using normal globalization (CurrentCulture + resource files in both languages) and avoid having to duplicate each page. I must keep the original paths valid, thus I have excluded ASP.NET MVC for now (for lack of knowing if I could continue to support ".aspx" paths).

Is this possible?

Michael Liu
55.8k14 gold badges126 silver badges158 bronze badges
asked Jan 30, 2012 at 22:57
5
  • Hope this will help you: stackoverflow.com/questions/373106/… Commented Jan 31, 2012 at 3:15
  • It does offer a solution for a fresh start, but in my case, I have to keep the existing paths valid. The real question is "how can I make "site.com/page.aspx" handle a request to "site.com/fr/page.aspx" but keeping "site.com/fr/page.aspx" as the URL the user sees. Commented Feb 2, 2012 at 1:39
  • 1
    I suppose you could create two Routes (first route for page with language and second for page without language) and create a constraint that matches the languages you want to accept. See msdn.microsoft.com/en-us/magazine/dd347546.aspx and weblogs.asp.net/scottgu/archive/2009/10/13/…. are all of your paths off the root of your site or do you have N number of folders you want to support too? Commented Feb 3, 2012 at 1:13
  • @MartinPlante I tagged this question with "c#" based on your profile. Please change it if you expect another language. Commented Feb 3, 2012 at 23:36
  • @Splash-X You should put that comment as an answer, since it's exactly what I was looking for. Currently, the site is all in the root. I'll simply support routes for "fr/..." and "en/...". Commented Feb 4, 2012 at 15:46

4 Answers 4

2
+50

URL Routing is avalaible in for ASP.NET.

You could create two routes, the first being the route that catches your language:

{language}/{page}

The second route would be just

{page}

In MVC we can create route constraints that would enforce the Language to be of a specific value (so like en, en-us, etc) I'm not positive if the same can be done in regular ASP.NET WebForms routing.

Here are two articles that describe the topic of routing in WebForms (non-MVC)

http://msdn.microsoft.com/en-us/magazine/dd347546.aspx

and

http://weblogs.asp.net/scottgu/archive/2009/10/13/url-routing-with-asp-net-4-web-forms-vs-2010-and-net-4-0-series.aspx

EDITED TO ADD CODE SAMPLE

In my Global.asax I registered the following:

 void RegisterRoutes(RouteCollection routes)
 {
 routes.Ignore("{resource}.asxd/{*pathInfo}");
 routes.Add(
 new Route(
 "{locale}/{*url}", //Route Path
 null, //Default Route Values
 new RouteValueDictionary{{"locale", "[a-z]{2}"}}, //constraint to say the locale must be 2 letters. You could also use something like "en-us|en-gn|ru" to specify a full list of languages
 new Utility.Handlers.DefaultRouteHandeler() //Instance of a class to handle the routing
 ));
 }
 void Application_Start(object sender, EventArgs e)
 {
 // Code that runs on application startup
 RegisterRoutes(RouteTable.Routes);
 }

I also created a seperate Class (see asp.net 4.0 web forms routing - default/wildcard route as a guide.)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Compilation;
using System.Web.Routing;
using System.Web.UI;
namespace SampleWeb.Utility.Handlers
{
 public class DefaultRouteHandeler:IRouteHandler
 {
 public IHttpHandler GetHttpHandler(RequestContext requestContext)
 {
 //Url mapping however you want here: 
 string routeURL = requestContext.RouteData.Values["url"] as string ;
 string pageUrl = "~/" + (!String.IsNullOrEmpty(routeURL)? routeURL:""); 
 var page = BuildManager.CreateInstanceFromVirtualPath(pageUrl, typeof(Page))
 as IHttpHandler;
 if (page != null)
 {
 //Set the <form>'s postback url to the route 
 var webForm = page as Page;
 if (webForm != null)
 webForm.Load += delegate
 {
 webForm.Form.Action =
 requestContext.HttpContext.Request.RawUrl;
 };
 }
 return page;
 }
 }
}

This works because when no locale is specified in the URL the default view engine for Web Forms takes over. It also works when a 2 letter locale (en? us? etc) is used. In MVC we can use an IRouteConstraint and do all kinds of checking, like making sure the locale is in a list, checking to see if the path exists, etc but in WebForms the only option for a constraint is using a RouteValueDictonary.

Now, I know there is an issue with the code as-is, default documents don't load. So http://localhost:25436/en/ does not load the default document of default.aspx, but http://localhost:25436/en/default.aspx does work. I'll leave that to you to resolve.

I tested this with sub directories and it works.

answered Feb 4, 2012 at 16:15
Sign up to request clarification or add additional context in comments.

1 Comment

How do you create a route that maps everything under {language}/{page} to {page}?
2

You can create an ASP.NET HTTP module that calls HttpContext.RewritePath to map requests from "fr/somepage.aspx" to "somepage.aspx". This technique works best with IIS 7.0 in Integrated mode because relative URLs to scripts and stylesheets will resolve to actual paths like "/fr/jquery.js", and these should be mapped to "/jquery.js" as well.

namespace SampleApp
{
 public class LocalizationModule : IHttpModule
 {
 private HashSet<string> _supportedCultures =
 new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "de", "es", "fr" };
 private string _appPath = HttpRuntime.AppDomainAppVirtualPath;
 public void Dispose()
 {
 }
 public void Init(HttpApplication application)
 {
 application.BeginRequest += this.BeginRequest;
 _appPath = HttpRuntime.AppDomainAppVirtualPath;
 if (!_appPath.EndsWith("/"))
 _appPath += "/";
 }
 private void BeginRequest(object sender, EventArgs e)
 {
 HttpContext context = ((HttpApplication)sender).Context;
 string path = context.Request.Path;
 string cultureName = this.GetCultureFromPath(ref path);
 if (cultureName != null)
 {
 Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName);
 context.RewritePath(path);
 }
 }
 private string GetCultureFromPath(ref string path)
 {
 if (path.StartsWith(_appPath, StringComparison.OrdinalIgnoreCase))
 {
 int startIndex = _appPath.Length;
 int index = path.IndexOf('/', startIndex);
 if (index > startIndex)
 {
 string cultureName = path.Substring(startIndex, index - startIndex);
 if (_supportedCultures.Contains(cultureName))
 {
 path = _appPath + path.Substring(index + 1);
 return cultureName;
 }
 }
 }
 return null;
 }
 }
}

Web.config:

<!-- IIS 7.0 Integrated mode -->
<system.webServer>
 <modules>
 <add name="LocalizationModule" type="SampleApp.LocalizationModule, SampleApp" />
 </modules>
</system.webServer>
<!-- Otherwise -->
<system.web>
 <httpModules>
 <add name="LocalizationModule" type="SampleApp.LocalizationModule, SampleApp" />
 </httpModules>
</system.web>
answered Feb 3, 2012 at 4:31

Comments

0

You can update Application_BeginRequest in Global.Asax with this codes. If global.asax does not exists, create it.

Visual Studio Project Virtual Path must be /

protected void Application_BeginRequest(object sender, EventArgs e)
{
 string file_path = Request.RawUrl.ToLower();
 char[] separator = new char[] { '/' };
 string[] parts = file_path.Split(separator, StringSplitOptions.RemoveEmptyEntries);
 if (parts.Length > 0 && parts[0] == "fr")
 {
 System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR");
 Context.RewritePath("~/" + file_path.Substring(4), true);
 }
 else
 {
 System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
 }
} 
answered Feb 3, 2012 at 20:17

Comments

0

One option is to put the texts of the aspx within <%$ Resources: My translated text %> tags. Resources tags will be resolved using a ResourceProviderFactory to get the translated value. This ResourceProviderFactory you can create yourself, doing the work of getting the translation from a resource file or database for example (Just implement IResourceProvider.GetObject()). You configure this in the web.config:

<system.web>
 <globalization resourceProviderFactoryType="CustomResourceProviderFactory" uiCulture="fr" culture="en-GB"/>
</system.web>

See: http://msdn.microsoft.com/en-us/library/fw69ke6f(v=vs.80).aspx

answered Feb 7, 2012 at 16:19

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.