如何使用 JavaScript 而不是提交按钮发布 ASP.NET MVC Ajax 表单

Posted

技术标签:

【中文标题】如何使用 JavaScript 而不是提交按钮发布 ASP.NET MVC Ajax 表单【英文标题】:How to post ASP.NET MVC Ajax form using JavaScript rather than submit button 【发布时间】:2010-11-21 07:02:53 【问题描述】:

我有一个使用 Ajax.BeginForm 创建的简单表单:

<% using (Ajax.BeginForm("Update", "Description", new  id = Model.Id ,
     new AjaxOptions
     
       UpdateTargetId = "DescriptionDiv",
       HttpMethod = "post"
     ,new id ='AjaxForm' )) %>
Description:
<%= html.TextBox("Description", Model.Description) %><br />
<input type="submit" value="save" />
<% %>

控制器已连接并返回更新DescriptionDiv 的局部视图。这一切都很好。

现在我希望能够在没有提交按钮的情况下提交此表单(通过单击链接或图像或其他方式)。不幸的是,这个小 jQuery sn-p 不能完成这项工作:

$('form#AjaxForm').submit();

它确实提交了表单,但是(我想这并不奇怪)是常规的回发,而不是 Ajax 回发。

为了简单起见,上面的 jQuery 是这样连接的:

<a href="#" onclick="$('form#AjaxForm').submit(); return false;">submit</a>

表单的 onsubmit 正在使用 Sys.Mvc.AsyncForm.handleSubmit() 但 jQuery 提交似乎绕过了这个。

PS。我正在寻找这种特殊方法的解决方案。我知道如何使用普通表单并使用 AJAX+jQuery 发布它。不过我对这个特殊的解决方案很感兴趣。

【问题讨论】:

【参考方案1】:

我将假设您在选择器周围缺少引号只是一个转录错误,但无论如何您都应该检查它。另外,我看不到您实际上在哪里给表格一个ID。通常您使用 htmlAttributes 参数执行此操作。我没有看到您使用具有它的签名。但是,如果表单完全提交,这可能是转录错误。

如果选择器和 id 不是问题,我怀疑这可能是因为当您使用 Ajax BeginForm 扩展时,单击处理程序是通过标记添加的。您可以尝试使用 $('form').trigger('submit') 或者在最坏的情况下,让锚点上的单击处理程序在表单中创建一个隐藏的提交按钮并单击它。或者甚至使用纯 jQuery 创建自己的 ajax 提交(这可能是我会做的)。

最后,您应该意识到,通过替换提交按钮,对于没有启用 javascript 的人来说,您将完全打破这一点。解决这个问题的方法是使用 noscript 标签隐藏一个按钮,并在服务器上处理 AJAX 和非 AJAX 帖子。

