Archive for category Ajax

Slow multiple jQuery autocomplete fields

I’m a fan of the jQuery autocomplete control. I had a page that worked great with one autocomplete control, but after I added a second, that second control was horribly slow (the first was unchanged). Both controls were defined similar to the one here:

$("#Coaster").autocomplete({
    source: function (request, response) {
        if (request.term.length < 4) {
            return;
        }
        var coaster = new Array();
        $.ajax({
            async: false,
            cache: false,
            type: "POST",
            url: uri + "MyControll/Autocomplete",
            data: { "term": request.term },
            success: function (data) {
                for (var i = 0; i < data.length ; i++) {
                    customer[i] = data[i];
                }
            }
        });
        response(coaster);
    },
    select: function (event, ui) {
        $("#CoasterID").val(ui.item.Id);
    }
});

In order to get the second control to respond within a reasonable period of time, I added this code to the end of the Ajax method, which resolved the problem:

$("#Coaster").autocomplete({

        $.ajax({
 …
        })._renderItem = function (ul, item) {
            return $("<li></li>")
                .data("item.autocomplete", item)
        };
});

Leave a comment

When your Boolean parameter says “oncheck” in JavaScript and what to do about it

In my MVC application, I was building a table using a partial view. One column was an HTML link whose onclick event was bound to the “show” method, and this method took two parameters, a string and a boolean:

 <table>
   <tr>
      <td><a onclick="show('@item.ID', '@item.IsVisible')">Click Me!</a></td>
   </td>
 </table>

Inside the “show” method, notice the “visible” checkbox. I am simply setting the “checked” property to true or false, depending on the value of the “visible” parameter:

function show(id, visible) {
 $("#id").val(id);
 $('#visible').prop('checked', visible);
}

When running this code, I got strange behavior, and using the Developer Tools (F12 in IE), I noticed that the string generating the edit button line looked like this:

 <td><a onclick="show('1', 'checked')">Click Me!</a></td>

Huh. How did that “checked” get in there? When I ran the debugger, and MVC code was correctly binding the Boolean variable to either “True” or “False”, so what’s with this “checked” things I’m seeing?

There were two problems here. First, I needed to modify the MVC code, calling the “ToString” method on the Boolean property:

    <td><a onclick="show('@item.ID', '@item.IsVisible.ToString()')">Click Me!</a></td>

Second, this would return “True” or “False”, with the first letter capitalized. JavaScript needs those values in lower case. So I set up a ternary operator to handle that:

function show(id, visible) {
  $('#visible').prop('checked', visible == "True" ? true : false);
}

Fixed!

Leave a comment

Deleting a row from inside a partial view

Post #200! I hope it’s a good one…

I had a view, within which was a partial view that contained a table. Inside this table was link to delete the current table row.

Form

Form

So to recap: View -> Partial View -> Delete Row

Since I did not want the whole page to refresh, I needed to use some jQuery to do this.
On my main page, I populated the various drop down lists you see above. Leaving out all that code, I have this remaining code at the bottom of the page:

    function deleteRow(id) {
        $.ajax({
            url: "/MyApp/DeletePermission",
            type: "GET",
            data: { id: id }
        })
        .done(function (partialViewResult) {
            $("#results").html(partialViewResult);
        });
    }

The “results” DIV tag holds the partial view, which I am populating with an onchange event earlier in the page. I assume you have this part down, but if not, post a comment and I’ll write something up about binding data to a partial view. Heck, maybe I will anyways.

In my partial view, I build the table, a truncated version of which is here:

     @foreach (var item in Model) {
         <tr>
             <td>@Html.DisplayFor(modelItem => item.) </td>
             <td><a onclick="deleteRow('@item.ID')">Delete</a></td>
         </tr>
     }

So when I click the “Delete” link in the partial view, it will call the “deleteRow” function in the main view. The jQuery will then call my controller action:

  public ActionResult DeletePermission(Permission item) {
      List<Permission> model = Repository.DeletePermission(item.ID);
      return PartialView("_PermissionsTable", model);
  }

Notice that the action returns a list of Permission objects, which is then use to refresh / rebind the table when the “done” method of the jQuery function is completed.

,

Leave a comment

Web API null parameter when POSTing from jQuery

You know that issue where you’re trying to POST a value from jQuery and in the Web API code the parameter is always null? Yeah, that sucks. Hopefully this post will help with your POST problems. I’ll keep this short and explain how I got it to work. First, my Web API method:

