0

ユーザー名のテーブルのすべての行に、各ユーザーに対してロック/ロック解除機能を切り替えるボタンを作成しようとしています。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>
4

1 に答える 1

0

次のようないくつかのアプローチがあります。

クライアント側で、ユーザーが[ロック/ロック解除]リンクをクリックすると、サーバーにAjaxリクエストを送信してロックステータスを変更し、Ajax呼び出しでユーザーIDを送信します。サーバーの「ロック」アクション内で、ユーザーのロックステータスが更新され、変更されたユーザーステータスが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など)でラップします。'Lock'アクションメソッドは、ユーザーのロックステータスを更新した後、部分ビューを返す必要があります。例えば

public ActionResult Lock(Guid id)
{
    //......
    //Update user locking status.
    //....
   if (Request.IsAjaxRequest()) {
      return PartialView( "UserLockView", updatedModel);
   }
   else{
      return View(updatedModel);
   }          
}
于 2012-04-10T19:48:50.997 に答える