Создание относительных URL-адресов для приложения MVC с использованием JavaScript
У меня возникли проблемы с получением С# и JavaScript/jQuery, чтобы играть здесь хорошо.
У меня есть модель представления нокаута, простой старый объект javascript... один из его свойств/методов запускает вызов .ajax()
, а параметр url построен с использованием некоторых других его значений свойств (переменные javascript).
Это отлично работает, когда полностью содержится в JavaScript, но при развертывании в качестве приложения для IIS относительная траектория запускается.
В MVC3 я обычно использовал бы что-то вроде @Url.Action
и позволял стороне сервера строить адрес... но опять же, трюк С# не знает об изменениях значений JavaScript.
Код:
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);
Вопрос:
Тогда мой вопрос: как я могу построить url для вызова ajax с использованием значений переменной javascript (например, count, filterText) и по-прежнему отображать от относительного корня приложения?
Ответы
Ответ 1
Одна возможность отправить эти значения javascript в качестве параметров запроса:
$.ajax({
url: '@Url.Action("vendors")',
data: { count: viewModel.count(), filter: viewModel.filterText() },
dataType: 'json',
success: function (data) {
viewModel.vendors(data);
}
});
Конечно, это означает, что вы используете маршруты по умолчанию, и параметры просто будут отправляться на сервер либо в виде параметров строки запроса (если вы используете GET), либо как часть тела запроса POST. В обоих случаях вы получите их на сервере одинаково:
public ActionResult Vendors(int count, string filter)
{
...
}
Другая возможность, если вы абсолютно настаиваете на том, чтобы иметь некоторые пользовательские маршруты для ваших запросов AJAX, будет использовать замену простой строки:
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);
}
});
Ответ 2
То, как мы это делаем в моем проекте MVC 3, должно включать следующее в макет основного файла:
<script type="text/javascript">
var baseSiteURL = '@Url.Content("~/")';
</script>
Затем вы просто добавляете это к своим URL-адресам в JavaScript.
Что в вашем примере будет читать:
url: baseSiteURL + 'vendors/' + viewModel.count() + '/' + viewModel.filterText()
Ответ 3
Даринский ответ является наиболее надежным, но он требует отправки данных с использованием параметров строки запроса на вызов ajax.
Чтобы этого избежать, я просто обернул метод @Url.Action()
в кавычки и добавил значения javascript, как я предполагал.
url: "@Url.Action("Vendors", "Home")/" + viewModel.count() + "/" + viewModel.filterText(),
В конечном итоге это дало наилучшие результаты, так как это позволило мне сохранить очень чистый URL... Request.ApplicationPath
казался слишком хакерским и может технически быть нулевым... @Url.Content()
предназначен для статических "контентов" путей (например, изображений, скрипты)... и т.д.