public class PermissionsController : ApiController {
     [System.Web.Mvc.HttpPost]
     public HttpResponseMessage Post([FromBody]DTO item)
     {
         string test = item.Name;
         return Request.CreateResponse(HttpStatusCode.OK);
     }
}

I’m passing in more than one field, so I created a data transfer object:

     public class DTO {
         public string Name { get; set; }
         public string AccessType { get; set; }
         public DTO() { }
     }

And my jQuery:

   $.ajax({
      url: 'http://localhost:33166/api/Permissions',
     type: 'POST',
     dataType: 'json',
     cache: false,
     contentType: "application/json",
     data: JSON.stringify(name),
     success: function (d) {
          alert('awesome');
     },
});

Leave a comment

Canceling a JavaScript / jQuery AJAX call

Technically, it’s not really canceled. I just wanted to say that straight away.

I had two drop down lists, the first with departments, and the second with supervisors in those departments. Choosing a value in the first DLL would populate the second DDL as well as loading a bunch of data to display on the page. The second DDL was populated quickly, but the rest of the data could take a while longer to display, and I wanted the users to be able to cancel the long-running request to see the supervisor-specific data.

One problem was that if I selected a supervisor while the department data was still loading, the supervisor-specific data would load, but when the call to the department-wide data finally finished, it would overwrite the supervisor data.

I was using the jQuery “$.ajax” method to call a Web API method. I had tried using the abort() method of the XMLHttpRequest object, the underlying object of the AJAX request, when the second DDL was changed. This didn’t work – the department data was still overwriting the supervisor data – so I had to get hacking.

Here is my solution. I created a variable called “processingRequest”. When the loadData function (which pulled the data from Web API) is started, the variable is set to “true”.  When the request completes, either successfully or it fails, the variable is set to false. Short-running requests will complete before any long-running requests, thus setting the “processingRequest” variable to false. When the long-running requests finished, it will see that the “processingRequest” variable isn’t true, and not perform the page update.

var processingRequest = false;
function loadData(supervisor, dept) {
    var theData = {
        'Supervisor': supervisor,
        'Dept': dept
    }
    processingRequest = true;
    var jqxhr = $.ajax({
        method: 'POST',
        contentType: 'application/json',
        url: uriToMyService,
        data: JSON.stringify(theData)
    })
      .done(function (d) {
          if (processingRequest) {
              populatePage(true);
              processingRequest = false;
          }
      })
      .fail(function (jqXHR, textStatus, errorThrown) {
          console.log('loadData error: ' + errorThrown);
          processingRequest = false;
      })
};

As I said in the beginning of the post, the request is not canceled, but the results of the request are never shown to the user.

,

Leave a comment

Data not refreshing in MVC view with IE, but was in Chrome

I had some basic code binding to my model, and here is a beautiful snippet:

@using (Html.BeginForm("Manage", "Account", FormMethod.Post)) {
        <label>Select User</label>
        <select id="users" onchange="getUser()">
            <option selected="selected" value="0">Add User</option>
        </select>
        @Html.LabelFor(m => m.UserName)
        @Html.TextBoxFor(m => m.UserName)
       <input type="submit" id="save" value="Save" />
}

Yes, I used an HTML select list in MVC – don’t judge me.

