Welcome to Professional ASP.NET - Chris Love's Official Blog Sign in | Join | Help

Chris Love's Official ASP.NET Blog

Chris Love's Helpful tips, tricks and pragmatic development knowledge for the ASP.NET world.
Add to Technorati Favorites


ASP Insider Follow Me On Twitter
Automatic jQuery Fake Name Checker

I had a great time presenting my jQuery, WCF Databinding talk at the Philly Code Camp yesterday. As usual I keep adding ‘features’ to the demonstration application I use in the session. Since I last delivered the talk I added a few creature comforts of sorts to the application. Today I want to review how I added a Fake Name checker to the contact form.

The context for my Fake Name checker comes from a real honest to goodness application I build about 9 years ago. My client launched, but was not happy he could not sign up with a fake credit card number (this is no joke). So he demanded I remove all and I mean all data validation from the site. Needless to say within a few weeks Mickey Mouse and a entire army of fictional characters were new members with fake credit cards on file.

As I thought about that project again this week I had this funny thought about extending the Username Availability checker I posted about last year to screen for obviously fake names. How realistic this is to actually implement in production is slim, but I thought it would serve to prove a point about making real-time validation happen. If you think about it you could tie this action to just about any screening process. I was thinking maybe a real-time Akismet, bad word checker, etc.

Starting at the bottom of the process there needs to be some business logic. For the demo, I chose to add 2 different names, Mickey Mouse and Steve Ballmer. I defined two totally different responses to either of these names being entered in the First and Last name fields. All other names just naturally pass through without any client-side interference. The CheckFakeName method accepts the first and last name, checks it and then returns a CheckFaleNameResponse class. The CheckFakeNameResponse class has a validState property that indicates if the name is allowed or not. If not then the responseMsg is set and will be displayed later. Finally I also added a third property for an optional message used to pre-populate the form’s comment field.

public CheckFakeNameResponse CheckFakeName(string firstName, string lastName)
{
var response = new CheckFakeNameResponse()
{
validState = true,
responseMsg = "",
commentMsg = ""
};

if(firstName.ToLower() == "micky" && lastName.ToLower() == "mouse")
{
response.validState = false;
response.responseMsg = "Seriously??? You expect me to belive this?";
} else if (firstName.ToLower() == "steve" && lastName.ToLower() == "ballmer")
{
response.validState = false;
response.responseMsg = "We are so honored to have you.";
response.commentMsg = "Developers!!!! Developers!!!! Developers!!!!! YEAH!!!!";
}

return response;
}

The service method simply returns the result to the client, in JSON of course ;). The JavaScript calls the service just like the other methods, first creating a request object containing the form’s first and last name values.

function CheckFakeName() {

var request = {
firstName: $("#FirstName").val(),
lastName: $("#LastName").val()
};

ContactServiceProxy.invoke({ serviceMethod: "CheckFakeName",
data: { request: request },
callback: function(response) {

if (!response.validState) {
alert(response.responseMsg, "Reality Check", function() {

if (response.commentMsg !== '') {
$("#Comment").val(response.commentMsg);
}

});
}

},
error: function(xhr, errorMsg, thrown) {
postErrorAndUnBlockUI(xhr, errorMsg, thrown);
}
});

return false;
}
The callback function displays an alert dialog with the responseMsg and the title ‘Reality Check’. Notice I defined a callback function to be called when the alert dialog is closed. More on that in my next post, but if there is a commentMsg it is added the form’s comment textarea.
 
Now that I have shown all the steps in the check process I need to show how all this is initiated. In the jQuery Ready function I defined an event handler for the lastName’s the blur event. This checks to make sure there is content in both the first and last name fields, if so it then calls the CheckFakeName function.
 
$("#LastName").live("blur", function() {

if ($("#FirstName").val() !== '' &&
$("#LastName").val() !== '') {
$.WCFjQuery.CheckFakeName();
}

});

That’s pretty much it. By using an AJAX call the screening is done behind the scenes and does not interfere with the user’s progress. Well that is unless you are Mickey Mouse or Steve Ballmer.
My next post will discuss how I display a nicer looking alert dialog instead of the boring battleship grey alert we have become accustomed to viewing.
 
I also want to remind you to download the updated source code for my presentation here.
Pro JavaScript Techniques

If you are into jQuery you no doubt know who John Resig is, the creator of jQuery. Well before jQuery hit the scenes John wrote Pro JavaScript Techniques, by Apress. I have really been digging into the bowls of how JavaScript works because I am doing more and more AJAX development these days. This has led me to read some core JavaScript resources, which John Resig’s Pro JavaScript Techniques is certainly one.

As I read through this book I could really see how Resig organized the foundations of jQuery. In fact once you get past the JavaScript primer sections, and when I say primer in this context I mean advanced JavaScript primer, He shows how different JavaScript libraries apply different principles. But what I found even more revealing is his review of several, I will call them projects for lack of a better name, that laid the foundations for what is now jQuery.

For example in Chapter 5 he shows how the cssQuery library can be used to select a DOM element using CSS selectors. Hmmmm that sounds very familiar. He then starts to introduce jQuery and how he started developing it.

What I really like about this book is Resig continually shows simple foundational examples of what I consider key elements of the jQuery library. If you are just using jQuery and have not wanted to break it apart and look at the guts, you are just missing out. Pro JavaScript Techniques is sort of a dissection of what this powerful library is on the insides.

One thing is for sure, as I read through the pages of this book I was more and more thankful that John wrote jQuery to abstract all this crazy functionality away from me. As I have been sharpening my JavaScript skills the past few months I am more and more convinced it is not the language that has been my enemy but more knowing and understanding how to work with the functionality baked into each browser to make real things happen. First because there just is not good (that means non white-paperish) documentation for these APIs and then they all vary slightly.

At the end of the day Pro JavaScript Techniques is a great resource that gives you a glimpse at the mind of one of the world’s best JavaScript experts. I highly recommend picking up this book, spending a good weekend, or like me long flight, and reading through it. Next start applying the principles to your daily JavaScript coding to make your AJAX applications function at a higher level.

No mapping specified for the following EntitySet/AssociationSet

Today I was working on a new project using Entity Framework 4. This is the first time I have used the model first approach available with EF 4 and came across an interesting compiler error, “No mapping specified for the following EntitySet/AssociationSet”. After that is listed several entities defined in my model. My first thought was it must be complaining about some of the associations I created between these entities. I had created many relationships just like I might designing my database tables first, so my thought was I had done something wrong.

