I'm having trouble getting C# and JavaScript/jQuery to play nice here.
I have a knockout view model, plain old javascript object... one of its property/methods fires off an .ajax()
call, and the url parameter is built using some of its other property values (javascript variables).
This works fine when completely contained in JavaScript, but when deployed as an app to IIS, the relative pathing is hosed.
In MVC3 normally I would use something like @Url.Action
and let the server side build the address... but again, the trick is C# is unaware of the changing javascript values.
var viewModel = {
vendors: ko.observableArray([]),
count: ko.observable(10),
page: ko.observable(1),
filterText: ko.observable(""),
submit: function () {
$.ajax({
// works fine, until deploy when it is no longer a site relative URL
url: 'vendors/' + viewModel.count() + '/' + viewModel.filterText(),
// does not work, because C# is unaware of the javascript variables.
//url: @Url.Action("Vendors", "Home", new { count = viewModel.count(), filter = viewModel.filterText() })
dataType: 'json',
success: function (data) {
viewModel.vendors(data);
}
});
}
// next: // load sequence starting with (page+1 * count)
// previous: // load sequence starting with (page-1 * count)
};
ko.applyBindings(viewModel);
My question then is, how can I build the url for the ajax call using the javascript variable values (ex. count, filterText) and still map from the relative root of the application?
One possibility is to send those javascript values as request parameters:
$.ajax({
url: '@Url.Action("vendors")',
data: { count: viewModel.count(), filter: viewModel.filterText() },
dataType: 'json',
success: function (data) {
viewModel.vendors(data);
}
});
Of course this implies that you are using default routes and the parameters will simply be sent to the server either as query string parameters (if you are using GET) or as part of the POST request body. In both cases you will fetch them on the server the same way:
public ActionResult Vendors(int count, string filter)
{
...
}
Another possibility, if you absolutely insist on having some custom routes for your AJAX requests, would be to use a simple string replace:
var url = '@Url.Action("vendors", new { count = "__count__", filter = "__filterText__" })';
url = url.replace('__count__', viewModel.count())
.replace('__filter__', viewModel.filterText());
$.ajax({
url: url,
dataType: 'json',
success: function (data) {
viewModel.vendors(data);
}
});
The way we do this in my MVC 3 project is to include the following in the Master Layout:
<script type="text/javascript">
var baseSiteURL = '@Url.Content("~/")';
</script>
Then you just prepend that to your URLs in the JavaScript.
Which in your sample would read:
url: baseSiteURL + 'vendors/' + viewModel.count() + '/' + viewModel.filterText()
Darin's answer is the most solid, but it requires sending data using query string params on the ajax call.
To avoid that, I simply wrapped the @Url.Action()
method in quotes and appended the javascript values as I intended.
url: "@Url.Action("Vendors", "Home")/" + viewModel.count() + "/" + viewModel.filterText(),
Ultimately this produced the best results as it lets me keep a very clean url... Request.ApplicationPath
seemed too hackish and can technically be null... @Url.Content()
is intended for static "content" paths (ex. images, scripts)... etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With