Page Names: ASP.Net Web Forms Site, Deploying Multiple Languages - asp.net

Sorry about the title, couldn't think of a good way to describe it briefly. On to the question...
I've written a site in ASP.NET using web forms and have used resource files to handle static text for multiple languages and our Database is setup for multiple languages, so everything is localized. It's as easy as switching culture and uiCulture in web.config to switch the site between French and English.
However, the french site has to be deployed with folders and page names translated to French. Example, http://www.product.com/accessories/category.aspx?id=111 needs to be http://www.produit.com/accesoires/categories.aspx?id=111
Aside from making copies of all the ASPX pages (not the code behinds), changing their names to the French equivalent and leaving their code-behind to point to the original aspx.cs... what is the preferred/proper/nice way to do this?
Please note: URLs referenced in the pages/code themselves are built dynamically so they will be localized as well.
Thank you!

Have you tried having a look at routing in asp.net? http://www.hanselman.com/blog/OneASPNETSneakPeekElegantWebFormsAndSnowballsInHell.aspx

I can't use routing as the server is running .NET 2.0 and routing wasn't introduced into the framework until 3.5 SP1. So I had to resort to URL rewriting.
In web.config I added:
<system.web>
<httpModules>
<add name="UrlRewriter" type="Utilities.UrlRewriter, MyProject"/>
...
<system.webServer>
<modules>
<add name="UrlRewriter" type="Utilities.UrlRewriter, MyProject"/>
I then created UrlRewriter which inherits IHttpModule, and in the Init method added a handler for HttpApplication.BeginRequest.
In BeginRequest I inspect the URL and replace localized folder names and page names with their English equivalent. For e.g. /mysite.com/a-propos-de-nous/ is converted to /mysite.com/about-us/ but the user still sees the French URL in their browser.
There's a bit of checking to do to convert the URL but it works well enough and the checking/replacing isn't horrid.
I have a couple quirks to figure out, if the URL comes in as /mysite.com/a-propos-de-nous (notice the missing '/' at the end) the rewrite works, but the URL in the browser address bar gets changed to /mysite.com/about-us which is not desired.
If any one has any additional thoughts, comments, or experience in localizing URLs please add to the thread.
[Edit - Feb. 28, 2013] - RE: lack of trailing slash in URL entered in browser
Adding this to make this more complete in case someone stumbles upon it.
The problem here is that IIS adds a courtesy trailing slash and this creates a redirect. To handle this case what I've done here is to inspect the URL and determine if it contains a page/file at the end of the URL. I use the following in my Url rewrite code:
void UrlRewriter_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
... // other rewrite code here
string lastSegment = app.Request.Url.Segments[app.Request.Url.Segments.Length - 1];
string extension = System.IO.Path.GetExtension(lastSegment);
// no extension, must be a directory/folder
if (string.IsNullOrEmpty(extension))
{
if (!sendTo.EndsWith("/"))
sendTo = sendTo + "/";
}
app.Context.RewritePath(sendTo);
}

Related

automatically rewrite URLs in ASP.NET

I use VS2010,C# to develop an ASP.NET web site, my customers want me to have their pages like this:
mysite.com/customer (in fact they call mysite/customer/default.aspx)
so I've manually created several folders for each customer, and inserted a default.aspx file in the folder so that users can view customer page by typing mysite.com/customer
is there a better way for performing this scenario? I don't want to have mysite.com/customer1.aspx, I want to have mysite.com/customer1, is there anyway that I can remove folders (and their containing default.aspx files) and generate something automatic using my customers database?
should I use URL rewriting? is there anyway that I can create page mysite.com/customer1.aspx, and users can view it by typing mysite.com/customer1?
I think it is possible to rewrite URLs in web.config, but I don't want to do it manually in web.config as my pages would increase in a daily basis
thanks
If you really really wanted to do this in code and not in the config you can rewrite the path yourself in the Application_BeginRequest using the RewritePath method of HttpContext
For example (and this is a very simplified example), if your aspx was in a subfolder the root it could go something like this:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request.Path.StartsWith("/customer"))
HttpContext.Current.RewritePath("/customer/whatever.aspx");
}
Note: This ignores any query string which must be extracted and re-added and if you want it to be case-insensitive, you've have to handle that too.
Config-based URL rewrite is your best option. Look here: http://msdn.microsoft.com/en-us/library/ms972974.aspx . The rewriting is pattern based, so what you are describing (mysite.com/customer1.aspx to mysite.com/customer1) is possible.
ASP.NET Routing is the best way to do this, http://msdn.microsoft.com/en-us/library/cc668201.aspx
I've written a Navigation project that will help you as well, http://navigation.codeplex.com/ - if you're interested in this and need any help, let me know.
If you are (actually) willing to try url rewriting and such why not try ASP.net 4 Web Pages?
You can do Razor syntax in C# (cshtml) or VB (vbhtml).
You gain "pretty urls" by default (no configuration nor global.asax routing)
You can use Visual Studio or even WebMatrix
Possible challenges:
the (new) syntax - but its not that difficult - mostly # instead of <%=..%>
if you're more comfortable with ASP.Net controls, then it may prove to be more difficult than much simpler...

