Add second language support with root path in an existing ASP.NET WebForms site

自古美人都是妖i 提交于 2020-01-01 16:37:26

问题


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?


回答1:


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.




回答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>



回答3:


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");
    }

} 



回答4:


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



来源:https://stackoverflow.com/questions/9072088/add-second-language-support-with-root-path-in-an-existing-asp-net-webforms-site

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!