So I searched for the error message using quotes. Side note: if you wrap your search term in quotes all the major search engines do a specific search for URLs containing that exact string. The only results I got back were relating to stored procedures, which I had none in my model. But I did find one secondary reference to an ASP.NET forum post on the error. The answer was not having the corresponding tables in my database yet. In other words I needed to Generate the Database from the Model.

So I did, which creates a SQL script, that must be executed. I am not sure why it wont just update the database for you, but I will deal with that later. I sort of can understand. So I executed the script, recompiled and viola the error has disappeared!

The jQuery Templating Plugin and Why You Should Be Excited!

One of the things that just seemed to be missing from the jQuery ecosystem was a truly simple to use data-binding mechanism. I have been writing about and presenting the use of John Resig’s Micro-Templating mechanism all over the country this Winter. Now I can update my sample code to use the templating plugin officially introduced at MIX last week.

The jQuery templating plugin is the first addition added to the jQuery Core from Microsoft. To be honest the Microsoft team is doing some real intense collaboration with the jQuery Core team from what I have observed. But that aside, lets see what we can do with this great new plugin.

The biggest problem with using Micro-Templates was the fact is was not in a real plugin format. Instead is requires sort of a loose group of functions. So I am really glad to see this progress to a much richer plugin format. Rather than reviewing all the cool new features, I will defer that to the actual templating plugin proposal that walks through the new functionality. I want to show how to update my WCF/jQuery sample code to use the new plugin.

The new plugin not only simplifies the data binding process, but it adds much more functionality than I had before at least in the plugin. So with all the great new features you should be real excited!

The first thing you need to update is the field delimiters from the <%=%> I have been using to {%=%}. This is a slight change from the previous syntax, which I was perfectly fine using. But they decided to change it for various reasons. But since this is still a Beta offering this syntax is subject to change, so pay attention in case it does.

The View Contacts page is the one page that needs to be updated to reflect these changes. There are two markup templates that need to be updated to the following:

<script id="ContactRowTemplate" type="text/html">

{% for(var i=0; i < Contacts.length; i++)
{
var contact = Contacts[i];
}
<tr>
<td>
{%=contact.FirstName%} {%=contact.LastName%}
</td>
<td>
{%=contact.City%}
</td>
<td>
{%=contact.State%}
</td>
<td><img src="images/edit.gif" onclick="GetNewContactInfo({%=contact.ContactId%});" /></td>
</tr>
{% } %}
</script>

<script id="ContactInfoDlg" type="text/html">

ol>
<li>
<label id="lblFirstName">
First Name :
</label>
{%= FirstName%}</li>
<li>
<label id="lbllastName">
Last Name :
</label>
{%= LastName%}</li>
<li>
<label id="lblAddr1">
Address :
</label>
{%= Address1%}
</li>
<li>
<label id="lblAddr2">
Address 2 :
</label>
{%= Address2%}
</li>
<li>
<label id="lblCity">
City :
</label>
{%= City%}
</li>
<li>
<label id="lblState">
State :
</label>
{%= State%}
</li>
<li>
<label id="lblZip">
Zip :
</label>
{%= PostalCode%}
</li>
<li>
<label id="lblPhone">
Phone :
</label>
{%= PhoneNumber%}
</li>
<li>
<label id="lblEmail">
E-Mail :
</label>
{%= EMail%}</li>
<li>
<label id="lblComment">
Comment or Question :
</label>
{%= Comment%}</li>
</ol>

</script>

That was not so bad, I even used Visual Studio’s search and replace functionality to make it go faster.

Next I added some new functions, only changing what I needed to change to utilize the new templating plugin. The NewProcessActiveContacts function looks like the following:

function NewProcessActiveContacts(response) {
if (!response) {
$("#dContacts").empty().html('No Contacts Returned');
return;
}

$("#dContacts").html($("#contactsTable").html());

if (response.Contacts) {

$("#ContactRowTemplate")
.render(response)
.appendTo("#tblContactList tbody");


$('#tblContactList tbody tr:nth-child(even)').addClass('evenRow');

}
$.unblockUI();
}

Before I talk about the template plugin application I want to point out that I placed the table markup into a script tag. This puts the markup in the page where it belongs, not the script. Instead I reference the script block containing the table skeleton and insert it in the dContacts DIV. The table markup is accessible by calling the jQuer html() method and passing that result to the html() method of the Contacts DIV.

$("#dContacts").html($("#contactsTable").html());

Now to the good stuff (finally). Instead of calling $.parseTemplate this time I call render. off the ContactRowTemplate script block. The render method accepts two parameters, data and an optional options. For this demo I do not need to pass any options. I will save that for a later post. The last step is to append the resulting markup to a DOM element. In this case that would be the TBODY in the results table. Ultimately this is a much cleaner pattern to follow than the previous pattern I have been using.

The next function that got updated is the DisplayNewContactInfo. Again the render function takes the contact object returned from the server and merges it into the template.

function DisplayNewContactInfo(response) {

if (!response || !response.ContactInfo) {
showErrorMsg('No Contact Returned');
return;
}

var dContactDlg = $('#dContactDlg');

if (dContactDlg.length == 0) {
$("<div/>", { id: 'dContactDlg' })
.appendTo("Body");

dContactDlg = $('#dContactDlg');
}

$.unblockUI();

dContactDlg.empty();
var contact = response.ContactInfo;

$("#ContactInfoDlg")
.render(contact)
.appendTo("#dContactDlg");

showContactDialog(dContactDlg);

}

There you have it, utilizing the new jQuery plugin to bind data returned from a WCF service method! I have updated the source project for you to download and try it out yourself.

Applauding Microsoft’s Shift to Improve jQuery!

One of the big announcement at MIX 10 besides the Windows Phone Development stuff was a new jQuery plugin to do data templating. This comes is some very welcome news for me. If you have followed me this year or caught one of my talks I have been spending a lot of time talking about jQuery to WCF messaging. In that demonstration I hope you have seen how I leverage John Resig’s Micro-Templating engine.