How to get Umbraco to handle requests for non .aspx files (IIS integrated pipeline mode)?

I'm trying to get the 301 URL Tracker package for Umbraco to work to my likings.
My goal is to be able to map the old URLs (from another CMS) to the new Umbraco URLs. In my specific situation, the old site is PHP based and therefore use the .php file extension (http://example.net/test.php -> http://example.net/test/) - but it could be any non .aspx extension (asp, png and so on). The problem is that Umbraco is not handling request for .php files. It works perfectly for .aspx and directories (extensionless URLs).
I have tried various things for getting this to work. Before I go any further, I should note that the Application Pool is in integrated mode and .NET 4.0.
I kind of got it to work by defining a custom error in the web.config:
<customErrors defaultRedirect="not-exists.aspx" />
This triggers the handlers defined in NotFoundHandlers in the Umbraco config file 404handlers.config. But has the side effect of returning a 302 Found header, before the 301 URL Tracker kicks in and handles the 301 redirect. And this is just a big SEO "no no".
I then tried to explicitly create a HTTP handler module for .php files. I successfully got the System.Web.UI.PageHandlerFactory module to handle the request for the .php file. But this does not invoke any of the NotFoundHandlers in Umbraco.
As I understand the integrated pipeline in IIS 7, all the modules registered should try to handle the request (http://stackoverflow.com/questions/3765317/how-to-catch-non-aspx-files-with-a-http-module). But perhaps somebody can enlighten me on this subject?
Others are also experiencing the difficulties in getting this configuration to work: http://our.umbraco.org/projects/developer-tools/301-moved-permanently/feedback/7271-when-the-old-pages-are-not-from-umbraco
What am I missing in getting Umbraco to handle request for non .aspx files in integrated pipeline mode?
If you are already running under Integrated Pipeline mode then the included UrlRewriting.net module should pick up requests automatically.
Simply add:
<add name="phptoaspx"
virtualUrl="^~/(.*).php"
rewriteUrlParameter="ExcludeFromClientQueryString"
destinationUrl="/$1.aspx"
ignoreCase="true" />
to your /config/UrlRewriting.config file, and all should be well.
P.S. You should not be using a customError handler to handle SEO 301/302'ing content. This can be a massive headache in terms of maintainability - please trust me on this, I tried this once when I was a junior .NET dev!
I am not familiar with Umbraco, but believe this is what you are looking for http://blogs.iis.net/ruslany/archive/2008/09/30/wildcard-script-mapping-and-iis-7-integrated-pipeline.aspx
Of course you'll have to add your own rewrite rules... so this only gets you half way.

Possible bug/issue in ASP.NET 3.5 related to Request.RawUrl property

I posted a query for 301-redirect using ASP.NET 3.5 here:
Redirecting default.aspx to root virtual directory
Based on the replies I got there, I realized there might be a bug in ASP.NET's Request.RawUrl method which is unable to return the actual raw url (without /default.aspx) when being used in a sub-directory, i.e. the /default.aspx page is inside a subdirectory.
Can someone please shed some light on this possible bug?
Thanks,
Asif
i found a good explanation here
http://codeasp.net/blogs/vivek_iit/microsoft-net/873/301-redirect-from-default-aspx-to-site-root
Thanks
If you suspect this is a bug, then the place to go is Microsoft Connect, where you can report and discuss the bug directly with Microsoft.
Edit: I was able to reproduce the look per your comments.
I was unable to reproduce the infinite loop, however. I injected code into the Global.asax Application_BeginRequest handler of a web application and got the expected behavior of a single redirect.
There are other, and IMO much better, options for handling global redirect rules. On IIS7, I use the URL Rewrite module to configure rewrite rules in IIS. You can read more about it and download it here: http://www.iis.net/download/urlrewrite. The appeal of a solution such as this is that you can customize and update your rewrite rules without recompiling the application.
Edit: I was able to retrieve the raw URL without the default.aspx (after the redirect) by using instead:
Request.ServerVariables["CACHE_URL"]
It's worth a shot.
Have you looked at the IIS settings for your virtual directory? If there is a default document set to default.aspx then this will explain the infinite loop that you are experiencing. You are telling the website to redirect to the virtual directory without the "default.aspx" and IIS is detecting this on the next request and putting it back in ad infinitum.
Right click your virtual directory, select Properties and then the Documents tab. If default.aspx is in the list then that is what you will get. The Url of the request will be passed to the ASP.NET worker process as /folder/default.aspx rather than /folder/
This is not a bug. If IIS didn't do this, you would get a page not found error.
Sounds to me like you need to investigate URL rewriting: http://msdn.microsoft.com/en-us/library/ms972974.aspx

Global.asax not firing for .aspx pages in IIS7

We run a link redirection service which can handle links thrown at it in various formats. One of these formats is to append the destination URL to the end of the link, for example
http://url.fwd/abcd/http://www.mydomain.com/page.aspx
This was working on a Windows Server 2003 / IIS6 box for the last two years, but now we're trying to move to a Windows Server 2008 / IIS7 setup and its not working anymore.
I've read about the problem with colons in the URL but it doesn't affect pages not ending in '.aspx'. For instance,
http://url.fwd/abcd/http://www.mydomain.com/page.php
would redirect fine.
http://url.fwd/abcd/http//www.mydomain.com/page.aspx
also works fine (note the lack of a second colon). Despite being the wrong URL, it does get handled by our URL forwarding system, which uses a custom 404 page. On the old system, we had a similar problem, so a method was written in Global.asax > Application_Error specifically to handle the '.aspx' case, and it worked fine.
On our new server, the Application_Error never gets thrown in Global.asax. Instead, I get a System.NotSupportedException - "The given path's format is not supported". This System.NotSupportedException is the exact case we handle in the Global.asax page, so it's definitely not being fired.
I've changed the registry keys indicated in several forum posts,
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET VerificationCompatibility=1
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP|Parameters AllowRestrictedChars=1
I've tried changing the Handler Mappings settings for .aspx.
I've tried setting the App pool to use classic mode instead of integrated, but this causes a completely different error where static content such as images and CSS do not display at all. I've checked that static content is enabled in the windows features, and it is.
Under classic mode, the '.aspx' request throws two Bad Request errors with absolutely no information whatsoever. The code of the error page I get is literally
Bad Request<html><body>Bad Request</body></html>
UPDATE: I've changed the static file Handler Mapping to the form found in this page
http://improve.dk/blog/2006/12/11/making-url-rewriting-on-iis7-work-like-iis6
However, as the author rightly points out, this is a hack and not the correct way of doing things under IIS7. It also only fixes the static file problem in classic mode. '.aspx' pages still throw an error under classic mode.
Any thoughts or input would be greatly appreciated at this point.
IIS 7 Solution
The easy solution in IIS 7 is to add a setting in your web.config file to tell IIS to process all requests through your Global.asax events. Just add or change this section in your web.config to enable requests:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
In my case, I was publish my site in production and I miss copy to server App_global.asax.compiled file. For this reason was not fire the Events inside Global.asax.
Hope anyelse help this tips, I lost 8 hours seeking.

How to 301 redirect

Ok, I need to know how to do a redirect (where to put the code or specify the setting). We're redirecting from one app to another after we've moved the app.
So for example, if a user goes to existing.example.com/archive/
we want to redirect any requests that contain old.example.com to new.example.com. The rest in the url stays the same. So for example /archive/ is one example so we'd want to redirect them to the new location of this app which is new.example.com/archive/
I need to figure out how to check to see if the incoming URL to our existing site has existing.example.com, and if so replace that part only with the new new.example.com and keep the rest of what's in the url
I know you can do this in IIS 7 or programmatically. I guess I'm not understanding how to do this in either situation. I installed the IIS7 Rewrite plugin and ok fine, but here's what I don't get:
Pattern:
RedirectURL:
I don't see how in that interface I am able to match the existing.example.com and then what to put in the RedirectURL because I want to put the entire URL with only that existing.example.com changed to new.example.com in for the REdirectURL... and I don't see how I'd do this in IIS 7.
Here's a post describing how to match one domain and redirect to another with everything else in tact using the IIS7 URL Rewrite add-in: http://weblogs.asp.net/owscott/archive/2009/11/27/iis-url-rewrite-rewriting-non-www-to-www.aspx
You don't need any complicated rewriting stuff to do such a trivial redirect, it's a basic web server feature. In IIS7 you can now choose not to install it (from World Wide Web Services->Common HTTP Features->HTTP Redirection), but it would be unusual to do so.
Edit the ‘Bindings’ of the main web site in IIS Manager so that it only responds to the ‘Host name:’ new.example.com, then create a new web site bound to host name old.example.com. For this site hit the ‘HTTP Redirect’ option and ‘Redirect requests to this destination:’ http://new.example.com/ with ‘Status code:’ 301.
In config XML terms:
<system.webServer>
<httpRedirect enabled="true" destination="http://new.example.com/" httpResponseStatus="Permanent" />
</system.webServer>
In your site's global.asax.cs file you can redirect from BeginRequest as follows. You can write the routine to replace the domain names as needed with regex or string.replace() or whatever you prefer.
protected void Application_BeginRequest(Object sender, EventArgs e){
...parse urls...
Response.Redirect(myNewPath)
}
For asp.net applications, I've had good experience with urlrewriting.net, a free component where you can configure redirects in your web.config. It allows you to enter regular expressions and specify the new URL with back references, e.g. something like this (untested):
<add name="newdomain" virtualUrl="^http\://old.example.com/(.*)$"
rewriteUrlParameter="ExcludeFromClientQueryString"
destinationUrl="http://new.example.com/$1"
redirect="Domain"
redirectMode="Permanent"
ignoreCase="true" />
Drawback: This needs to be configured for every ASP.NET application (and you might need to reconfigure IIS to route everything through asp.net, or it might only work for .aspx files). If you want to redirect your complete domain, you are probably better off doing this on IIS level rather than on application level. For this, however, you might get better help on http://serverfault.com, which is where the sysadmins reside...

Resources