JQuery Addons: dataTables (a JQuery GridView)

As a .Net developer who likes a screaming fast user interface, programming in .Net can be frustrating if you are one of the teeming millions that use a GridView.  Perhaps you’ve dabbled in .Net extensions over the years such as Infragistics, Telerik, or DotNetNuke.  If you were not satisified with any of that, you probably were very happy when you found JQuery, and like a beacon in the fog you stumbled towards the subsonic AJAX calls they had told us about years ago…

As great as JQuery is though, it’s not easy to do everything you want out of the box.  Enter Allan Jardine’s wonderful add-on: DataTables.  It’s really just that.  A “magical” link between your well defined HTML tables and four ways to populate them with data really quickly.

This walk through will discuss the necessary pieces to incorporate this.  It also builds off a previous blog, JQuery to web service ajax, so I’ll skip the details around that.

First thing you need is to link to the following files or download them:

Now you need to do some prep work to get the table squared away.  First, define your target HTML table:

         <table id="tblAwesomeSauce" width="700px">
        <thead>
        <tr>
        <th>Header 1</th>
        <th>Header 2</th>
        <th>Header 3</th>
        <th>Header 4</th>
        <th>Header 5</th>
        <th>Header 6</th>
        <th>Header 7</th>
        <th>Header 8</th>
        </tr>
        </thead>
        <tbody id="tblAwesomeSauce-body">
        <tr>
        <td colspan="4" class="dataTables_empty">
        Loading data from server
        </td>
        <td />
        <td />
        <td />
        <td />
        <td />
        <td />
        <td />
        </tr>
        </tbody>
        </table>
        <div id="tblAwesomeSauce-noresults">There is no data</div>

 

Now, we’re going to jump to the bottom of your page and create the Template columns for later use.  Two things of note: Put it below the </Form> tag and don’t be sad when Intellisense does not pick this up.

    <script id="tblAwesomeSauce-row" type="text/html">
      <tr>     
<td><a href='#' onclick='openPopUp1(${value1},${value2}); return false;' >Click here 1</a></td>
<td><a href='#' onclick='openPopUp2(${value1},${value2}); return false;' >Click here 2</a></td>
<td>${value1}</td>
<td>${value2}</td>
<td>${value3}</td>
<td>${value4}</td>
<td>${value5}</td>
<td>${value6}</td>    
      </tr>
    </script>

CAVEAT! If the number of columns between your HTML table header/rows and your Template row do not match, your data will likely not show up, and you will be sad that you forgot this simple gotcha.

Create a button or something to wire this event up to, and then let’s head up to your JQuery code.  Here’s what a complete set of instructions could look like.  Take a look and then we’ll discuss them:

<script language="javascript" type="text/javascript">
        $(document).ready(function () {
            //For more info on wiring up a GridView OnClick event to get the row id: 
            //http://aspdotnetcodebook.blogspot.com/2010/01/page-languagec-autoeventwireuptrue.html
            $('#<%# radGrid1.ClientID %>').find("tr").click(function (event) {
                var id = $(this).find("td:first").text();
                fillGrid(id);
            });
            $('#tblAwesomeSauce').dataTable({
                bJQueryUI: true,
                bFilter: false,
                bPaginate: false,
                bSort: false,
                bInfo: false
            });
        });
        function fillGrid(id) {
            $.ajax({
                type: 'POST',
                url: 'yourWebService.asmx/GetData,
                data: "{id:'" + id + "'}",
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function (msg) {
                    fillGridSucceeded(msg);
                    setTimeout("fillLoansGrid(id)", 30000);
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    //alert(xhr.status);
                    //alert(thrownError);
                }
            });
        }
        var fillGridSucceeded = function (result) {
            var data = result.d;
            var dt = $('#tblAwesomeSauce').dataTable({ bRetrieve: true });
            dt.fnDestroy();
            $("#tblAwesomeSauce-body").empty();
            if (result.d.length == 0) {
                $("#tblAwesomeSauce-noresults").show();
                $("#tblAwesomeSauce").hide();
            } else {
                $("#tblAwesomeSauce-noresults").hide();
                $("#tblAwesomeSauce").show();
                $("#tblAwesomeSauce-row").tmpl(data).appendTo("#tblAwesomeSauce-body");
                $('#tblAwesomeSauce ').dataTable({
                    bJQueryUI: true,
                    bFilter: false,
                    bPaginate: false,
                    bInfo: false,
                    "sScrollY": "500px",
                    aaSorting: [[3, 'asc']]
                });
            }
        };
    </script>