I don’t know if you were aware that the ASP.NET AJAX team has also been working on solving the template/data binding problem for AJAX developers. Personally I was not real thrilled with the solution they created because it relied way too much on controls and script injections. For me the most workable solution has been the micro-templates, but I knew there could be better. I had been thinking how to capitalize on the templating in the context of a plugin. Well sometimes you just have to let others that are smarter than you do your work. So during the Tuesday morning MIX10 keynote Microsoft and jQuery announced the templating plugin! More importantly the ASP.NET team announced their future efforts will not put anymore energy into ASP.NET, instead they will be focusing all their AJAX resources on adding to and improving jQuery.

It means that Microsoft is shifting its resources to invest in jQuery. Developers on the ASP.NET team are now working full-time to contribute features to the core jQuery library. Furthermore, we are working with other teams at Microsoft to ensure that our technologies work great with jQuery. – Stephen Walther

I am fully behind this move. The big winners in all this are the users of our sites. We as developers will now be able to developer much richer user experiences with less code and less effort. To me the ASP.NET AJAX framework was clumsy not only in the way you had to develop applications, but in the fat code it injected to the page, which led to a very poor user experience compared to other frameworks that were not tied to any server-side technology.

If you have not made an effort to start learning jQuery to this point I encourage you to do so. It is a rich, easy to use JavaScript framework that adds so much power to the client. Their is a vast and growing eco-system of jQuery plugiins available to solve just about any need you may have. In fact the biggest issue jQuery has is the large number of plugins you have to sort through to find the one that best meets your needs! A plugin is analogous to a control or more like a control extender really.

The following code shows how I use the Valdiator plugin in my WCF/jQuery sample application. In this example the first part is the DOM selector, in this case a FORM with the id of ContactForm. The validate ‘method’ is actually the call to the Valdator plugin. Here I pass in one of the possible parameters, a callback method to execute when the form is valid.

$("#ContactForm").validate({ submitHandler: function(form) {
StoreNewContact();
}
});

I have written about jQuery several times over the past year and plan on continuing with more posts on jQuery and applying it to ASP.NET web sites. But big kudos to the ASP.NET team for fully embracing jQuery and putting their resources behind this fantastic library!

Cures for the Common Ailments – Getting a Random Item in JavaScript

At the end of the day yesterday one of my peers at my client came over and asked me how to randomly select an item from a SharePoint List. She was retrieving the list using jQuery and only wanted to display one item from the list, but she wanted that item to be random each time the page was loaded. She felt it would ultimately be the simplest solution to do this on the client, and I agreed. Our problem really came down to our personal limits using JavaScript, neither of us had done anything with random yet. I knew there had to be some pseudo-random number generator available, I have not met a modern language that does not have something to offer random yet.

Turns out JavaScript does have a random function that is a member of the Math object. I looked at a few uses of this function and decided using it with Math.floor() would produce the result we were after.

First, Math.random produces a ‘random’ value between 0 and 1. But we needed to randomly select an array item, which would be an integer index between 0 and the length –1. So multiplying the random result by the array’s length will almost produce the index value desired. Passing the value to the Math.floor method will round the result down to the closest integer value. Now we have a ‘random’ integer value that can be reliably used to select an item from the array of items. The following code is an example of how to test this methodology:

<script type="text/javascript" charset="utf-8">
$(document).ready(function () {

var temp = ['1', '2', '3', '4', '5', '6'];

$("#container").html((temp[get_random(temp.length)]));

});

function get_random(max) {

if (undefined === max) {
max = 5;
}

var ranNum = Math.floor(Math.random() * max);
return ranNum;
}
</script>

So back to the original problem. My co-worker is retrieving a SharePoint list from the web service APIs. This list should be represented as an array of object literals (assuming it is not a simple list of strings) in JavaScript. So instead of an array of strings she will be selecting an object literal and displaying values from that object. I am sorry I don’t have a full blown demo of deserializing a SharePoint list, but if you refer to my recent post on using jQuery to communicate with WCF services you can see how to consume a list of objects in the example to retrieve a list of active contacts from the server.
WCF and jQuery Exception Handling

Now that I have covered the basics of calling a WCF service using jQuery’s AJAX functionality with JSON its time to deal with bugs. Yep, we all create them and have to troubleshoot them on a daily basis. Even if you are not actually coding the WCF service you need to know how to deal with any exception that may be bubbled back to the client when you call a service API method.

If you remember there were a few items I referenced in the previous post on the jQuery side of this transaction to deal with errors. The first is a DIV element to hold any error messages you may want to display to the user called AJAXError. In the jQuery Ready method I told this element to response to the global ajaxError event handler by displaying some diagnostic information to the user.

$("#AJAXError").ajaxError(function(event, request, settings) {
$(this).append("Error requesting page " +
(settings.url) ? settings.url : '' + "<br/>http Status Code: " +
(request.status) ? request.status : '' + "<br/>http Status:" +
(request.statusText) ? request.statusText : '');
});

Now in production I do not recommend displaying a message like this to the end user. I will discuss ways to handle this more gracefully later.

AJAX Error handling

The next item included in the sample code is a generic OnPageError method that is executed in the .ajax error callback method. You can either call this directly or inside a more custom error handler. I want to point out there are three parameters it processes, one for the XMLHttpRequest object, the is a string that describes the error and finally an exception object if any.

The following code snippet shows a basic error processing event handler. The showErrorMsg method in this example is designed to display an appropriate message to the user. But in reality the OnPageError method should be much more complex to process all sorts of scenarios

function OnPageError(xhr, errorMsg, thrown) {
if (typeof xhr == "string") {
showErrorMsg(xhr);
return;
}else if (typeof (xhr.responseText) == "string" && xhr.responseText != "")
{
showErrorMsg(xhr.responseText);
} else {
showErrorMsg("Unknown error occurred in callback.");
}
}

An example of a custom error callback that eventually calls the OnPageError method is below, it closes the processing message to make the page available again. You may need to clean up some things depending on your needs like the example below. This is why I like creating a custom callback method instead of passing the OnPageError method directly. Click the image below to see the detail of the XMLHttpRequest object when a typical exception is thrown.

XMLHttpRequest Error handling

One thing you need to realize is JavaScript is very flexible and when an error is thrown in the AJAX process you may not get all these parameters, it might just be the errorMsg parameter or the thrown (exception object) parameter. This is why you need to build out an even more robust routine to process the parameters. A more robust method would process an exception object. If an exception is bubbled up through the WCF service it will be serialized, in our example it will be a JSON object. This means we can parse the exception object and handle it more gracefully.

