I have a bizarre routing issue with my ASP.NET MVC project that I hope you guys can help me with.
Overall everything works fine when I run the project off my localhost or run it on the server while it's deployed directly at http://myServerName
. The problems start when I deploy the application to various enviornments on the server located under different virtual directories. For example: http://myServerName/QaEnviornment
or http://myServerName/TestEnviornment
The problem is that all Javascript calls to application URLs ignore my environment virtual directories and fail. For example on my QA server whenever I have to make an Ajax call I take a standard approach such as:
var myUrl = '/ControllerName/ActionMethodName/'
$.ajax({url:myUrl,success:function(){Do stuff} })
Because my application is deployed on http://myServerName/QaEnviornment
, when rendered I expect myUrl to be http://myServerName/QaEnviornment/ControllerName/ActionMethodName
. Instead it comes back as http://myServerName/ControllerName/ActionMethodName
and ofcourse fails.
To get around this for now I declared a global Javascript variable that contains the environment folder name and when I build URLs for javascript calls I have to remember to ALWAYS construct them as var myUrl = myGlobalFolderVar + '/ControllerName/ActionMethodName/'
Using a global JavaScript variable to get around this issue seems as a bad solution to me. Is there anything I can do to get routing to work properly so whenever JavaScript calls are made whatever subfolder the application is running under is always included in the URL ?
Instead of always having to remember to construct them correctly, make a helper function that you call to create your URLs
function CreateUrl(string path){
return myGlobalFolderVar + path;
}
To answer your second question, not really. Routing is not aware of what made the request and you cannot always rely on the X-Http-RequestedWith
header to base that decision on. In addition, your site application root is not at the domain root, therefore routing would only kick in when it visits your application. The only other way I am aware of is to have MVC actually generate the Url for you (var url = '@Url.RouteUrl(params)';
) but this does not help at all when you have your JavaScript in a single or a few .js files.
EDIT
The above function is a JavaScript function that can sit anywhere you would like in your application, including external JS files. As for setting your myGlobalFolderVar, there are a few ways you could set this.
1.Actually hard code the variable in your external JS file.
var myGlobalFolderVar = 'TestEnviornment';
This is hard however if you are deploying to several different testing servers.
2.If you are using web.config transformations, you could add an AppSettings key/value pair in your web.config transformations depending on build type. Then, using that value, set your global Javascript variable in your master page layout/views.
<appSettings xdt:Transform="Replace">
<add key="folderLocation" value="TestEnvironment" />
</appSettings>
In your external JS file
//this makes it a site wide/global variable in any place you
//include your external JS file
var myGlobalFolderVar = '';
And in your master view
<script type="text/javascript">
myGlobalFolderVar = '@ConfigurationManager.AppSettings["folderLocation"]'
</script>
3.Same as number two, but use the URL helpers to figure out what the path to your application is in your master view instead of using the web.config transformations
<script type="text/javascript">
myGlobalFolderVar = '@Url.Content("~/")'
</script>
The basic idea is using .NET to figure out where it lives and set a global JavaScript variable with that path information. Then, in conjunction with the helper JavaScript function provided at the top of this answer, you can correctly generate paths as needed throughout your application - regardless of path depth, deployment location or any other deployment type concerns.
var myUrl = CreateUrl('/ControllerName/ActionMethodName/');
$.ajax({url:myUrl,success:function(){Do stuff} });