If you are used to making AJAX calls with JQuery, kudos to you, if you’re not, here’s a breakdown of what’s happening at a high level. When they click on a row in the GridView (Telerik RadGrid actually), the following code will grab the ID field and call the next function:

            $('#<%# radGrid1.ClientID %>').find("tr").click(function (event) {
                var id = $(this).find("td:first").text();
                fillGrid(id);
            });

fillGrid is your average JQuery AJAX call to a Web Service.  You set up your call, throw it a value, and setup it’s success and failure options:

         function fillGrid(id) {
            $.ajax({
                type: 'POST',
                url: 'yourWebService.asmx/GetData,
                data: "{id:'" + id + "'}",
                contentType: 'application/json; charset=utf-8',
                dataType: 'json',
                success: function (msg) {
                    fillGridSucceeded(msg);
                    setTimeout("fillLoansGrid(id)", 30000);
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    //alert(xhr.status);
                    //alert(thrownError);
                }
            });
        }

fillGridSucceeded is where the dataTable and Template magic happen.

         var fillGridSucceeded = function (result) {
         var data = result.d;
         var dt = $('#tblAwesomeSauce').dataTable({ bRetrieve: true });
         dt.fnDestroy();

These four lines get back the results from your WebService in JSON format (so, like a JavaScript object with a bunch of string variables would be an easy way to test this out).  Then it gets hold of the HTML table and summarily destroys it’s contents so we don’t get confused.  Then we’ll skip down to the else statement where the work happens:

         $("#tblAwesomeSauce-row").tmpl(data).appendTo("#tblAwesomeSauce-body");
         $('#tblAwesomeSauce ').dataTable({
            bJQueryUI: true,
            bFilter: false,
            bPaginate: false,
            bInfo: false,
            "sScrollY": "500px",
            aaSorting: [[3, 'asc']]

This takes the JSON object and tries to smash it into the HTML Template you defined at the bottom of your page.  Then it appends that to the HTML table’s body tag.  The rest are various settings to do stuff likfe Y-axis scrolling and custom sorting or paging.

You may want to see the Web Service – Data Layer code for this example, but suffice to say, all it does is return the data as a List<Class>.  That <Class> is simply 8 string variables.  DateFields and Dollar amounts I converted into strings for this example to see what the dataTable extensions would do.  What does it do?  Well, by default it will attempt to auto-detect your types and it does that fairly well in it’s Sorting procedures.  Want to break it?  No problem; it’s fairly simple to confuse.  Try prefixing your dollar amounts with a $, then it will auto detect that back into a normal string.  There’s a lot of annoying details at this level, so, I’ll stop there.  Using LINQ to return an [object] from Entity Framework’s also works quite nicely.

Why bother?  In the words of Anthony Burgess: “O my little brothers”, because it is fast and it is the “very height of fashion”.

Enjoy

Posted in Uncategorized | Tagged , , | Leave a comment

Parallel.For Faster Than Regular For?

In the recent MSDN magazine I read an article espousing the wonders of parallel processing.  Ever since I forked my first threat back in school, I’ve liked the idea.  However since joining the world of business programming I’ve seldom come across it in use with legitimacy or the desired effect.

Take this extremely simple example in .Net 4 WinForm (It’s a Form with 2 buttons and 2 Textboxes.  Below is the code:

        private void button1_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();

            int x = 1;

            for (int i = 0; i < 1000000000; i++)
            {
                x *= i;
            }

            sw.Stop();
            textBox1.Text = "Total Time: " + sw.ElapsedMilliseconds;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();

            int x = 1;
            System.Threading.Tasks.Parallel.For(0, 1000000000, i =>
            {
                x *= i;
            });

            sw.Stop();
            textBox2.Text = "Total Time: " + sw.ElapsedMilliseconds;
        }

Results?  Regular For Loop wins hands down and consistently.  I have to wonder, why is it slower?  To answer that, I found the following link:

http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/2468e6ee-f551-42c4-a404-dfb051ac2614

Answer:

To be more specific, your workload per iteration is extremely short (access by index, and increment a single integer) – and this allows the cost of synchronizing the worker threads to become more significant than the workload itself. If you try longer workloads in the delegate, you should observe better results.

Hmm…  So, it’s because I was just doing simple math?

Another interesting thread I found on the issue that has a more complex test:

http://social.msdn.microsoft.com/Forums/en-US/parallelextensions/thread/6bd174ea-3a29-441b-a43f-e61d44497029/

I will try some further testing in the future with more complex math and different hardware configurations to confirm what is said in that post.

Made for a little fun though; hope you enjoy.

 

Posted in Uncategorized | Leave a comment

Entity Framework: getting sproc results the easy way

Most of the articles I read on EF are focused on projects where you only have a database, no sprocs, and your entity model is your primary method for manipulating that data…

In the world I work in, that’s typically not allowed for some good reasons.  Mostly because the database and sprocs/functions/etc have all been written, tested, and used for years and no one (i.e. your business user(s)) is going to want to do that again just because you want to upgrade technology.

So, while modeling data is fun and cool, I’m just going to show how to slap some Data Access Code around an Entity Framework model that was literally dropped on top of an existing database and then all the sprocs were imported and assigned function imports.  That’s about the easiest thing you can do to integrate EF with an existing database-designed application.

Say you have a grid and you want to bind it to the results of a sproc…  no problem:

In your DAL, it could look as simple as this:

public static System.Data.Objects.ObjectResult ef_GetSomeData(DateTime someDate)
{
 Your_Entity db = new Your_Entity();
 return db.sp_GetSomeData(someDate);
}

That’s great for a grid, but what about all the other scenarios?  What about getting it in an easy format for feeding single values to a bunch of form fields?  Personally, I just want it in the fewest lines possible so the next person to come along doesn’t want to strangle me.  Also, if you search on this, you’ll find a lot of very upset people trying their best to cram those results into a DataTable.  If that’s you, my advice is stop now 😉

Here’s an easier way:

public static Your_Entity.sp_SomeData_Result sp_up_GetSomeData(DateTime someDate)
{
 Your_Entity db = new Your_Entity();
 System.Collections.IEnumerator enumerator = ((System.Collections.IEnumerable)db.sp_SomeData(someDate)).GetEnumerator();
 enumerator.MoveNext();
 Your_Entity.sp_SomeData_Result r = (Your_Entity.sp_SomeData_Result)enumerator.Current;
 return r;
}

 Then you can do it in one line on your test page:

Your_Entity.sp_SomeData_Result data = DAL.sp_up_GetSomeData(someDate);
//Assign it to some fields on the screen
SomeData1.Text = string.Format("{0:c2}",data.field1);
SomeData2.Text = string.Format("{0:c2}",data.field2);
SomeData3.Text = string.Format("{0:c2}",data.field3);

No muss, no fuss.

Posted in Uncategorized | Tagged , , , | Leave a comment

Lowering password strength with ASP.Net Authentication

In implementing authentication recently I found it troublesome to pinpoint how to modify this setting. So, here’s how.

In this example, I am using the AspNetSqlMembershipProvider over the Active Directory one. I haven’t changed the name from that, although you could.
This link explains how:
http://msdn.microsoft.com/en-us/library/ff648345.aspx

In your web.config’s system.web section you’ll need:

<membership>
      <providers>
        <remove name="AspNetSqlMembershipProvider" />
        <add name="AspNetSqlMembershipProvider"
                  type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                  connectionStringName="LocalSqlServer"
                  enablePasswordRetrieval="false"
                  enablePasswordReset="true"
                  requiresQuestionAndAnswer="true"
                  applicationName="/"
                  requiresUniqueEmail="false"
                  minRequiredPasswordLength="1"
                  minRequiredNonalphanumericCharacters="0"
                  passwordFormat="Hashed"
                  maxInvalidPasswordAttempts="5"
                  passwordAttemptWindow="10"
                  passwordStrengthRegularExpression="" />
      </providers>
    </membership>

Let’s talk about some pieces here.

<remove name="AspNetSqlMembershipProvider" />

could also be <clear/> 

Additionally, The Machine.config file contains a default SqlMembershipProvider instance named AspNetSqlMembershipProvider .  Which is why I’m replacing it with my web applications web.config setting.
This is explained in depth here: http://msdn.microsoft.com/en-us/library/ff648345.aspx

minRequiredPasswordLength sets the length (can be 1 to 128)
passwordStrengthRegularExpression sets the difficulty that the password will be validated against.
In my recent user testing, the defaults for these settings proved to be annoying and unnecessary.

Cheers.

Posted in Uncategorized | Tagged , | Leave a comment

Basics of MongoDB with .Net

Basics of MongoDB with .Net

Watch the “Introduction to MongoDB”

http://www.youtube.com/watch?v=iRDOGkFKBRw&feature=player_embedded#at=95

Download MongoDB for Windows 64bit:

http://www.mongodb.org/downloads

Unzip to C:Mongo

Follow these instructions for installation:

http://www.mongodb.org/display/DOCS/Quickstart+Windows

Run these two applications (can be setup as a Windows Service)

  1. Mongod.exe first (which will stay open)
  2. Mongo.exe second, which will run and connect to Mongod.exe

 

Now connect to your Test database:

  1. Open a command prompt.
  2. Browse to c:Mongobin
  3. Type: mongod
  4. Make sure you leave this running (this is your database server)

 

Alternatively you can create a shortcute with:

Target: C:WindowsSystem32cmd.exe /k mongod

Start in: C:Mongobin

Create your first document:

  1. Open a new command prompt.
  2. Browse to c:Mongobin
  3. Type: mongo (this connects you to the database server running locally)
  4. Type: db and hit enter to see what database you’re connected to.
  5. Type:db.foo.insert({a:1}) (inserts a document)
  6. Type: db.foo.find() (does a search on the document database)

Great!

.Net Setup for MongoDB

Download drivers for MongoDB C# and .Net.

MongoDB C# driver MSI:

https://github.com/mongodb/mongo-csharp-driver/downloads

Download and run.

Community supported driver:

https://github.com/samus/mongodb-csharp

Download to C:MongoCommunityCSharpDriver

You can drop the 3 .DLLs into your .Net project.

                MongoDB.Driver.dll

                MongoDB.GridFS.dll

                MongoDB.Linq.dll

.Net Sample Web Application

Create a new web application in Visual Studio 2010 (or 2008)

Add the 3 reference DLLs.

Create/Open a Default.aspx.cs file and connect to your test Mongo Database:

Drop some controls on (I’m using Telerik’s RadGrid in this example)

    <form id="form1" runat="server">
    <div>
            Create a new Mongo Database:<br />
        Name:
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
&nbsp;<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Create" />
        <br />
        <br />
        <asp:Button ID="Button2" runat="server" onclick="Button2_Click" 
            Text="View Results" />
        <br />
        Results<telerik:RadGrid ID="RadGrid1" runat="server">
        </telerik:RadGrid>

    </div>
    <telerik:RadScriptManager ID="RadScriptManager1" Runat="server">
    </telerik:RadScriptManager>
    </form>

 

Add some code:

        protected void CreateMongoDB(String dbName)
        {
            //mongod.exe must be running for this to work.
            var mongo = new Mongo();
            mongo.Connect();

            //if the database is not found in c:datadb it will be created.
            var db = mongo.GetDatabase(dbName);

            //declare a new "table"
            var categories = db.GetCollection("categories");

            //create a new key value set
            var document = new Document();
            document["Name"] = "Product";
            document["Name"] = "Price";

            //create the "tabt"
            categories.Insert(document);
            mongo.Disconnect();
        }

 

And the button call:

        protected void Button1_Click(object sender,EventArgs e)
        {
            String name = TextBox1.Text;
            CreateMongoDB(name);
        }

 

Run it.

Now you can create MongoDB’s through a web form.

Filling a Grid with the Results

We’ll jump ahead a tiny bit to where you’ve added some documents to one of your MongoDB’s.

Mine is called TestProducts.

Each document has a Name and a Price.

Add some more code to default.aspx.cs

        protected String GetMongoDBResults(String dbName)
        {
            //mongod.exe must be running for this to work.
            var mongo = new Mongo();
            mongo.Connect();

            //if the database is not found in c:datadb it will be created.
            var db = mongo.GetDatabase(dbName);

            //declare a new "table"
            var categories = db.GetCollection("categories");

            //get the categories table
            var category = categories.FindOne(new Document() { { "Name","Price" } });
            //alternatively you can get all documents in the database
            var documents = categories.FindAll().Documents;
            String res = category["Name"].ToString();

            //diconnect
            mongo.Disconnect();

            //return results in a EF friendly shapre just because that's what I'm working with mostly nowadays
            return res;
        }

 

Add the button call code:

        protected void Button2_Click(object sender,EventArgs e)
        {
            RadGrid1.DataSource = GetMongoDBResults(TextBox1.Text);
            RadGrid1.DataBind();
        }

 

Run it.

Now you can fill a Grid with data from your MongoDB.

Posted in Uncategorized | Tagged , , | Leave a comment

jQuery to Web Service AJAX

jQuery to Web Service AJAX

This is a bit wacky, but in the end it all makes perfect sense.

jQuery has two functions you could use: get and put, but the function you’ll end up using is.ajax.

Example:

Let’s say I want to use JQuery to fill a Drop Down list on my ASP.Net page.

Here’s the basics of how that flows:

On whatever event (in this example it is a button click) you will wire up a JQuery function to fire off an AJAX call.

On the web, most examples call a PHP page, and that’s not what we want to do.

HTML:

<body>
    <form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="MyDropDownList" runat="server">
        </asp:DropDownList>
        <asp:Button ID="FillDropDownListButton" runat="server" Text="Fill DropDownList" />
    </div>
    </form>
</body>

 

JQuery function to tap into the click event for the button:

    <script type="text/javascript">
        $(function () {

            $('#<%= FillDropDownListButton.ClientID %>').click(function () {
                doAjaxCall('/Test.asmx/FillDropDownList');
                return false;
            });

 

JQuery function to do the AJAX call:

            function doAjaxCall(url, data) {
                $.ajax({
                    type: 'POST',
                    url: 'Test.asmx/FillDropDownList',
                    data: "{}",
                    contentType: 'application/json; charset=utf-8',
                    dataType: 'json',
                    success: successHandler,
                    error: ajaxFailed
                });
            }
 

You can see that this is using the HTTP POST protocol, and thus, the function being called must either be an actual web page .aspx or a user control .asmx/.svc or it could be the rarely seen .ashx (not covered here).  It cannot be a library .cs because that doesn’t communicate via HTTP protocol.

Also note the data object being passed is an undefined empty object. 

The url has the page/function.  That function must be a web method.
 

The success function:

            function successHandler(response) {
                var myDropDownList = $('#<%= MyDropDownList.ClientID %>');
                myDropDownList.find('options').remove();
                var data = response.d;
                var doc = $('<div></div>');
                for (var i = 0; i < data.length; i++) {
                    doc.append($('<option></option>').
                            attr('value', data[i].CountryID).text(data[i].CountryName)
                            );
                }
                myDropDownList.append(doc.html());
                doc.remove();
            }

 The failure function:

            function ajaxFailed(xmlRequest) { alert(xmlRequest.status + ' nr ' + xmlRequest.statusText + 'nr' + xmlRequest.responseText); }

        }); 
    </script>

 

Now, as for the Test.asmx:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [ScriptService]
    public class Test:System.Web.Services.WebService
    {
        [WebMethod]
        public Collection<Location> FillDropDownList()
        {
            var locations = new Collection<Location> 
                { 
                    new Location {CountryID = 0, CountryName = "Please Select"}, 
                    new Location {CountryID = 1, CountryName = "Country1"}, 
                    new Location {CountryID = 2, CountryName = "Country2"}, 
                    new Location {CountryID = 3, CountryName = "Country3"}, 
                    new Location {CountryID = 4, CountryName = "Country4"}, 
                    new Location {CountryID = 5, CountryName = "Country5"} 
                };
            return locations;
        }
        public class Location
        {
            public int CountryID { get; set; }
            public string CountryName { get; set; }
        }
    }
}

 

So, while I’m returning a collection from the code, it could also make a call to SQL or the WebCache, etc.

Posted in Uncategorized | Tagged , , | 1 Comment

Twitterizer & .Net: Adding a feed to your website

Create a Twitter user:
http://twitter.com/

Register your application:
https://dev.twitter.com/apps/new
This gives you:
    <add key=”AccessToken” value=”blahblahblah”/>
    <add key=”AccessTokenSecret” value=”blahblahblah”/>
    <add key=”ConsumerKey” value=”blahblahblah”/>
    <add key=”ConsumerSecret” value=”blahblahblah”/>
Add it to your web.config

Go to:
http://www.twitterizer.net/downloads/
Download the Twitterizer package:
Twitterizer2-2.3.2.zip.

Add
Twitterizer2.dll and Newtonsoft.Json.dll
in your project references

Make an ASPX page with:
                    <div id=”homeDev”>
                        <fieldset style=”width: 230px”>
                            <legend>Development Buzz</legend>
                            <%=Data1%>
                        </fieldset>
                    </div>

Do this in the .CS
 public partial class Home : System.Web.UI.Page
    {
        private string _data1;
        public string Data1
        {
            get { return _data1; }
            set { _data1 = value; }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            ConnectTwitter();
        }

        protected void ConnectTwitter()
        {
            OAuthTokens tokens = new OAuthTokens();
            tokens.AccessToken = ConfigurationManager.AppSettings[“AccessToken”];
            tokens.AccessTokenSecret = ConfigurationManager.AppSettings[“AccessTokenSecret”];
            tokens.ConsumerKey = ConfigurationManager.AppSettings[“ConsumerKey”];
            tokens.ConsumerSecret = ConfigurationManager.AppSettings[“ConsumerSecret”];
           
            TwitterResponse<TwitterStatusCollection> statuses = TwitterTimeline.HomeTimeline(tokens);
            for (int i = 0; i < statuses.ResponseObject.Count; i++)
            {
                Data1 += “<p>”;
                Data1 += statuses.ResponseObject[i].Text.ToString();
                Data1 += “</p>”;
            }
        }
    }

Posted in Uncategorized | Tagged , , | 8 Comments