Add subdirectory for locale based URL existing ASP.NET website, resolve relative paths correctly - asp.net

Existing ASP.NET (MVC and webforms hybrid) website displays translated content. The language is based on a cookie that stores the user's preference. There is no change in the URL when the user changes the setting. The content is reloaded in the preferred language. For SEO, the locale should be included in the URL ( support.google.com/webmasters/answer/182192?hl=en).
I've tried the following:
1) Use URL Rewrite Module: (http://www.iis.net/learn/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables)
Issues:
- All hyperlinks and redirects still point to the old URL without the locale.
- Complex outbound rules required based on the folder structure and usage (mixture of absolute paths and relative paths e.g. ../, ~/, /).
- Also need to disable static compression as per documentation
- Performance considerations due to large size of Html.
- Postback results in runtime exceptions due to issue in the relative path rewrite.
- Paths defined in script files (ajax loading etc) are a huge challenge
- Base tag does not work as expected, because the Rewrite Module seems to append ../ (http://www.iis.net/learn/extensions/url-rewrite-module/url-rewriting-for-aspnet-web-forms#Using_tilda)
2) IIS 7.5 Virtual Directory: Create Virtual Directory for each language and point it to the root. i.e. www.example.com is the root and www.example.com/fr-ca/ is a virtual directory mapped back to the root
Issues:
- Runtime exception in config file saying that the virtual directory needs to be converted to application
- Converting it to application gives 500.19 error due to duplicate entries in the web config (since the virtual directory is pointing back to the root)
- I tried moving the root to another subdirectory (i.e. have a physical directory for each language) to avoid web config conflicts, but that is resulting in some sort of "kernel" error. Also, this would mean changing the physical structure of the application, and also address routing issues
3) Using sub-domains:
I have also considered using sub-domains and hosting the application independently for each language, but this has a lot of drawbacks, including having to address scalability, single sign on, cookies, domain specific stuff like analytics etc.
So what is the least painful way to include a language sub-directory in the URL, and make all links relative to that sub-directory?
Note: The site contains a mixture of absolute paths and relative paths e.g. (../, ~/, /) sometimes used in conjunction with ResolveClientUrl, ResolveUrl

