【问题标题】:Dynamically return an AJAX action link from a controller action从控制器动作动态返回 AJAX 动作链接
【发布时间】:2012-04-10 14:33:39
【问题描述】:

我正在尝试在用户名表的每一行上创建一个按钮,该按钮可以针对每个用户切换锁定/解锁功能。我想使用 AJAX,这样我就不必每次重新加载页面时都获取所有用户。在表格中很容易有一个 AJAX 操作链接,但是在我锁定或解锁用户后,我一直不知道从我的控制器返回什么。作为一个小技巧,我返回一个字符串,它是一个新的 AJAX 操作链接的 html 标记。我理论上可以单击动态返回的按钮,然后继续切换锁定/解锁。令我惊讶的是,这确实有效,直到我点击了按钮。动态按钮确实返回正确的标记,但它在空白页上。为了使事情进一步复杂化,我正在使用自定义助手来输出我的操作链接。我已经详细说明了下面的所有代码,如果有人能看到可能出现的问题或处理这种情况的更好方法,我将不胜感激。

HTML 助手:

 public static string ImageActionLink(this AjaxHelper helper, string imageUrl, string   altText, string actionName, object routeValues, AjaxOptions ajaxOptions)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("src", imageUrl);
        builder.MergeAttribute("alt", altText);
        var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions);
        return link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing));
    }

控制器:

public string Lock(Guid id)
    {
        IUserMethods userMethods = new UserMethods();

        ISMPUser user = userMethods.GetUser(id, CompanyId);
        string ajaxButtonHTML;

        //For some reason breaking the button HTML into substrings and appending them together for readability causes the anchor tag to render incorrectly.
        if (user.IsEnabled)
        {
            userMethods.AdministratorEnableAccount(CompanyId, CurrentUser.Id, user.Username, false);
            ajaxButtonHTML = "<a class=\"row_selected\" href=\"/MMWeb/Admin/Lock/" + id.ToString() + "\" onclick=\"Sys.Mvc.AsyncHyperlink.handleClick(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, confirm: 'Lock User?', httpMethod: 'Post', updateTargetId: 'Enable-'" + user.Id + "' });\"><img src=\"/MMWeb/Content/Images/lock.png\" alt=\"Lock\"></a>";
        }
        else
        {
            userMethods.AdministratorEnableAccount(CompanyId, CurrentUser.Id, user.Username, true);
            ajaxButtonHTML = "<a class=\"row_selected\" href=\"/MMWeb/Admin/Lock/" + id.ToString() + "\" onclick=\"Sys.Mvc.AsyncHyperlink.handleClick(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, confirm: 'Lock User?', httpMethod: 'Post', updateTargetId: 'Enable-'" + user.Id + "' });\"><img src=\"/MMWeb/Content/Images/unlock.png\" alt=\"Unlock\"></a>";
        }

        return ajaxButtonHTML;
    }

查看:

<td id="<%= Html.Encode("Enable-" + user.Id) %>" class="icon-column">
                    <% if(user.IsEnabled)
                       { %>
                           <%--<img class="LockImg" alt="User Unlocked" src="<%= Url.Content("~/Content/Images/unlock.png") %>" />--%>
                           <%= Ajax.ImageActionLink(Url.Content("~/Content/Images/unlock.png"), "Lock", "Lock", new { id = user.Id.ToString() }, new AjaxOptions { Confirm = "Lock User?", HttpMethod = "Post", UpdateTargetId = "Enable-" + user.Id })%>
                    <% }
                       else
                       {%>
                           <%= Ajax.ImageActionLink(Url.Content("~/Content/Images/lock.png"), "Lock", "Lock", new { id = user.Id.ToString() }, new AjaxOptions { Confirm = "Unlock User?", HttpMethod = "Post", UpdateTargetId = "Enable-" + user.Id })%>
                    <% }%>
                </td>

【问题讨论】:

    标签: ajax asp.net-mvc asp.net-ajax


    【解决方案1】:

    可能有几种方法,例如:

    在客户端,当用户点击一个Lock/Unlock链接时,向服务器发送一个Ajax请求来改变锁定状态,发送user-Id和Ajax调用;在服务器的“锁定”操作中,更新用户锁定状态并将更改的用户状态作为 JSON 数据返回给客户端。根据结果​​,更改链接的 CSS 以反映当前的锁定状态。下面是示例代码:

    查看:

    <td>
     <a class='<%= (item.IsLocked ? "userLock" : "userUnlock") %>' 
        href='<%= Url.Action("ResetLock", new {id = item.Name, isLocked = item.IsLocked}) %>'>
     </a> 
    </td>
    

    示例 CSS:

    .userLock,
    .userUnlock
    {
        background-image: url('/MMWeb/Content/Images/lock.png');
        display: block;
        height: 16px;
        width: 16px;                        
    }
    .userUnlock
    {
        background-image: url('/MMWeb/Content/Images/unlock.png');
    }    
    

    javaScript:

    <script type="text/javascript">
    $(function () {
    
        $('a.userLock, a.userUnlock').click(function (e) {
    
            e.preventDefault()
            var $this = $(this);
    
            $.ajax({
                url: $this.attr('href'),
                type: "POST",
                dataType: "json",
    
                success: function (result, textStatus, jqXHR) {
                    if (result.status == "Succeed") {
                        if (result.IsLocked == true) {                                
                            $this.removeClass('userUnlock').addClass('userLock');
                        }
                        else {                                
                            $this.removeClass('userLock').addClass('userUnlock');
                        }
                    }
                },
                error: function () {
                    alert('Failed to reset lock.');
                }
            });
        });
    });
    </script>
    

    控制器:

     [HttpPost]
        public ActionResult ResetLock(Guid id)
        {
            //......
            //Update user locking status.
            //user.IsEnabled = !user.IsEnabled;
            //......
    
            var updatedModel = new { 
                status = "Succeed",
                IsLocked = user.IsEnabled
            };
    
            return Json(updatedModel);
        }
    

    这种方法使您的控制器操作保持精简和干燥。 我认为,在控制器的操作中将视图生成为字符串并不是一个好习惯。

    另一种方法可能是:

    将锁定视图包装在部分视图中(例如 UserEnableView.ascx)。 在更新用户的锁定状态后,“锁定”操作方法应返回部分视图。例如

    public ActionResult Lock(Guid id)
    {
        //......
        //Update user locking status.
        //....
       if (Request.IsAjaxRequest()) {
          return PartialView( "UserLockView", updatedModel);
       }
       else{
          return View(updatedModel);
       }          
    }
    

    【讨论】:

      猜你喜欢
      • 2014-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多