为什么 Ajax 在第一个请求时可以正常工作,但在第二个请求时会在新页面上返回部分视图?

2024-05-27

我有一个嵌套在表中每一行中的 Ajax 表单,以提供添加/删除功能。该部分列出了所有可用的角色(Microsoft Identity 2.0),以及每个角色的指定用户是否与该角色关联,以及用于切换用户进出角色的按钮(Ajax)。

当我使用 Ajax.Beginform 时,一切工作正常,但是当我使用常规 jquery 时,第一次单击按钮切换用户与角色的关联时,它会工作,但第二次它会在其新页面上加载部分视图。自己没有CSS样式。

在 stackoverflow 上搜索,我看到其他人也有类似的问题,但他们似乎根本没有 ajax 工作,不像我,它在第一个请求上工作,然后就不再工作了。我还应该提到,我对 Asp.net 相当陌生,这是我第一次直接使用 jquery(遵循 Scott Allan 的 PluralSight 教程)。

这是我已经尝试过的: 使用调试断点检查 ajax 请求是否命中该操作。 检查我是否在布局视图中引用了 jquery,并且引用的次数不超过一次。 检查我是否以正确的顺序引用 jquery 和 jquery unobtrusive ajax。 检查 web.config 是否将相关标志设置为 true。

我已经坚持了几个小时了,任何指导将不胜感激。

BundleConfig.cs:

    namespace GCCP
{
    public class BundleConfig
    {
        // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
        public static void RegisterBundles(BundleCollection bundles)
        {   
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.validate*",
                        "~/Scripts/jquery.unobtrusive*"));

            bundles.Add(new ScriptBundle("~/bundles/gccp").Include(
                        "~/Scripts/gccp.js"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                      "~/Scripts/bootstrap.js",
                      "~/Scripts/respond.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include(
                      "~/Content/bootstrap.css",
                      "~/Content/site.css"));

            // Set EnableOptimizations to false for debugging. For more information,
            // visit http://go.microsoft.com/fwlink/?LinkId=301862
            BundleTable.EnableOptimizations = true;
        }
    }
}

行动方法:

public ActionResult UserRoles(string returnUrl, string UserName)
{
    ViewBag.ReturnUrl = returnUrl;

    UserRolesViewModel Model = new UserRolesViewModel();
    Model.UserName = UserName;
    Model.RoleAssignments = UserRoleAssignments(UserName);

    return View(Model);
}

[HttpPost]
public ActionResult ToggleUserToRoleAssignment(string returnUrl, string UserName, string RoleName)
{
    ViewBag.ReturnUrl = returnUrl;

    var userStore = new UserStore<ApplicationUser>(context);
    var userManager = new UserManager<ApplicationUser>(userStore);
    var roleStore = new RoleStore<IdentityRole>(context);
    var roleManager = new RoleManager<IdentityRole>(roleStore);
    string userID = userManager.FindByName(UserName).Id;

    if ( roleManager.RoleExists(RoleName) == true )
    {
        if ( userManager.IsInRole(userID, RoleName) == true )
        {
            userManager.RemoveFromRole(userID, RoleName);
        }
        else
        {
            userManager.AddToRole(userID, RoleName);
        }
    }

视图模型:

namespace GCCP.Models
{
    public class UserRolesViewModel
    {
        [Required]
        [Display(Name = "User")]
        public string UserName { get; set; }
        public Dictionary<string, bool> RoleAssignments { get; set; }
        public string AjaxTest { get; set; }
    }

}

View:

@using GCCP.Models;
@using System.Web.Mvc.Ajax;
@model UserRolesViewModel

@{
    ViewBag.Title = "User Roles";
}

<h2>
    @Model.UserName  |  Assigned Roles 
</h2>

    @Html.Partial("_UserRolesList", Model)

部分视图:

@using GCCP.Models;
@using System.Web.Mvc.Ajax;
@model UserRolesViewModel

<div id="roleAssignmentList">
    <table class="table table-condensed">
        <thead>
            <tr>
                <th>
                    Roles
                </th>
                <th>
                    Assigned
                </th>
                <th>
                    Add / Remove
                </th>
            </tr>
        </thead>
        <tbody>
            @foreach ( var item in Model.RoleAssignments )
            {
                if ( item.Value )
                {
                    <tr class="active">
                        <td>
                            @item.Key
                        </td>
                        <td>
                            <i class="glyphicon glyphicon-ok"></i>
                        </td>
                        <td>
                            <form action="@Url.Action("ToggleUserToRoleAssignment")" method="post" data-gccp-ajax="true" data-gccp-target="#roleAssignmentList">
                                <input type="hidden" name="RoleName" value="@item.Key"/>
                                <input type="hidden" name="UserName" value="@Model.UserName"/>
                                <input type="submit" value="Change"/>
                            </form>
                        </td>
                    </tr>
                }
                else
                {
                    <tr>
                        <td>
                            @item.Key
                        </td>
                        <td>
                            <i class="glyphicon glyphicon-remove"></i>
                        </td>
                        <td>
                            <form action="@Url.Action("ToggleUserToRoleAssignment")" method="post" data-gccp-ajax="true" data-gccp-target="#roleAssignmentList">
                                <input type="hidden" name="RoleName" value="@item.Key"/>
                                <input type="hidden" name="UserName" value="@Model.UserName"/>
                                <input type="submit" value="Change"/>
                            </form>
                        </td>
                    </tr>
                }
            }
        </tbody>
    </table>
</div>

Jquery:

$(function () {
    var ajaxFormSubmit = function () {
        var $form = $(this);

        var options = {
            url: $form.attr("action"),
            type: $form.attr("method"),
            data: $form.serialize()
        };

        $.ajax(options).done(function (data) {
            var $target = $($form.attr("data-gccp-target"));
            $target.replaceWith(data);
        });

        return false;
    };

    $("form[data-gccp-ajax='true']").submit(ajaxFormSubmit);

});

提前致谢 :)


“仅第一次有效”行为是动态添加内容但事件直接绑定到元素的情况的典型情况(例如,在 DOM 就绪时)。

相关部分是这样的:

$("form[data-gccp-ajax='true']").submit(ajaxFormSubmit);

它仅绑定到运行该行代码时存在的现有表单。

另一种方法是使用委托事件处理程序,附加到元素的不变祖先:

e.g.

$('#roleAssignmentList').on("submit", "form[data-gccp-ajax='true']", ajaxFormSubmit);

它的工作原理是监听提交事件以冒泡到该祖先,then将 jquery 选择器应用于气泡链中的元素,then应用该函数。

如果你没有方便的工具不变的祖先 use document。我不能 100% 确定你没有完全取代#roleAssignmentList(或只是它的子项),因此该示例无法使用document反而。

e.g.

$(document).on("submit", "form[data-gccp-ajax='true']", ajaxFormSubmit);

但永远不要使用“body”作为委托事件处理程序目标(它有一些与样式相关的错误,这意味着它可能会错过某些事件)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Ajax 在第一个请求时可以正常工作,但在第二个请求时会在新页面上返回部分视图? 的相关文章

随机推荐