如何在ASP.NET MVC中通过AJAX正确调用POST动作方法

时间:2016-08-12 14:13:08

标签: ajax asp.net-mvc

我尝试通过Ajax调用MVC操作失败了。当我这样做时,会发生以下错误:

HttpException: A public action method 'Find' was not found on controller 'MyProject.Controllers.LoanController'.

我尝试调用的操作方法具有以下签名:

[Route("Loan/Find/{loanNumber:int}")]
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
[ActionName("Find")]
[AllowAnonymous]
public ActionResult Find(int loanNumber)
{
    var model = new LoanStatusModel
    {
        Record = Repository.GetRecord(loanNumber),
        User = this.SecurityPrincipal
    };

    return this.PartialView("LoanStatusSearchResult", model);
}

尝试调用它的视图代码如下:

@using(Ajax.BeginForm("Find", new AjaxOptions
                                        {
                                            HttpMethod = "POST",
                                            AllowCache = false,
                                            InsertionMode = InsertionMode.Replace,
                                            UpdateTargetId = "ajaxTarget",
                                            LoadingElementId="loader"

                                        }))
{
    <fieldset>
            <div class="col-sm-3">
                <input type="text" 
                       id="loanNumber" 
                       name="loanNumber" 
                       value="@Model.LoanNumber" 
                       class="form-control" 
                       minlength="8" 
                       maxlength="10"/>
            </div>
            <div class="col-sm-7">
                <input type="submit" 
                       value="Search" 
                       class="btn btn-primary"/>
            </div>
        </div>
    </fieldset>
}

<div id="loader" style="display:none">
    Working, please wait...
</div>
<div id="ajaxTarget">
</div>

这是我的RouteConfig.cs的内容:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new
            {
                controller = "Home",
                action = "Index",
                id = UrlParameter.Optional
            }
        );

}

Fidler报告说,路由请求导致HTTP 401 Not Authorized,这是有道理的,因为这是一个最初配置为禁用匿名访问的Intranet站点。但是,已启用匿名访问,并且仍会出现错误。

要解决此问题,我在搜索了整个互联网(特别是StackOverflow)之后尝试了以下内容:

  • 我更改了IIS以接受匿名请求并重新启动了服务器。这与结果无关。
  • 最初,动作方法用HttpPostAttribute修饰。将其更改为使用AcceptVerbs与结果无关。
  • 我在方法中添加了AllowAnonymous,它与结果无关。

如何解决此问题?它可以解决吗?我需要提供哪些其他信息?

1 个答案:

答案 0 :(得分:2)

您有属性路线定义

[Route("Loan/Find/{loanNumber:int}")]

因此,当您尝试使用yourSite/Loan/Find/123123313访问您的操作方法时,它将转到操作方法,但如果您尝试正常yourSite/Loan/Find?loanNumber=123123123,它将无法正常工作!

您的Ajax.BeginForm html帮助器会将表单标记的操作值生成为&#34; / Home / Find&#39;当您提交表单时,loanNumber的值将在帖子正文中提交。它不在您在属性路由定义中定义的路由模式中。

如果删除属性路由路由定义,您的代码将起作用。属性路由主要用于创建不错的seo友好类型URL。因此,最好是GET操作,而不是表单发布方案。

如果您仍想保留属性路由路由模式,我建议您不要使用Ajax.BeginForm帮助方法并处理ajax调用您自己,您可以按照自己的方式构建URL。

所以建立一个普通的表格,给表格一个id。

@using (Html.BeginForm("Find","Home", FormMethod.Post,new {id="mySearchForm"}))
{
   <div class="col-sm-3">
         <input type="text" id="loanNumber" name="loanNumber"value="@Model.LoanNumber" />
    </div>
    <div class="col-sm-7">
       <input type="submit" value="Search" />
    </div>
}

并使用javascript来监听此表单上的提交事件,停止默认行为并使用我们想要的网址进行ajax调用!

$(function () {

    $("#mySearchForm").submit(function(e) {
            e.preventDefault();
            var url = "@Url.Action("Find","Home")";    //change to your controller name     
            url = url + "/" + $("#loanNumber").val();
            $.post(url, function(res) {
                    $("#ajaxTarget").html(res);
            });
    });

});