I am working on a small MVC 5 application which has a handful of views and javascript files.
The project structure is pretty standard, i.e. the normal layout for Controllers, Views, Scripts etc but I'm having problems the the AJAX calls within the scripts when I deploy to the client system - where the application is deployed within a Virtual Directory, e.g. http://host/application/
.
The issue is caused by the url parameter of the jquery ajax call not resolving consistently. For example, one script is happy with:
$.ajax({ url: 'controller/action' ....});
while another requires
$.ajax({url: '../controller/action' ....});
and most recently another requires
$.ajax({url: '../action' ....});
I can't see that I've done anything differently for these scripts (or controllers or views) so why are the urls being generated differently?
I can work around this for now but want to understand the cause of the problem so i don't get in a mess later.
I suggest you generate urls for your javascript server side (these can change if your applications is hosted in IIS as a sub app or something similar). A very helpful tool is T4MVC. Add it via nuget. Check it here.
You just save the T4 and it will generate strongly typed actions (and a lot of other neat stuff as well).
Or you can install a visual studio extension that does this for you automatically. It is called autoT4MVC
What you do then, is create javascript object in razor and have all URLs generated. So if you change your controllers or actions, you will have compile time errors.
var myUrls = {
get: '@Url.Action(MVC.MyController.Get())',
add: '@Url.Action(MVC.MyController.Add())'
}
Then use it like this:
$.ajax({url: myUrls.get});
And all your url troubles are solved =)
The main problem here is that people are suggesting to use things like @Url.Action and @Html.ActionLink which are not going to work - ever.
Reason being is that as the OP has said, the javascript is held in .js files. IIS will serve .js files via the StaticFileHandler, unless you are using some other handler defined by your web.config file. The out-of-the-box SFH does not live in the execution chain of MVC, it's not for serving up of dynamic content, hence its name. Therefore you can't put MVC @ directives or calls in javascript files or in css files. An @ in css is legal and will be processed but not by the MVC/ASP.NET stack.
T4MVC - good tool, but probably overkill for this problem.
Back to the OP though, what's the pattern here? A call using the $.ajax(...) syntax should not need any manipulation of the url parameter. Doing so would break the cacheability of the script. It's not the script itself that needs fixing.
When I get problems like this, I tend to ask myself a few questions: Are all of these scripts in the same directory?
Are they all called from the same MVC View path structure? or are some views more nested than others?
Is the behaviour different depending on the script being included in a partial or "full" view?
One of these usually flags up the problem, but if there's no time because of a looming deadline, I usually opt for using a path to the required endpoint in my .js file in a format IIS will be able to resolve. You hardcoded "/Letter/GetRecpient" so why not hardcode "~/Letter/GetRecipient"? Using the "~" means IIS resolves the url correctly, even when the file is served via the SFH ;)
So what happens if you deploy this solution to a local IIS which you have complete control over? Try and deploy it to a virtual directory and also to a root directory and see what happens. There's a slight smell of IIS misconfig about your problem. Only slight though