顺便说一句,微软不接受标准做法,通过 javascript 添加处理程序而不是通过标记。这使您的 javascript 保持在一个位置,因此您可以更轻松地查看表单上发生的情况。这是我将如何使用触发机制的示例。

  $(function() 
      $('form#ajaxForm').find('a.submit-link').click( function() 
           $('form#ajaxForm').trigger('submit');
      ).show();
  

<% using (Ajax.BeginForm("Update", "Description", new  id = Model.Id ,
     new AjaxOptions
     
       UpdateTargetId = "DescriptionDiv",
       HttpMethod = "post"
     , new  id = "ajaxForm"  )) %>
   Description:
   <%= Html.TextBox("Description", Model.Description) %><br />
   <a href="#" class="submit-link" style="display: none;">Save</a>
   <noscript>
       <input type="submit" value="Save" />
   </noscript>
<%  %>

【讨论】:

感谢您的 cmets。这一切都是有道理的——我将示例快速放在一起,因此表单没有引号和显式 ID(它们存在于实际应用程序中)。确实,用 jQuery 做这一切更清晰,但目前不是一个选择。 实际上,这并不适用于所有浏览器。它适用于 Safari 和 Firefox,但不适用于 IE 和 Chrome。在 Safri/Firefox 中触发 'submit' 事件在 Chrome/IE 中有效,触发 'onsubmit' 有效并且触发 'submit' 实际上会导致传统的非 ajax 帖子发生。 $('form#ajaxForm').submit(); 使用 jQuery 1.4.4 和 MVC 3 为我工作。但我花了很长时间才弄清楚您需要引用一些脚本文件,否则这将退回到常规帖子-背部。这些文件在我的情况下:jquery.unobtrusive-ajax.(min.)js + MicrosoftAjax 和 MicrosoftMvcAjax 如果不同的是 .submit() 到 .trigger('submit');,它并不能解决问题。 加载 jquery.unobtrusive-ajax.(min.)js 对我也有帮助。【参考方案2】:

我已经尝试过几次让 ajax 表单提交工作得很好,但总是遇到完全失败或太多妥协。下面是一个页面示例,它使用 MVC 页面内的 jQuery Form plug-in 在用户在输入框中键入内容时更新项目列表(使用部分呈现的控件):

<div class="searchBar">
    <form action="<%= Url.Action ("SearchByName") %>" method="get" class="searchSubmitForm">
        <label for="projectName">Search:</label>
        <%= Html.TextBox ("projectName") %>
        <input class="submit" type="submit" value="Search" />
    </form>
</div>
<div id="projectList">
    <% Html.RenderPartial ("ProjectList", Model); %>
</div>

<script type="text/javascript">
    jQuery(document).ready(function() 
        jQuery("#projectName").keyup(function() 
            jQuery(".searchSubmitForm").submit();
        );

        jQuery(".searchSubmitForm").submit(function() 
            var options = 
                target : '#projectList'
            

            jQuery(this).ajaxSubmit(options);

            return false;
        );

        // We remove the submit button here - good Javascript depreciation technique
        jQuery(".submit").remove();
    );
</script>

在控制器端:

public ActionResult SearchByName (string projectName)

    var service = Factory.GetService<IProjectService> ();
    var result = service.GetProjects (projectName);

    if (Request.IsAjaxRequest ())
        return PartialView ("ProjectList", result);
    else
    
        TempData["Result"] = result;
        TempData["SearchCriteria"] = projectName;

        return RedirectToAction ("Index");
    


public ActionResult Index ()

    IQueryable<Project> projects;
    if (TempData["Result"] != null)
        projects = (IQueryable<Project>)TempData["Result"];
    else
    
        var service = Factory.GetService<IProjectService> ();
        projects = service.GetProjects ();
    

    ViewData["projectName"] = TempData["SearchCriteria"];

    return View (projects);

【讨论】:

感谢您提供此示例,但我正试图深入了解这个特定问题 - 正如我所指出的,我有一个使用 jQuery 的替代解决方案,但我无法使用它。【参考方案3】:

一个简单的例子,下拉列表的改变触发一个 ajax 表单提交来重新加载一个数据网格:

<div id="pnlSearch">

    <% using (Ajax.BeginForm("UserSearch", "Home", new AjaxOptions  UpdateTargetId = "pnlSearchResults" , new  id="UserSearchForm" ))
     %>

        UserType: <%: Html.DropDownList("FilterUserType", Model.UserTypes, "--", new  onchange = "$('#UserSearchForm').trigger('submit');" )%>

    <%  %>

</div>

trigger('onsubmit') 是关键:它调用了 MVC 嫁接到表单上的 onsubmit 函数。

注意。 UserSearchResults 控制器返回一个使用提供的模型呈现表的 PartialView

<div id="pnlSearchResults">
    <% Html.RenderPartial("UserSearchResults", Model); %>
</div>

【讨论】:

@Abel 你确定你的编辑吗?我记得当时它非常具体地触发('onsubmit'),而不是触发('submit')。 好吧,我尝试了您的解决方案,使用 onsubmit 引发了 JS 错误,使用 submit 没有。就那么简单。不过我并没有多想。【参考方案4】:

与其使用 JavaScript,不如试试

<a href="#">

  <input type="submit" value="save" style="background: transparent none; border: 0px none; text-decoration: inherit; color: inherit; cursor: inherit" />

</a>

【讨论】:

【参考方案5】:

不幸的是,触发 onsubmit 或 submit 事件在所有浏览器中都不起作用。

在 IE 和 Chrome 中工作:#('form#ajaxForm')trigger('onsubmit'); 在 Firefox 和 Safari 中工作:#('form#ajaxForm')trigger('submit');

另外,如果您在 Chrome 或 IE 中触发('submit'),它会导致整个页面被发布,而不是执行 AJAX 行为。

适用于所有浏览器的是removing the onsubmit event behavior and just calling submit() on the form itself。

<script type="text/javascript">
$(function() 

    $('form#ajaxForm').submit(function(event)  
        eval($(this).attr('onsubmit')); return false; 
        );

    $('form#ajaxForm').find('a.submit-link').click( function()  
        $'form#ajaxForm').submit();
        );

  
</script>
  <% using (Ajax.BeginForm("Update", "Description", new  id = Model.Id ,
     new AjaxOptions
     
       UpdateTargetId = "DescriptionDiv",
       HttpMethod = "post"
     , new  id = "ajaxForm"  )) %>
   Description:
   <%= Html.TextBox("Description", Model.Description) %><br />
   <a href="#" class="submit-link">Save</a> 
<%  %>

此外,链接不必包含在表单中才能使其正常工作。

【讨论】:

评估,真的吗?这是一场安全噩梦。为什么这么难?【参考方案6】:

Ajax.BeginForm 看起来失败了。

使用常规的 Html.Begin 可以很好地解决问题:

$('#detailsform').submit(function(e) 
    e.preventDefault();
    $.post($(this).attr("action"), $(this).serialize(), function(r) 
        $("#edit").html(r);
    );
); 

【讨论】:

【参考方案7】:

试试下面的方法:

<input type="submit" value="Search" class="search-btn" />
<a href="javascript:;" onclick="$('.search-btn').click();">Go</a>

【讨论】:

【参考方案8】:

只需将普通按钮放置在 Ajax.BeginForm 中,然后单击查找父表单并正常提交。 Razor 中的 Ajax 形式:

@using (Ajax.BeginForm("AjaxPost", "Home", ajaxOptions))
            
        <div class="form-group">
            <div class="col-md-12">

                <button class="btn btn-primary" role="button" type="button" onclick="submitParentForm($(this))">Submit parent from Jquery</button>
            </div>
        </div>
    

和 Javascript:

function submitParentForm(sender) 
    var $formToSubmit = $(sender).closest('form');

    $formToSubmit.submit();

【讨论】:

以上是关于如何使用 JavaScript 而不是提交按钮发布 ASP.NET MVC Ajax 表单的主要内容,如果未能解决你的问题,请参考以下文章

createElement 按钮似乎提交表单而不是函数调用[重复]

使用 URL + GET 参数填写表单按钮而不提交表单

按钮类型=使用php isset而不是输入类型按钮提交[重复]

如何在javascript中使用class而不是id

如何使用 JavaScript 在没有提交按钮的情况下提交“文件”输入?

使用 JavaScript 和 AJAX,我是不是仍需要 HTML <form> 标签,是不是仍需要使用“提交”按钮向服务器提交表单?