function OnPageError(xhr, errorMsg, thrown) {

if (typeof xhr == "string") {
showErrorMsg(xhr);
return;
}
else if (typeof (xhr.responseText) == "string" && xhr.responseText != "") {
var err = JSON2.parse(xhr.responseText);

switch (err.ExceptionType) {

case 'System.Exception':
showErrorMsg(err.Message);
return;
default:
showErrorMsg(xhr.responseText);
return;
}
} else {
showErrorMsg("Unknown error occurred in callback.");
}

}

Since it is a JSON object you can simply use the JSON2.parse method to hydrate the object and then process it as if it were on the in the .NET code you are use to working with.

error: function(xhr, errorMsg, thrown) {
$.unblockUI();
OnPageError(xhr, errorMsg, thrown);
}

Great now you can gracefully handle exceptions for the user, what should you do now to figure out the bug and squash it? First realize an exception could be thrown in one of two places; the client or the server (inside the web service). The first order of business is to determine what side of the request the issue resides.

The first place to look is the Http Status code sent from the server. If you have a 500 value it was the server. If you don’t have a value or it is 200 or another non 500 series value the odds are it is in the client code. I make a lot of typos when I am typing from scratch, so those have gotten me quite a bit in my learning process. Often it was simply an improper case since JavaScript is very strict when it comes to casing. So knowing if it is in the service or the JavaScript is real important to solve the issue.

I primarily work in Internet Explorer, so the first place I tend to look is the development tools and take advantage of the fantastic debugging facilities built into the browser. I reviewed these techniques in a previous post. If you are working in FireFox Firebug is your friend. Other browsers may their own idiosyncrasies, so you may need to look into the debugging tools for that specific browser if you get real desperate.

XMLHttpRequest Error handlingAnother tool I use to track down errors or just unexpected behavior with AJAX is Fiddler. Remember when working against the localhost you must place a period before the port directive in the URL like this: http://localhost.:23168/errorDemo.aspx. The Fiddler Inspectors tab gives you keen insight to see the exact messages being passed back and forth between the browser and the server.

Finally you can always set break points both in the JavaScript and your server-side code in Visual Studio and step through your code.

Above I show a basic OnPageError event handler, the sample application has a page that deliberately creates an exception in the AJAX call. The service method just throws a new Exception with a custom message, nothing fancy for the demo. The error callback is invoked by the JQuery ajax method. It passes an instance of the XHttpRequest object, an error message and if it was thrown.

 

function BlowUp() {

wjBlockUI();

ContactServiceProxy.invoke({ serviceMethod: "BadMethod",
callback: function(response) { ProcessBlowReturn(response) },
error: function(xhr, errorMsg, thrown) {
HandlerBlowUpError(xhr, errorMsg, thrown) }
});
}

So I hope you have a little more insight into how to troubleshoot errors you may be having in your AJAX development. If you have other suggestions I invite you to share them in the comments.

Using JQuery and JSON to Interact with a WCF Service via AJAX

Yesterday’s post reviewed how to setup a WCF web service to work with JSON from top to bottom. Today I am going to review what needs to be done to use JQuery to work with those WCF end points. If you have not already done so please download the example code so you can really follow along. This demonstration shows a simple web site with a contact form, an admin type page to display a list of contacts and a full contact upon selection. It also contains a page to demonstrate how exceptions can be handled. The exception page will be explained in a future post.

Lets get right to it by opening the ContactUs.js file. At the very top there is a ContactInfo object defined. The members of this object match the members of the corresponding ContactInfo class in the class library we reviewed yesterday. The default value for each member is also define to an empty string.

var ContactInfo = { 
FirstName: '',
LastName: '',
Address1: '',
Address2: '',
City: '',
State: '',
PostalCode: '',
Business: '',
PhoneNumber: '',
EMail: '',
Comment: ''
}

The reason I defined this object at the top and on a ‘global’ scope is because it will be used in multiple functions later and I do not want to repeat the code over and over.

Before I go any further in the file I want to point out the dependant files for this script to actually function. First I decided to use the latest JQuery 1.4 library. It was just released and I felt this would be a great opportunity to test it out. All the code should work with the previous release to my knowledge. I am not doing anything in this script that has not worked with v 1.3.x in the past.

The next important dependency is the JSON2.js library created by Douglas Crockford and modified by Rick Strahl. It makes working with JSON objects a breeze in JavaScript. A quick side-bar here; Internet Explorer 8 and the latest version of FireFox have native JSON serialization built into their JavaScript engines. Unfortunately I do not like to be locked into the browser specific things like that so I rely on the JSON2 library. In the future, once all the relevant browsers have this ability we will probably change, but I bet we will need an abstraction layer even then.

Rick updated the original JSON library create by Crockford to handle odd date formatting issues created by MS AJAX library.

Other JQuery plugins include the BlockIU, to display Please Wait messages, and the validation and masked input. I have review the latter two last year.

I am going to skip around the ContactUs.js file for now, so bear with me. First the Ready function, it defines some basic setup functionality like input masks, table striping and default buttons etc. Below that it defines some behavior to display some stock messages for global JQuery AJAX events.

The ajaxError event handler gives you the ability to ‘hook’ into the pipeline to define your own actions to take when an exception is thrown by the server or any other instance where there is an Http Status code of 500 generated by the server or a request timeout occurs. For this demonstration I have simply created a DIV to hold these error messages.

$("#AJAXError").ajaxError(function(event, request, settings) { 
$(this).append("Error requesting page " + (settings.url) ?
settings.url : '' + "<br/>http Status Code: " +
(request.status) ? request.status : '' + "<br/>http Status: "
+ (request.statusText) ? request.statusText : '');
});

var ajaxLog = $("#ajaxLog");

ajaxLog.ajaxStart(function(evt, request, settings) {
var dt = new Date();
$(this).append("<br/><hr/>Starting request... " + dt.toLocaleString());
});

ajaxLog.ajaxComplete(function() {
var dt = new Date();
$(this).append('<br/>Triggered ajaxComplete handler.' + dt.toLocaleString());
});
ajaxLog.ajaxSuccess(function() {
var dt = new Date();
$(this).append('<br/>Triggered ajaxSuccess handler.' + dt.toLocaleString());
});