In the end, we went with option 2, with the below steps:
Create a new folder, deploy a copy of the application to the new folder. The new folder should be in a different directory from the root application.
Create a new virtual application* (not virtual directory) under the root application; 1 for each new language, pointing to the new folder. (If the need arises in the future, any of the virtual applications can point a different folder customized for that specific language)
In the new folder, remove the modules and handlers sections in the system.webServer section of the web.config file (they will be inherited from the parent web.config)
If you are using SQL session state, you will need to specify a custom Application Name in the web.config, and modify TempGetAppID stored procedure so that the Application Name is the same across all the virtual applications. See the following (http://blogs.msdn.com/b/toddca/archive/2007/01/25/sharing-asp-net-session-state-across-applications.aspx)
Hopefully, all the links are resolved on the server side using Url.Content (MVC) or ResolveUrl (webforms). If not, they need to be fixed. Any paths specified in javascript would not automatically resolve to the virtual application either (they would still be resolved to root application)
Test the heck out of it. Each and every link. (A tool like ScreamingFrog may help to make sure that no 404s are returned, methinks. But it wouldn't solve HTTP POST)
Note that depending on custom error handling, and any existing URL rewrite rules, the steps maybe different.
Summary: option 1 (URL Rewrite) is totally impractical. Option 2 (sub-directory) is the most practical solution, however it is not quite as straightforward as it should've been.

Related

Select correct path for files from App Under IIS

I have inherited an .NET app that is hosted on IIS. Previously it would have been its own site within IIS. Now in my Dev environment I have to run it under Default WebSite (in Production it will still run as its own site.
So in Dev I was having problems loading scripts and css files - so I right click Default Web Site in Dev and Add Application - call the new App - MyApp and point to the physical location on disk.
So previously style sheets would have been loaded:
href="/css/folder/mystylesheet.css"
and js files:
src="/jslib/jquery-1.9.1.js"
which worked fine when the application is hosted as its own site within IIS and which still needs to happen in Production (just not in my dev) So in dev I need to change the css and js as below:
href="~/css/folder/mystylesheet.css" (note ~ added)
src="./jslib/jquery-1.9.1.js" (note . added)
and now the js and css files for MyApp under Default website are loaded. However is there something simple I can do in IIS or webconfig to switch this behaviour on/off easily in Dev/Production rather than editing all the places where scripts and css files are loaded - as I know at some point a file will get checked into Production with the path incorrect
The other problem is there is numerous links throughout the site that are all relative so were /Link/Page.aspx which now break in MyApp hosted under Default Website
EDIT
Looking at the answer below from this question
In ASP.NET, many times you will need to use a tilde (~) to get the application's root directory, so your paths would look like ~/stylesheets/main.css
When you specify a path that starts with / you are indicating the server root so if you have you site in a virtual directory, it will not be taken into account, but if the site is hosted as the default site, the path will qualify:
Example: server named foo.net with site hosted in a virtual directory named app /stylesheet will translate to foo.net/stylesheet not foo.net/app/stylesheet
All my paths start with / (i.e going to server root) - what I need to figure out is there something I could add to web.config that for Dev would let me specify The Virtual Application MyApp needs to be taken into account (just for Dev - this could then be removed in Web Transform for Production web.config file
The short answer is no, there is not one single place where you can deal with the site's location. That's because there are many possible outcomes that you might want, including:
site served from IIS root folder and accessed at root of domain (or not)
site served from IIS subfolder and accessed at same path (or not)
IIS rewrite rules (inbound and outbound), which adds layers of mapping between public and private paths
sites mapping to subdomains, DNS wildcard mapping (where requests are distinguished by hostname), etc
sites mapping to child applications, inheriting or not inheriting rewrite rules (and other configuration)
all of the above
At the same time, there are many places where you interface with paths:
internal physical paths, usually for disk access, and usually requiring mapping of virtual path
internal virtual paths
internal ASP.NET paths, like virtual paths except that they can be app-relative (using ~), which IIS doesn't always recognize
public-facing paths
all of the above can be relative or absolute
So yeah, it's a mess.
For your case, the simplest thing is probably to make the development environment mirror the production environment. Unless you're moving the live site, delegating all the path references to a configuration-aware function is probably more trouble than it's worth.
The ~ is added to make the path relative to root directory. One suggestion is to move the folder up a few levels.or down a few levels to make sure your project is in the correct directory. Hope this works

ASP domain and files

I have no idea about asp, but I had to do some modifications in a web site, an easy modification. So I downloaded all files from server and I did all the modifications in Visual Studio 2013. Then I tested each page in the local host and it was perfect.
When I uploaded the files, I created a folder called "development", to tested it before I changed in the real site, so, my real site is for example "www.realsite.com" and my new folder is inside, with all the file, so I write in my url "www.realsite.com/development" and it shows the page, but not the one I had modified, but the real site. I want to know if there is a config file to change the path of the development site to see the changes I make and not the real site, because if I click in the development site a menu, it sends me to the page in the real site.
I hope you can help me with this,
Thank you!
PS: Do you know what is the meaning of "~/" in for example : src="~/folder/folder/xxxx.xx"
This is because the URLs in the project are using absolute paths, all pointing to the root. If they were using relative paths, moving the project to a folder and running it from there would work just file.
The difference:
... <-- absolute, note the leading slash
... <-- relative, no leading slash
Well, it depends on what kind of changes you are referring to, what kind of ASP.net site (or application).
The ~/ in ASP.Net means "path from application root". A subfolder (the new folder you created) in an existing application is just that, a folder. It is not "another application root". So if the existing code refers to "its root", e.g. where it uses ~/, it's probably not what you would expect..
Again, not enough info, but if you experience more unexpected behavior, it will probably be because of this (application scope).
Ref: ASP.NET Web Project Paths
ASP.NET includes the Web application root operator (~), which you can use when specifying a path in server controls. ASP.NET resolves the ~ operator to the root of the current application.
Hth...

Is default.aspx a .Net equivalent to an "index" file?

I have just started to work for a new company as a web developer, previous research has led me to find out their site is built in asp.net which isn't a problem, I just dont have any experience in this, all my experience is html, css, php and Js.
Upon gaining access via ftp, I noticed there is no traditional index.bla, so I went to the homepage on their website, and in stead of index, it was default.aspx.
Is this "default.aspx" file the .Net replacement / equivalent of an index file, and does it work in the same way?
Yes. In IIS (the web server) you can specify which files will be shown when a directory (like the root, when accessed through http://www.sitename.tld/) is requested.
You can configure which files will be shown and in what order. Like here (IIS 6):
So when a user requests a directory on that site, IIS will search for "Default.htm", if that isn't found it'll look for "Default.asp" and so on. If none of the default documents are found, you will either see the directory's contents (disabled by default) or an error saying you can't see the directory's contents.
In Apache this is set through the DirectoryIndex directive in httpd.conf.
Yes. index is an arbitrary name that Apache defaults to. The index page can be named anything, and with IIS it is usually default.

Application-Relative URLs

I've just create a new ASP.NET Web Application in VS2010, and set it up as an application in IIS7.
Not sure if this is relevant, but the code physically resides in the \myserver\projects\epeui\epe folder (the projects folder is the root of my default web site). The application hangs off the root of this machine's default web site: http://myserver/epe/. And is configured as an application in IIS.
Normally, I used URLs that are relative to the application root, so my CSS files are in /styles/, my images are in /images/ and my JavaScript files are in /scripts/.
Given that the application is configured as such in IIS, to access my logo, I would expect to use /images/mylogo.png, an application-relative URL.
However, this doesn't work for this site; instead I need to use parent paths (../images/mylogo.png) or URLs relative to the default web site (/epe/images/mylogo.png). Neither of these are very good for portability reasons.
I've also tried using the tilde to use URLs that are supposedly relative to the virtual path (i.e. the application root) = ~/images/mylogo.png
I swear I've done this a thousand times before but clearly screwing up somewhere... Any suggestions?
Can someone at least confirm that, for a standard application in IIS, /mypage.html should reference http://myserver/myapp/mypage.html and not http://myserver/mypage.html?
/mypage.html is going to map to the root http://myserver/mypage.html, this is correct behavior
The ~ on a SERVER SIDE control will map to the application root (so <asp:HyperLink NavigateUrl="~/mypage.html"...> will map to http://myserver/myapp/mypage.html
I have, in the past, especially with css and javascript files had to use <%= Request.ApplicationPath %>/myPage.html. Sometimes it's good to define that as a global variable in the global.asax.cs so you can use it all over. Request.ApplicationPath in your instance will be "/myapp"
I've struggled with this a lot too.

ASP.NET: external custom config file in a virtual directory - how to?

I know that there at least two approaches to leverage the web.config file:
using the configSource attribute which was introduced in .NET 2.0 - here is a good blog entry about it.
The file attribute of the appSettings tag which lets you point to an external file with a relative path. Described in the MSDN documentation on the appSettings element.
Now, my problem is that both approaches work well only for physical paths. But I need to address a config file which is in a virtual directory.
Which other method could I use to put my config resources in a virtual directory?
Note: I want to do it this way, because I have multiple instances of my web application on the same server (and that on many servers). To keep deployment easy and clean, I want to keep one directory for all the files (aspx, ascx, images, css, js etc.) and point the web apps in IIS for different customers (=domains, https etc.) to this single directory. In every IIS web I would have a virtual directory called "custom" which points to a different folder for each web.
Update: I'd like to point out that this virtual directory "custom" is not suited to contain an inherited web.config - that web.config would be valid only for the custom folder which doesn't contain aspx/ascx files.
I have the same scenario and after reading you post I realised that asp.net won't let you do this for various security reasons.
Therefore I turned to the OS to find an equivalent to the Linux soft link function which in turn led me to the Junction utility from sysinternals. This can create a directory that is actually any other directory on that volume and asp.net can't tell the difference and so happy loads the config sections that are not actually in a subdirectory of you website. Works for me :)
Virtual Directories can be set as applications, and you can just place another web.config there.
It will inherit any changes from the parent config, and you can add custom settings in it.
I was looking to do the same thing but it did not work, so I decided to do the opposite, as you know the web.config can be inherited, so I pointed IIS to a folder containing the client config (connection string, file path etc) files and the website files i put them on a virtual directory with the rest of the webconfig (where it load dll and other application files needed)
So basically i can use the website files to multple clients and the clients with their own Database connection string and other specific client settings.

Resources