I also had some jQuery calls. The first would populate the awesome (and easy to use) select control, and the second would be called when a user selected an item in my awesome (and easy to use) select list:

    function getUsers() {
        $.ajax({
            url: '@Url.Content("~/Account/Users")',
            method: "GET",
            dataType: 'json',
            async: false,
            success: function (data) {
                var options = $("#users");
                $.each(data, function (i, val) {
                    options.append($("<option />").val(val.UserId).text(val.UserName));
                });
            }
        });
    }
    function getUser() {
        $.ajax({
            url: '@Url.Content("~/Account/GetUser")',
            method: "GET",
            dataType: 'json',
            data: { 'userId': $("#users").val() },
            async: false,
            success: function (data) {
                $("#UserName").val(data.UserName);
            }
        });

With Chrome, everything was fine, and there was much happiness abounding at my stand up desk. But when using IE, the Sad Clown of Life paid a visit, and neither my select list nor my fields were updated after I would choose a record, update it, and click the save button.

The problem was that IE was caching my data. I understand, it was great data, but sometimes, you just need to let go. The key was adding the “cache: false” tag to the jQuery function, like so:

    function getUser() {
        $.ajax({
            url: '@Url.Content("~/Account/GetUser")',
  cache: false,
  …
        });

Success – I got data in IE.

,

Leave a comment

404 error calling an MVC controller action

There are two reasons I have seen this so far, and I have included both. I have creatively labeled them “Reason #1” and “Reason #2”. I leave it to you what will happen if I find a third reason.

Reason #1

I was using Ajax to call an MVC action like so:

        $.ajax({
            type: 'GET',
            url: '@Url.Content("~/Home/Stuff")',
            success: function (data) {
                $('#results').replaceWith(data);
            }, error: function (xhr) {
                alert(xhr.statusText);
            }
        });

And my Stuff action in the Home controller:

private ActionResult Stuff() {
            return PartialView("~/Views/Home/Stuff.cshtml");
}

But, I was deeply saddened to see that I was getting a “404 Not Found” error when I tried to do this. And it was because I made a simple mistake and hadn’t made my Stuff action public. Making that change fixed the issue:

public ActionResult Stuff() {
             return PartialView("~/Views/Home/Stuff.cshtml"); 
}

Reason #2

The second reason was that the URL was pointing to the wrong location. Shocker, I know. But here is the code that was causing the 404:

    $.ajax({
        url: '/Account/GetUsers',
        method: "GET",
    });

It appears that this would be fine – calling my controller Account, and the action GetUsers. However, this is ignoring that jQuery doesn’t know the complete path. The right code is:

    $.ajax({
        url: '@Url.Content("~/Account/GetUsers")',
        method: "GET",
    });

 

,

1 Comment

MVC – Retrieving data using jQuery and Ajax

Retrieving text using MVC through jQuery and Ajax is fairly simple. What I wanted to happen was to have a link that loaded a DIV when the user clicked it. So the really simple HTML:

<a href="#" onclick="load()">Support</a>

The jQuery for this request wasn’t much, either. Just a simple GET request pointing to the controller and action:

    function load() {
        $.ajax({
            type: 'GET',
            url: '@Url.Content("~/Home/Test")',
            success: function (data) {
                $('#results').text(data);
            }, error: function (xhr) {
                alert(xhr.statusText);
            }
        });
    }

And the Home controller, Test action:

public string Test() {
       return "Testing";
}

I did run into a problem where I was getting “404 Not Found” errors when I attempted to access the action. This was happening because my action was declared as private, so the 404 message made perfect sense.

, , ,

Leave a comment

“Request blocked because of sensitive information” error using jQuery / JSON

I had a very simple jQuery method to call a Web API method, such as this:

function GetLogs() {
request = $.ajax({
url: “Home/Get”,
type: “GET”,
dataType: ‘json’,
async: false,
contentType: “application/json;charset=utf-8”,
success: function (request, status, error) {
alert(‘success’);
},
error: function (request, status, error) {
alert(‘error’);
}
});
}

Behind the scenes, I had this little test method that returned a couple of string values:

public ActionResult Get() {
List<string> results = new List<string>();
results.Add(“one”);
results.Add(“two”);
return Json(results);
}

When I returned the data from this innocuous piece of code, I got this unfortunate error:

 “This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.”

It was a simple fix – I just had to add the AllowGet method to my “Json” method call:

public ActionResult Get() {
List<string> results = new List<string>();
results.Add(“one”);
results.Add(“two”);
return Json(results, JsonRequestBehavior.AllowGet);
}

And back came the data.

Leave a comment

Fixing the “Could not load file or assembly AjaxControlToolkit” error with bindingRedirect

I was upgrading a web site to use a later version of the AjaxControlToolkit.dll. The file version of the new DLL was 4.1.60623.0. So I changed the DLL to the new version and rebuilt my project locally, and all was well with my pages, giving me that warm, fuzzy feeling like rum-infused egg nog. But that warm, fuzzy feeling went away when I tried to deploy it on this whole interwebs thing, when I got this error:

Could not load file or assembly ‘AjaxControlToolkit, Version=4.1.50401.0, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e’

The first thing I tried was screaming “WHY AREN’T YOU WORKING?” at the computer, but this did not seem to work. Which is odd – it usually does.

So the next thing I did was search, and I found something interesting: The bindingRedirect element, the documentation of which you can find on MSDN. So I modified my web.config file, adding this code inside the <configuration> element:

   <runtime>
      <assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1″>
         <dependentAssembly>
            <assemblyIdentity name=”AjaxControlToolkit”
                              publicKeyToken=”28f01b0e84b6d53e”
                              culture=”neutral” />
            <bindingRedirect oldVersion=”4.1.50401.0″
                             newVersion=”4.1.60623.0″/>
         </dependentAssembly>
      </assemblyBinding>
   </runtime>

Tada! It worked.

Leave a comment