The Gist: You should update _SecurityGuardLayoutPage.cshtml and any other views that you decide to customize, adding scoped JavaScript references to the UI elements used by the package.

The Issue: https://github.com/kahanu/Security-Guard/issues/10

The Long Story

Like many others that are available, SecurityGuard is an awesome NuGet package available for both ASP.NET MVC3 and ASP.NET MVC4 which when installed, gives you a quick and easy way to get up and going in managing users and roles within your web application using the ASP.NET Security Providers.

After installing SecurityGuard and completing the site integration, I also decided that I wanted to update the look and feel, making it more consistent with the rest of the site. More specifically, I incorporated the top-level site’s navigation bar which was implemented using a <ul> element and CSS. Well, after completing this UI integration, I found that in one of the views (Roles\Index.cshtml) in particular, each time that I selected a role, my navigation elements disappeared from the top of the page.

So I took a look at the source code and found an interesting method call:

OnGetUsersInRoleSuccess()

 /***********************************************
        * Begin Get Users In Role Functions
        ***********************************************/

        //users-in-role-div

        var usersInRoleDiv = $("#users-in-role-div");

        $("#RolesList").change(function () {
            var item = $(this).val();

            if (item != "") {
                usersInRoleDiv.show();

                $.ajax({
                    url: '@Url.Action("GetUsersInRole", "Role")',
                    dataType: 'json',
                    type: 'GET',
                    cache: false,
                    data: { roleName: item },
                    success: OnGetUsersInRoleSuccess,
                    error: OnGetUsersInRoleError
                });
            } else {
                $("#users-in-role-div").hide();
            }
        });

        function OnGetUsersInRoleSuccess(data) {
            $("li").remove();
            if (data == "") {
                ul.append("<li>No user(s).</li>");
            } else {
                $.each(data, function (index, item) {
                    ul.append("<li><a href=\"/SecurityGuard/Membership/Update/" + 
                    item + "\">" + item + "</a></li>"); }); } } function OnGetUsersInRoleError(xhr, status, error) { message.show().delay(5000).fadeOut(); // Show the message $("li", message).addClass("red"); // Apply the Green style $("strong", message).text(error); // Insert the message } /*********************************************** * End Get Users In Role Functions ***********************************************/

The thing that is interesting about this method is that the call to $(“li”).remove() is not scoped, meaning it will remove all <li> elements on the page, regardless of location (scope). This included my navigation menu elements.

The Solution:

As a solution, I simply scoped the calls to the <ul> element that the function is intended to execute on. The end result is a set of methods that look like this:

 /***********************************************
        * Begin Get Users In Role Functions
        ***********************************************/

        //users-in-role-div
        //roles ul

        var usersInRoleDiv = $("#users-in-role-div");
        var ul = $("#users-in-role-div ul");

        $("#RolesList").change(function () {
            var item = $(this).val();

            if (item != "") {
                usersInRoleDiv.show();

                $.ajax({
                    url: '@Url.Action("GetUsersInRole", "Role")',
                    dataType: 'json',
                    type: 'GET',
                    cache: false,
                    data: { roleName: item },
                    success: OnGetUsersInRoleSuccess,
                    error: OnGetUsersInRoleError
                });
            } else {
                $("#users-in-role-div").hide();
            }
        });

        function OnGetUsersInRoleSuccess(data) {
            //clear existing list items
            ul.empty();
           
            if (data == "") {
                ul.append("<li>No user(s).</li>");
            } else {
                $.each(data, function (index, item) {
                    ul.append("<li><a href=\"/SecurityGuard/Membership/Update/" + 
                    item + "\">" + item + "</a></li>"); }); } } function OnGetUsersInRoleError(xhr, status, error) { message.show().delay(5000).fadeOut(); // Show the message $("li", message).addClass("red"); // Apply the Green style $("strong", message).text(error); // Insert the message } /*********************************************** * End Get Users In Role Functions ***********************************************/

Essentially, I created a global object scoped to the “users-in-role-div” <ul>. Then in the method, I could simply call empty() on the DOM element. Note that [list element].empty() is a native method exposed by JavaScript and not a jQuery method. It’s funny how the two are so ambiguous these days.

In any case, problem solved and I posted the issue on github so I’m sure that it will be resolved in later releases.

Comments


Comments are closed