Подскажите пожалуйста почему если использовать Ajax.BeginForm
, тогда нужно использовать кнопку с типом submit для отправки формы, а если использовать с помощью jquery $.ajax
тогда можно просто button и форма всё равно отправиться. В чём разница?
Код с хелпером:
<div>
@using (Ajax.BeginForm("BookSearch", new AjaxOptions
{
UpdateTargetId = "results"
}))
{
<input type="text" name="name" />
<input type="submit" value="Поиск" />
}
<div id="results"></div>
</div>
Код с jquery:
<div>
<input id="txt" type="text" name="name" />
<input id="btn" type="button" value="Поиск" />
<div id="results"></div>
</div>
@section scripts {
<script type="text/javascript">
$('#btn').on('click', function () {
$.ajax({
type: "POST",
url: "/Home/BookSearch",
data: { "name": $('#txt').val() },
success: function (data) {
$('#results').html(data);
},
error: function (xhr) {
alert(xhr.status + 'Ошибка');
},
});
});
</script>
}
Вот так работают оба варианта, но если я в первом случае так же сделаю type у инпута, button, тогда запрос не отработает. Почему?
Давайте сначала отвлечёмся от ajax и обратимся к обычным html-формам. Если на веб-странице будет расположена веб-форма (<form></form>
), то все стандарты на html говорят о том, что отправка формы происходит по нажатии на кнопку с type=submit, которых может быть более одной. В более новых стандартах кстати упоминается, что не только кнопки могут быть submittable elements формы.
Я не видел браузеров, которые бы отклонялись от стандартов в этом плане, всё очевидно: кликнул по кнопке submit — пошла отправка формы, всё остальное не вызывает отправку формы.
Формы в asp.net mvc вы можете вставить либо вручную (<form method="...
) создав разметку, либо использовав helper для формы @Html.Form — который точно так же вставляет те же самые <form ...
.
Вот исходный код для этого хелпера:
public static MvcForm BeginForm(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues, FormMethod method, IDictionary<string, object> htmlAttributes)
{
...
return htmlHelper.FormHelper(url, method, htmlAttributes);
}
private static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes)
{
TagBuilder tagBuilder = new TagBuilder("form");
tagBuilder.MergeAttributes<string, object>(htmlAttributes);
tagBuilder.MergeAttribute("action", formAction);
tagBuilder.MergeAttribute(nameof (method), HtmlHelper.GetFormMethodString(method), true);
bool flag = htmlHelper.ViewContext.ClientValidationEnabled && !htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled;
if (flag)
tagBuilder.GenerateId(htmlHelper.ViewContext.FormIdGenerator());
htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
MvcForm mvcForm = new MvcForm(htmlHelper.ViewContext);
if (!flag)
return mvcForm;
htmlHelper.ViewContext.FormContext.FormId = tagBuilder.Attributes["id"];
return mvcForm;
}
internal static void EndForm(ViewContext viewContext)
{
viewContext.Writer.Write("</form>");
viewContext.OutputClientValidation();
viewContext.FormContext = (FormContext) null;
}
То есть никакой особой магии когда вы пишете @using(Html.BeginForm(...
нет. Я как-то отвечал на вопрос, можно ли сделать подобный хелпер самостоятельно — и в принципе, вы сами можете потренироваться в создании кастомных хелперов.
Давайте теперь вернёмся к ajax. Вы в коде пишете @using(Ajax.BeginForm(...
— и эта конструкция вызывает аналогичный код, который вписывает <form method="...
, никаких изменений.
Важно:
Давайте определимся: отправка формы срабатывает только в случае нажатия на submittable элементы!
И неважно, ajax у вас или нет.
Но видите ли, никто не запретит вам на любом элементе формы сделать вызов любой javascript-функции. Можно сделать alert()
или console.log()
, раскрасить элементы или вызвать эфффект fade. Или — вызывать this.form.submit()
Ну и даже (sic!) — сделать запрос к другому серверу. Собственно второй пример у вас именно такой: вы могли хоть onMouseOver или onKeyUp повесить вызов некоторого ajax-запроса, но навесили на событие onClick, которое вам кажется, что это событие onSubmit (для кнопок type=submit это действительно так!). Ну а что форма не отправится - ну так и не надо, действия оказываются выполненными практически одинаково.
Чисто гипотетически, я могу предположить, когда это может выстрелить, но такой случай вам в реальной практике не понадобится и так в ногу себе вряд ли получится выстрелить.
Никто не мешает вам сделать две кнопки:
Вот тут мы разбирали как раз очень похожий случай, когда было написано не:
$('#btn').on('click', function () {
$.ajax({
type: "POST",
А было что-то типа (там использовалась библиотека axios, я для наглядности привожу эквивалент):
$('#btn').on('click', function () {
$.ajax({
type: "POST",
contentType:"application/json; charset=utf-8",
И напоследок пара слов не о том, что вы спрашивали. Есть одна очень частая ошибка связанная с написанием ajax, вы её допустили во втором примере.
С учётом того, что "и так всё работает" и "форму отправлять не надо" некоторые вебмастера пишут невалидный код. По html стандарту полагается что элементы типа input и button могут находиться только внутри формы. А где она у вас? Нету вообще.
Правильно вот так:
<div>
<form ...>
<input id="txt" type="text" name="name" />
<input id="btn" type="button" value="Поиск" />
</form>
<div id="results"></div>
</div>
Насчёт того, что "ненуачо, работает же". Я не буду говорить о том, вёрстка должна быть валидной — это на совести каждого конкретного специалиста, я буду говорить о том, что зачастую люди ходят на сайты с отключенным javascript. И хотя вряд ли у человека с отключенным js будет полноценная возможность работать с сайтом, но в случае если у вас есть валидная форма с кнопкой submit — у человека остаётся шанс заполнить форму и отправить. А в случае, когда у вас input'ы и submit'ы висят в воздухе — никакого. Подумайте об этом.
Form для получения данных через перезагрузку страницы
Ajax Post для динимаческой отрисовки.
Этот вопрос был решён ранее
Виртуальный выделенный сервер (VDS) становится отличным выбором
Пытаюсь скачать видео (любое) с сервиса Sibnet, провел тестирование получения ссылки на видео-файл, и успешно получаю нормальный Url, но при этом,...
Как мне можно присвоить Action'у методы (разные) с разным кол-вом параметров и при этом параметры разные
Мне нужно распарсить строкуОна может иметь один из вот таких видов:
Как можно узнать куда был перенаправлен запрос HttpClient если для запроса указывать только запрос заголовков?