I also added an ‘ajaxlog’ DIV to the site’s master page. The code above builds a log of when an AJAX request is initiated, completed and successful. This is done with a simple timestamp.

<div id='container'> 
<div id="AJAXError" class="Error-Message-Area">
</div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
<br />
<hr />
<div id="ajaxLog">
</div>
</div>

Now scroll down almost to the bottom of the ContactUs.js file till you find the object definition for serviceProxy. I am going to defer a detailed explanation of how this object functions to Rick Strahl since he has already written about the serviceProxy helper object. I did enhance it a little by allowing you to pass in a set of options and defaults to define how an AJAX call is made.

// *** Call a wrapped object 
this.invoke = function(options) {

// Default settings
var settings = {
serviceMethod: '',
data: null,
callback: null,
error: null,
type: "POST",
processData: false,
contentType: "application/json",
timeout: 10, //Not Preferable, but needed for now.
dataType: "text",
bare: false
};

if (options) {
$.extend(settings, options);
}

This makes the invoke method more flexible by letting you define custom settings depending on your needs. In my case I realized the application I was working on had some non-optimized methods that were causing timeouts the first time they were run. Instead of wasting time chasing these issues on the client end I decided to extend the timeout setting to 2 minutes (I know super long, but it was needed). Normally I would set this value to 10 seconds or less. So as I add new method calls I set the value appropriately.

Before I go on you may be wondering why Rick chose to create a serviceProxy object instead of just calling the JQuery.ajax method directly. Well by creating an object you only have to create one instance of the object and it can retain common variables during the lifetime of the page. This especially comes in handy when you are calling more than one service on a page.

There are really two members of the serviceProxy object you need to be aware of; the ServiceURL value and the invoke function. The ServiceURL value is the URL to the WCF service you are calling.

var ContactServiceURL = "ContactUs.svc/";
var ContactServiceProxy = new serviceProxy(ContactServiceURL);

The invoke method, which I showed the top part above, actually makes the AJAX call based on the options you passed to the method. The $.ajax() success option is a callback function that is executed when the service responds to the client. In the case of serviceProxy a function is executed. It does some error checking before it executes the actual callback method you may have defined in your options. It calls the JSON2 parse function to deserialize a JavaScript object and passes the object to your custom callback.

success:
function(res) {
if (!settings.callback) { return; }

// *** Use json library so we can fix up MS AJAX dates
var result = JSON2.parse(res);

if (result.ExceptionDetail) {
OnPageError(result.Message);
return;
}

// *** Bare message IS result
if (settings.bare)
{ settings.callback(result); return; }

// *** Wrapped message contains top level object node
// *** strip it off
for (var property in result) {
settings.callback(result[property]);
break;
}
}

Below is a code snippet from the example code where the serviceProxy invoke method is called to retrieve a ContactInfo object. Three parameters are set in the call, serviceMethod, data and callback. If you do not need to pass an object to the service, for example GetActiveContacts the data does not need to be set. The serviceMethod value should be set because it is the name of the method being called, otherwise you will not get the response you expect.

ContactServiceProxy.invoke({ serviceMethod: "GetContact",
data: { request: request },
callback: function(response) {
...//Do Work Here
}

The next key thing I need to discuss is how to deal with the data once you have received it on the client. This is where John Resig’s  parseTemplate function comes in real handy. I found it looking around for templating solutions and sort of fell into a chain of three Blog posts by Stephen Walther –> Rick Strahl –> John Resig.
 
http://weblogs.asp.net/dwahlin/archive/2009/04/17/minimize-code-by-using-jquery-and-data-templates.aspx
http://www.west-wind.com/Weblog/posts/509108.aspx
http://ejohn.org/blog/javascript-micro-templating/

The parseTemplate plugin/function accepts one parameter, data. this is your deserialized object. It magically merges the object into a template you define.

dContactDlg.empty().html($("#ContactInfoDlg").parseTemplate({ contact: response.ContactInfo }));

Where does this template reside? For this demonstration I decided to create script objects in the HTML.  This is a little trick I learned from the above posts. You can even place loops and other scripting conventions in the templates, which is really cook for tabular data (see GetActiveContacts). You just need to place a merge tag for your object and property like this <#=contact.FirstName#> in your template and the parseTemplate function will merge the value into the template and create the string of markup with your values in place.
 
<script id="ContactInfoDlg" type="text/html">
   1:  
   2: <ol>
   3:     <li>
   4:         <label id="lblFirstName">
   5:             First Name :
   6:         </label>
   7:         <#=contact.FirstName#></li>
   8:         ...    
   9:     <li>
  10:         <label id="lblComment">
  11:         Comment or Question :
  12:         </label>
  13:         <#=contact.Comment#>
  14:     </li>
  15: </ol>
</script>

The last thing I want to touch on is error handling. Even though I placed a global $ajaxError handler in the .ready function, I use a custom error handler for each AJAX call. The error setting of the .ajax function is a function that receives three parameters. I followed the example set by Rick again and have an OnPageError event handler function, but often I need to place some clean up code in the handler. In the following example I close the ‘Processing…’ message I display using the BlockUI plugin. Otherwise it would remain on the page. I can’t just assume it was displayed either and close it in the general handler, so I need to deal with it for each call.
 
error: function(xhr, errorMsg, thrown) {
$.unblockUI();
OnPageError(xhr, errorMsg, thrown);
}

I will go into more detail on dealing with AJAX exceptions in my next post. So keep an eye out for that post. I also have posts planned for AJAX debugging techniques and unit testing examples.
Creating a WCF Service for JSON

Saturday I gave a presentation for the first time at the Southern California Code Camp on how to use JQuery to perform AJAX operations against a WCF Endpoint. Today I want to review how to create a WCF service that supports JSON and how to properly create messages that can be serialized to and from JSON.

The first step is to add a WCF Service to a web site, typically this will be your actual web site but it does not have to be. Your architecture will vary by application requirements and network security rules. Even behind the firewall you may have cross domain scripting restrictions, etc. Adding a WCF Service to the site in Visual Studio gives us a .svc file, but it also creates content we need to remove.

Visual Studio 2008 and .NET 3.5

Since Visual Studio 2010 is just around the corner I want to try and break the two experiences apart. I have a follow up post using Visual Studio 2010 planned in a few days. Select ‘WCF Service’ from the Add new Item dialog. This adds the .svc file to the web site, but it also adds two files and some unneeded sections to the web.config file as well.

First the files, a code file (.vb or .cs) is added to the project that defines the interface implemented by the service. It also includes some minimal attributes to tell WCF how to use the service. A code-behind file is also added to the .svc that implements the service. Both of these files can be used as is, however I like to remove these files. Instead I prefer to create a class library containing the code for both the interface and class implementation. In the long run this is a much cleaner way to manage the code for your WCF services. First it makes it easier to create unit tests for the code, which I will cover in another post. Second it gives you a certain flexibility to add another provider that implements the service interface. As you will see this does not make life any harder for us, it just requires the service’s web site to reference the class library.

The web.config file has also become polluted because unneeded behaviors, services and endpoint sections have been added to the system.serviceModel section. The following is example configuration that was added, it can simply be removed from the file.

<behaviors>
  <serviceBehaviors>
    <behavior name="Web.TestsvcBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service behaviorConfiguration="Web.TestsvcBehavior" name="Web.Testsvc">
    <endpoint address="" binding="wsHttpBinding" contract="Web.ITestsvc">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="basicHttp" maxReceivedMessageSize="2147483647">
      <security mode="None"/>
    </binding>
  </basicHttpBinding>
</bindings>

Ultimately this comes down to the configuration of the services and I am not bashful to admit I know very little about WCF configuration. I have people for that . So here is where I am going to punt and say just trust me this works great.

The only thing left is to update the actual .svc file to use the correct service implementation and factory. This is an example of the directive in the default .svc file.

<%@ ServiceHost Language="C#" Debug="true" Service="Web.Testsvc" CodeBehind="Testsvc.svc.cs" %>

The following is an updated version of the file that points the Service to the service implementation class. It also tells the service to use the WebScriptServiceHostFactory, which tells WCF to use web protocols and adds the JSON serialization we need to make our service work with JQuery AJAX.

<%@ ServiceHost Language="C#"
    Service="WCFJQuery.ContactBLL.Implementation.TestSvc"
    Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>

The Class Library

The next step is to add a class library to actually implement the service if you do not already have one. I like to organize the files into folders describing their purpose. You can organize how you would like, it is all a matter of personal productivity. I like to have a Contracts folder that contains the service interfaces, I use the plural here because often you will have more than one WCF service in your application.

The WCF attributes depend on a reference to the System.ServiceModel dll, so you should go ahead and add it up front, unless you are using a tool like R# that will add it for you when you add the first WCF attribute. The first file to add is the service interface. The example I use in my presentation is a simple contact form, so the service is called ContactUs. The corresponding interface is IContactUs.cs.

If you remember the attributes included with the interface file you deleted in the web site, the class was adorned with a ServiceContract attribute. This time we will define the full namespace of the interface, the name of the service, SessionMode and ProtectionLevel. For our purposes the following work for my service.

[ServiceContract(Namespace = "urn:WCFJQuery.ContactBLL.Contracts",
    Name = "ContactUs",
    SessionMode = SessionMode.NotAllowed,
    ProtectionLevel = ProtectionLevel.None)]

Now we can add the members of the service interface. For the sample application there are 4 methods; PostNewContact, GetContact, GetActiveContacts and BadMethod. Each method has a definition like the following:

[OperationContract(IsTerminating = false,
    IsInitiating = true,
    IsOneWay = false,
    AsyncPattern = false,
    Action = "PostNewContact",
    ProtectionLevel = ProtectionLevel.None)]
PostNewContactResponse PostNewContact(PostNewContactRequest request);

 

Now we can add the class to implement the service. I place this file in the Implementation folder because this file implements the service. We will add some more files here in a second. The ContactUs.cs file contains this file. The ContactUs class implements the IContactUs interface, it also has a ServiceBehavior attribute adorning it. In this demo the IncludeExceptionDetailInFaults property is set to true. This means exception messages will be bubbled through the service using the proper serialization for the client request. In this case it means our JQuery will get a JSON data object it can parse for us.

The class members don’t require any attributes. You can quickly auto implement those by either using the SmartTag on the interface name or with a tool like R# or CodeRush.

At this point you should have a bunch of references to classes that don’t exist yet. We need to create them. They are also added to the Implementation folder. This is where things get highly customized to your particular needs. By that I mean each one of these classes is a message class. It contains the body of the message, which typically is the contents of the request or the response.

Before I loose you here, this is something that took me a bit to comprehend at first. WCF and SOA architecture is about messaging and passing objects around. Typically each service method accepts a request object and returns a response object. In the case of GetActiveContacts it does not accept any request object.

I always like to get a response object back to check on the client. This is where I differ from some who focus on the WCF side of the application. The first situation I found myself wanting this was on a method that added a new object to the data store. The author of the service method did not return any confirmation value, or any value at all, just a null value. His reasoning was if it did not work it would have thrown an exception. I think this is a bad practice for any code, you should not rely on just bubbling an exception to the client. Instead you should catch the error and return something meaningful to the client. You can read more about that in Brad Abrams book.

Lets get back to the code at hand by examining the request object for retrieving a specific contact record. The service method requires a ContactId, which is the business key for a contact object.

Another side-bar here, notice I am not referring to a contact record, this is because modern application are querying a data model and not the database anymore. So think Entity Framework, oData or nHibernate. An actual contact object may be composed of values contained in several tables such as person, address, phone, email etc.

The GetContactRequest has to be serialized by the WCF engine, thus we need to add a a DataContact attribute to the class and DataMember attribute for each member. In this attribute the name of the member is defined. It could be anything we want, just remember it is the name you need to reference on the client. Next we need to specify this value is required, otherwise we would make the request without specifying the record we want. Finally the Order is set to 0. This tells the serilizer to add this value first or to the 0 index of the serialized object.

using System.Runtime.Serialization;

namespace WCFJQuery.ContactBLL.Implementation {

[DataContract(Namespace = "urn:WCFJQuery.ContactBLL.Implementation",
Name = "GetContactRequest")]


    public class GetContactRequest {

        [DataMember(Name = "ContactId", IsRequired = true, Order = 0)]
        public int ContactId { get; set; }

    }
}

On to the response object; GetContactResponse. Again you need to reference the Serialization namespace and add the attributes. This class also only includes a single object; a ContactInfo class.

using System.Runtime.Serialization;

namespace WCFJQuery.ContactBLL.Implementation {

    [DataContract(Namespace = "urn:WCFJQuery.ContactBLL.Implementation",
Name = "GetActiveContactsRequest")]
    public class GetContactResponse {

        [DataMember(Name = "ContactInfo", IsRequired = true, Order = 0)]
        public ContactInfo contactInfo { get; set; }

    }
}

The ContactInfo class also needs to be serialized. So again you need to add attributes to manage this process. The ContactInfo class contains more than one member this time, some required, some not required. This time you will notice the index of the value increasing from 1 to 11.

using System.Runtime.Serialization;

namespace WCFJQuery.ContactBLL.Implementation {

    [DataContract(Namespace = "urn:WCFJQuery.ContactBLL.Implementation",
    Name = "ContactInfo")]
    public class ContactInfo {

        [DataMember(Name = "ContactId", IsRequired = false, Order = 0)]
        public int ContactId { get; set; }

        [DataMember(Name = "FirstName", IsRequired = true, Order = 1)]
        public string FirstName { get; set; }

    ...

        [DataMember(Name = "Coment", IsRequired = true, Order = 11)]
        public string Comment { get; set; }

    }
}

The process for the remaining request and response objects is the same. Remember any objects that are being passed in or out need to have serialization attributes defined. You are not required to add your contact or implementation classes to a class library, but as you will see in future posts it makes it much easier to test your code.

At this point we have a fully functioning WCF web service that will naturally accept and return JSON objects that can be used on the client. So in the next post I will review the infrastructure and patterns for making AJAX calls using JSON to a WCF service.

Source Code

WCF and JQuery Using JSON

What a wonderful showing yesterday at the SoCal Code Camp in Fullerton for both of my sessions. One thing I definitely learned is making AJAX calls to a WCF service with JQuery is in high demand and 60 minutes does not do it justice! Thanks for all the great interactions and sorry I did not have a chance to get my code and slide deck posted before the session, but I finally found some bandwidth that does not block the FTP port :).

For those of you not at the Code Camp session yesterday my first presentation was on making AJAX calls to WCF service methods using JQuery. This involves configuring your WCF service correctly, leveraging the JSON2 library, John Resig’s micro-Templating function and some JQuery and JavaScript magic dust.

I will post some write ups on what is going on in the code as the week progresses. I have just been too pressed for time lately to get things written, but should have time tomorrow. But for now you can download the source code for accessing WCF services using JSON via JQuery from here. The slide deck is on SlideShare.com, I will most likely be updating that over the next month now that I have given the session once and gotten great feedback.

Again thanks for everyone with the SoCal Code Camp, it was well worth the trip across the country to hang out with ya’ll.

First Quarter 2010 Speaking Schedule

Last week I wrote about voting for my MIX sessions, and if you have not voted for me, then why not? Go now and vote, you can come back afterwards and keep reading, I’ll wait. Meanwhile I wanted to publish my upcoming speaking dates. I am going to be at the Southern California Code Camp the weekend of Jan 30th at Cal St Fullerton. Next month I am speaking at the South Florida Code Camp in Miramar FL. Finally in March I am planning on speaking at the New York City Code Camp, they just announced a call for speakers last week so that is still in the works. And of course, if you vote for my sessions MIX!

So Cal Code Camp -  Jan 30-31st

South Florida Code Camp – Feb 27th

NYC Code Camp – March 6th

And of course I will be attending the MVP Summit next month and MIX in March, but still vote for me!

Vote for Chris Love in the MIX Open Call

Vote for Chris Love in the MIX Open CallThis year MIX is letting you, the community, determine some of the content available during the conference. I, along with many others submitted different sessions to be voted on by, well anyone! You can choose up to 5 sessions. Voting closes on January 15, 2010 and you can read more about the MIX Open Call on their web site. I submitted three sessions to the mix, Lightweight WebForms, JQuery and WCF: Going Beyond the UpdatePanel, Throwing Out Your Tables: CSS Layouts for Developers, Playing Small Ball: Making ASP.NET Sites for Mobile Phones. Each of these sessions are brand new for me and inline with areas I want to focus this year or spent a lot of time on in the recent months. I think they are all about user experience development and areas we as ASP.NET developers need to learn more about to be competitive going forward.

Throwing Out Your Tables: CSS Layouts for Developers

This session will be all about doing table less layouts. I will focus doing page layouts, navigation and tricks of creating good form layouts that can be repeated over and over.

Playing Small Ball: Making ASP.NET Sites for Mobile Phones

Mobile devices, phones, etc are all over the place now and it is time we start making our web sites render in a usable format for these devices. I am making this a priority to learn over the next year. In this session I am going to review best practices for creating sites to work nicely on smaller screen devices.

Lightweight WebForms, JQuery and WCF: Going Beyond the UpdatePanel

If you followed my Thin ASP series over the past year you saw how I used custom httpHandlers with my JQuery AJAX calls. I am going to take it to the next level by showing how to easily integrate WCF services and true messaging patterns with JQuery AJAX.

So vote early!!! There are lots of great sessions and speakers to choose from, just choose my sessions :)

New Decade, New Challenges and Opportunities

Happy New Decade!!! Its hard to believe I have reached my 4th decade here on Earth, but I have. The last decade was full of challenges, good times and many bad. New Years morning I received confirmation I have received the ASP.NET MVP award for the third straight year, which is a great thing! I feel honored to receive this award each and every year, not because I think I deserve it, but because it is an appreciation from Microsoft for a lot of unpaid work I and many others put into community and all around sharing. Generally MVPs do not participate merely to get the award, but do so because they have a passion for their technology and share it with others, both the good and the bad.

With that out of the way, I have plans for 2010 already in place. I really see three things being my primary focus this year, Mobile Web Sites, CSS and JQuery and how to build the best user experiences on the ASP.NET platform. I have a realistic plan I have drawn up over the Christmas break that I believe is achievable. I will start posting some blogs on these topics soon. I have already started with CSS and JQuery in 2009, but a focus on the mobile platforms will be new. Other things I foresee learning more about and using is ASP.NET MVC and WCF.

The main reason I see my plans as being achievable is due to the philosophy I am enjoying with my new company, Tellago. I started as a full-time employee in early November and have been positively surprised every week. Jesus Rodriguez, Don Demsak, Pablo Cibraro and the rest of the team have just been nothing but a pleasure to work with. Not only are they smart and good at what they do, they are really helping me learn things about SOA development I just never contemplated. But more than that they see value in my personal pursuit of the things I am good at and enjoy as well as their own. I cannot explain the night and day difference I am having with Tellago over what I had at my previous consulting firm (and I use that term lightly). Tellago is a rapidly growing company, with a clear plan for the next year and has the talent and collection of driven people to achieve our plans and probably more in 2010.

Creating a Twitter Like TextBox Character Warning Using JQuery

The other day I gave an intro to JQuery Lunch and Learn to my client’s development team. I walked them through creating a simple JQuery Plugin to create a character remaining feature like Twitter has on its web site.

The ingredients for this plugin involved a textarea field (but you could just use an input field if you really wanted) and assigning the plugin to the textarea.

<script src="jquery.limitcharacters.js" type="text/javascript"></script>
   1:  
   2:     <script type="text/javascript">
   3:         $(document).ready(function() {
   4:  
   5:         $('#txtWhatAreYouDoing').limitCharacters();
   6:  
   7:         });
</script> <textarea id="txtWhatAreYouDoing" name="txtWhatAreYouDoing" cols="50" rows="3"></textarea>

The plugin itself is composed of what I think of as 3 segments. The first allows you to define options, which as then mapped to an internal JavaScript object called settings with default values defined.

// Default settings
var settings = {
    charLimit: 50,
    showRemaining: true,
    remainingClass: 'remainingChars',
    remainingWarnClass: 'remainingCharsWarn'
};
if (options) {
    $.extend(settings, options);
}

The next section simply appends a SPAN to display the remaining characters as the user types in the field.

this.after("<span id='CharsLeft'></span>");

Now the real guts of the plugin! It intercepts the keyup event of the textarea and counts the number of characters used. If the number of characters is over the limit (settings.charLimit) it truncates to the maximum number of characters.

this.keyup(function() {
    var len = $(this).val().length;
    if (len > settings.charLimit) {
        this.value = this.value.substring(0, settings.charLimit);
    }

...

}

Next it gets the number of characters left and sets the value of the SPAN added earlier.

var charsLeft = settings.charLimit - len;

if (charsLeft < 0) {
    charsLeft = 0;
}

$('#CharsLeft').text(charsLeft + " characters left");

Finally it sets the style of the remaining character SPAN by determining if there are fewer than 10 characters remaining. It does this by leveraging the hasClass, addClass and removeClass JQuery utility methods.

if ((settings.charLimit - len) > 10) {
    if (!$('#CharsLeft').hasClass(settings.remainingClass)) {
        $('#CharsLeft').addClass(settings.remainingClass);
    }
    if ($('#CharsLeft').hasClass(settings.remainingWarnClass)) {
        $('#CharsLeft').removeClass(settings.remainingWarnClass);
    }
} else {
    if (!$('#CharsLeft').hasClass(settings.remainingWarnClass)) {
        $('#CharsLeft').addClass(settings.remainingWarnClass);
    }
}

The CSS classes used look like this:

.remainingChars
{
    font-family: Arial, Helvetica, sans-serif;
    font-size: 2.5em;
    font-weight: bold;
    color: #666666;
}

.remainingCharsWarn
{
    color: #660033;
}

Putting it all together gives us a nice little plugin.

The full plugin source:

jQuery.fn.limitCharacters = function(options) {

    if (this.length == 0) return;

    // Default settings
    var settings = {
        charLimit: 50,
        showRemaining: true,
        remainingClass: 'remainingChars',
        remainingWarnClass: 'remainingCharsWarn'
    };
    if (options) {
        $.extend(settings, options);
    }

    this.after("<span id='CharsLeft'></span>");

    this.keyup(function() {
        var len = $(this).val().length;
        if (len > settings.charLimit) {
            this.value = this.value.substring(0, settings.charLimit);
        }

        var charsLeft = settings.charLimit - len;

        if (charsLeft < 0) {
            charsLeft = 0;
        }

        $('#CharsLeft').text(charsLeft + " characters left");

        if ((settings.charLimit - len) > 10) {
            if (!$('#CharsLeft').hasClass(settings.remainingClass)) {
                $('#CharsLeft').addClass(settings.remainingClass);
            }
            if ($('#CharsLeft').hasClass(settings.remainingWarnClass)) {
                $('#CharsLeft').removeClass(settings.remainingWarnClass);
            }

        } else {

            if (!$('#CharsLeft').hasClass(settings.remainingWarnClass)) {
                $('#CharsLeft').addClass(settings.remainingWarnClass);
            }

        }

        return this;

    });


}
Resetting Focus After Selecting a Date with the JQuery UI DateSelector

If you have been using JQuery I hope you have started using the JQuery UI library. I use the JQuery UI Datepicker plugin to left users select a date from a calendar when they enter a date input field. The plugin works great, but an issue was raised by a user this morning that I had to also solve on with my previous client.

The customer is in the process of migrating from an old school main frame terminal to the more modern web application we were building them. Their normal user experience means tabbing between input fields. The user pointed out that once they selected the date from the datepicker the TAB focus was reset to the top of the DOM. This was not good because the user’s normal flow was broken at this point.

The solution was to set the focus of the page back to the input field in the Datepicker’s onClose event handler.

$(".datePicker").datepicker({ showOn: 'button',
        buttonImage: '../Images/Calendar.png',
        buttonImageOnly: true, onSelect: function() { },
        onClose: function() { $(this).focus(); }
        });

The focus from the input field was lost because once the user clicked the date in the calendar the immediate DOM element went from the input field to the calendar, which is not actually part of the form. It is just another page element that is removed from the DOM once the selection is made. Once the calendar is removed from the page, the browser now sets the immediate focus to the top actionable element in the DOM, thus interrupting the user’s process flow. Intercepting the onClose event gives us the flexibility to reassert focus to the input field and the user can continue as normal.

Finally, notice how the showOn setting is ‘button’. When the showOn setting is either ‘focus’ or ‘both’ the calendar is displayed as soon as the user enters the field. It also means setting the focus back to the input field when the calendar closes will cause the calendar to be redisplayed. I tried a few work arounds to correct this, but could not find a way to fix it. Alas I think to make it a true fix will require fixing the plugin itself to meet this user requirement 100%.