Showing posts with label development. Show all posts
Showing posts with label development. Show all posts

Tuesday, September 23, 2014

Life without a .Net

I wrote code exclusively on the Microsoft platform from 1997 until late 2013.  Sixteen years of ASP, ASP.Net, Visual Basic (4,5&6), VB.Net, wonderful C# and lots of MS SQL Server.  I could take a pile of computer parts, assemble them into a server, load the current flavor of Windows Server,  IIS and MS SQL Server, and assorted .Net Frameworks.  Then I could design a database, write the code(C#, assorted JavaScript add-ons), put it all together and Ker-Pow, a working software application/website/platform thingy.

And those applications worked!  And there were always more .Net jobs waiting for more things to be built.  And then, one day, while looking at Visual Studio 2013 I realized, I can't do this anymore.  I tried to slog through.  I know that everyone feels burnout from time to time, but I was starting to get a little worried at the thoughts going through my head.

Do you still want to be a software developer?  What else can I do?

I had recently moved from a startup (using .Net) to a big multi division company that had an Information Technology Department.  You know the kind of place I mean.  A cube farm that spanned an entire city block.  Bookshelves full for Wrox & MS Press titles.  Motivational slogans.  Well stocked Keurigs. Glass walled conference rooms.  End tables for network printers that had the \\unc\\ taped to the front.  My title was Senior Software Webgineer or some such.  The company was so big in fact, that the job I was hired to do had already been contracted out by the department that originally contacted IT.  Nobody told the hiring manager.  So after my on-boarding, there was not much for me to do.  I went to a few hackathons on the weekends.  That helped some, but the main problem was I didn't want to work in the .Net-corporate-IT-business-causal world anymore.  There was nothing wrong with the people at the company, it was all me.  I was tired of the dress code, the culture and the tech.  But at the same time I was scared to leave it.   It was all I knew.  That was part of what was bugging me.

I went to a meet-up for the relatively new programming language called Go (golang).  I had been messing around with the language in my free time just to break the .Net monotony.  The company that hosted the meet up said they were hiring and to talk to them if interested.  I was.  I knew this place would be different from what I had done in the past.  I also knew that I had zero skills in the tech stack they used.  At that point I'd written maybe 100 lines of Go, and they were primarily a Python/Django shop with a few projects in Go.  But I told them of my interest anyway and they suggested that I submit a resume.  I did.  Two interviews later I got the offer.  I was sitting in my cube in Corp-IT-Ville when I got the email.  I raised both hands in the air (clinched fists I think) and hissed, "Yessssss!"

I started out with new company with about 100 lines of Go code experience and a crash course in the Django tutorial.  But man, what a curve.  If it was just the language differences, that would have been easy enough, but it was more than that.  No Windows machines.  All developer machines were OSX.  And the development environment?  Well they used a tool called Vagrant, which housed a Linux build via Virtual Box with MySql and Gunicorn and Celery and Nginx and can you check out this feature branch and submit a PR that we can review?  Lots of command line...commands.  My head was spinning.  I was asking questions and Googling.  A lot.  I found myself thinking, "If this were on Windows, I'd do this thing this way!" But I wasn't on Windows.  Every day I was learning new things, which was great, but I was also finding out about new things that I did not know anything about.

And that was the worst part.  After about five months, I still was not able to turn things around as fast as I wanted to in my new job, but I also wasn't up to speed with the Microsoft world either.  New versions of C#, SQL Server and Visual Studio were released.  I did not know what the new features were.  I was trapped between the two worlds and I couldn't be productive in either of them like I wanted to be.  So what's a developer who is in over his head to do?

Slog through it.  Day after day.  Google dumb questions.  Ask dumb questions.  Get no where.  And then one day something makes a little bit of sense.  Slowly, I learned how to make changes to code that caused errors but...they were errors that I was expecting to see.  That's the Eureka moment.  When you can break source code in expected ways, soon you can make it do new things.  Things like, new features or bug fixes.  It's all the same thing, modifying the behavior of the code so that it responds the way it should.

Now I code in Go(golang) and Python.  I can form my thoughts into these new languages and produce thing that work.  Both of these languages have made me a better overall developer because they force me to think about code in different ways.  My pull requests still generate some chatter about how things could be improved, but then that's what pull requests are for.  Occasionally I'll get a, "oh, I didn't know you could do that" from some one.  It's cool when that happens, and not because it means I'm a big shot (ha!).  It's cool because, after having a team of developers patiently answer my questions for almost a year, it's nice to be able to give back, if only just a little bit.

To wrap this up, the journey was more than worth it.  Writing software is as fun as it's ever been.  It's hard to be a beginner in a field where you thought you knew a lot, but it's a necessary step if you want to continue to grow.




Saturday, July 2, 2011

jQuery tmpl plugin example for ASP.Net

Originally I was going to call this post, "Look Ma!  No view state!" but view state isn't really what I to talk about it.  This example will have no view state, but that's a side benefit.

What I want to talk about is client side data binding with jQuery.  The jQuery tmpl plugin has been documented in a number of places and I'm not going to show anything new here.  This post is intended to be a simple example for people still using data grids and heavy .Net server controls.  This example won't use any server controls.  We won't have a form tag and there will be no code behind.  Let's get to it.

Step 1: Create a web service

Here's our simple web service.  I called it "wsPlayers".  It has one method and returns a list of custom objects based on a simple NBAPlayer class.  Be sure to uncomment the line...

[System.Web.Script.Services.ScriptService]


...so that the web methods in the service can be called from client side JavaScript. We will also want to add a reference to the Script.Services namespace at the top of the file...

using System.Web.Script.Services;

...so that we can change the format of our web method to JSON (it's XML by default).

So here is the full  text of our web service method:


Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services; //Have to add this namespace for the ResponseFormat on the webmethod).
   
namespace tmplDemo
{
 /// <summary>
 /// Summary description for wsPlayers
 /// </summary>
 [WebService(Namespace = "http://tmplDemo/")]
 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
 [System.ComponentModel.ToolboxItem(false)]
 // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
 [System.Web.Script.Services.ScriptService]
 public class wsContacts : System.Web.Services.WebService
 {

  [WebMethod]
  //***The ResponseFormat has to be added to the method, not the WebService Class (above).
  [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
  public List<NBAPlayer> GetPlayers(int paramMinChampionships)
  {
   List<NBAPlayer> tempPlayers=new List<NBAPlayer>();
   
   NBAPlayer temp1 = new NBAPlayer("Nowitzki","Dirk",1);
   NBAPlayer temp2 = new NBAPlayer("James", "LeBron", 0);
   NBAPlayer temp3 = new NBAPlayer("Wade", "Dywane", 1);
   NBAPlayer temp4 = new NBAPlayer("Bryant", "Kobe", 5);
   NBAPlayer temp5 = new NBAPlayer("Paul", "Chris", 0);
   
   tempPlayers.Add(temp1);
   tempPlayers.Add(temp2);
   tempPlayers.Add(temp3);
   tempPlayers.Add(temp4);
   tempPlayers.Add(temp5);

   return (from p in tempPlayers 
     where p.championships>=paramMinChampionships 
     orderby p.lastname,p.firstname
     select p).ToList<NBAPlayer>();
  }
 }
 public class NBAPlayer{
   public NBAPlayer(string lname,string fname,int chmps){
   lastname=lname;
   firstname=fname;
   championships=chmps;
  }

  public NBAPlayer()
  {

  }

  public string lastname { get; set; }
  public string firstname { get; set; }
  public int championships { get; set; }
 }
}

As you can see from the code, the web service has a method called GetPlayers and it accepts one parameter of type int called paramMinChampionships.  It then returns a list of type NBAPlayer where each NBAPlayer object has a championship property equal to or greater than the paramMinChampionships.

Now, I've made a custom class and hard coded a few elements for the example but this is where you'd put your database calls or Linq objects and build your return set that way.  We're done with the web service.

Step 2: Download jQuery files.


Create a directory in your project called jQuery.  Download these two jQuery files:


Add these files to the jQuery directory you made at the beginning of this step.

Step 3: Create a default.aspx page.




Add a new file called default.aspx.  Once you've done that, your solution explorer should look something like the image at left.







Now the fun part.  First we're going to create some javascript that will do our Ajax call for us:

<script type="text/javascript">
        function GetPlayers() {
            $.ajax({
                url: "wsPlayers.asmx/GetPlayers",
                dataType: "json",
                type: "POST",
                contentType: "application/json; charset=utf-8",
                data: ("{paramMinChampionships: " + $("#selChamps").val() + "}"),
                error: function (err) {
                    alert("Error:" + err.responseText);
                },
                success: function (results) { OnComplete(results.d) }

            });
        }

        function OnComplete(results) {
            $("#tbodyPlayers").empty();  //We want to clear the body of the table first.
            $("#playerDataTemplate").tmpl(results).appendTo("#tbodyPlayers");
        }

    </script>


If that doesn't make sense, then stop right here and read about the jQuery Ajax method.  What we're doing is calling our web service and passing it a numeric value so that it will give us back our list of players.  Before we do that lets add the rest of the HTML to our default.aspx page.

We want a select element that looks like this:

Players with at least 
    <select id="selChamps"> 
        <option value="0">0</option> 
        <option value="1">1</option> 
        <option value="2">2</option> 
        <option value="3">3</option> 
    </select> 
    championships.

We'll want a button to fire off our ajax web service call:

<button id="btnSubmit" onclick="GetPlayers();" >Submit</button>

We'll also want a table to display our data:

<table border="1"> 
        <thead> 
            <tr> 
                <td>First Name</td> 
                <td>Last Name</td> 
                <td>Championships</td> 
                <td>Bing</td> 
            </tr> 
        </thead> 
        <tbody id="tbodyPlayers"> 
         
        </tbody> 
    </table>

Lastly, and most importantly, we add the data template:

<script id="playerDataTemplate" type="text/x-jquery-tmpl"> 
    <tr> 
        <td>${firstname}</td> 
        <td>${lastname}</td> 
        {{if championships>0}} 
        <td align="center"><span style="color:green;font-weight:bold;">${championships}</span></td> 
        {{else}} 
        <td align="center">${championships}</td> 
        {{/if}} 
        <td><a target="_blank" href="http://www.bing.com/search?q=${firstname}+${lastname}">search</a></td> 
    </tr> 
</script>


That's right, we're putting HTML markup directly inside our <script> tag in the example above.  Notice that the type is type="text/x-jquery-tmpl" and not type="text/javascript". This is a different kind of script that works with the tmpl plugin. The magic is in the OnComplete method and the data template we created.  Pay special attention to this line of JavaScript code:

$("#playerDataTemplate").tmpl(results).appendTo("#tbodyPlayers");

What this means is, we're going to take the value of results, which is the JSON object that contains our list of player data, pass it to the tmpl function of the playerDataTemplate selector and append the output to the
tbodyPlayers selector. The playerDataTemplate will apply what's inside for each element in the results variable. As you can see, by using the {} brackets we can drop the values of the properties whereever we want.  We can apply conditional if/else and we can put our property values inside HTML markup. And we can do it all without asp.net server controls or a code behind.  Well,we do have a code behind of sorts but that is encapsulated in the web service.  So if we have an iPhone app that wants to call our web service, no problem.  Windows forms wants to use it?  No problem.  Another thing about this approach is that we are getting away from all the custom .net control styling markup and back to straight up css.  Now when a designer looks at our source and wants to make some tweaks, they don't see a buch of <asp:textbox id="txtFirstName" runat="server" text="Johnny" />.  The see regular HTML that they should be able to update without breaking anything.

Another advantage to this approach is that we are doing an Ajax call but since we're not using an asp.net update panel and things like that, we're only sending and receiving the JSON objects.  That's a really light payload compared to all the view state stuff we'd get if we used update panels.  We also aren't using an asp.net script manager, we're just referencing our jQuery libraries normally so we don't have that overhead either.  I may do a follow up post to this one where I use update panels, script managers and a datagrid to show the difference in page size and network traffic.  It makes a huge difference.

So, that's the tmpl plugin for jQuery and that's why I love it.  If you want to play around with this project yourself, you can download the whole thing here.

Thursday, April 7, 2011

Web Service Minutiae

Sometimes, as part of a web project, I'll make a web service that will be called by a front end .aspx page elsewhere in the project.  Inevitably, I will forget to do two things:

One, I'll forget to uncomment the script service line above the web method, even though Visual Studio puts a comment above it that says the following:

'To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
 '<System.Web.Script.Services.ScriptService()> _
And two, I'll forget to set the InlineScript property of the service reference to true.  

Then I'll trouble shoot for an hour before I remember, oh yeah, I have to do those two things.  Hopefully by writing this on my blog, I'll remember.  Anyway, those to two tidbits are things that I forgot, but I did know at one time.  This week I learned some new things regarding web services.  I'm sure many developers out there will say, "well duh...I can't believe you didn't know that!  Dunce!"  In response to such barbs, I will quote Clark Gable in Gone With the Wind, "I apologize again for all my short comings."  Moving on...

Here are the two, new, things I learn about web services.  One, you can change the format of the SOAP data that gets passed back and forth from the verbose (but useful) XML format to the more concise Json format.   Did you know that?  I sure didn't.  You just change the property in the web method:

<WebMethod()> _
    <ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
    Public Function DoSomething() ...

Please note that the above code snippet assumes the import of the System.Web.Script.Services namespace.  I hate it when demo code doesn't include what namespaces are involved.

The second thing I learned is that there is a size limit on how big the Json object can be.  I was all happy until I quit getting results back because I knew there were lots of the results that were coming back and that was the problem.  You can set it manually in the web.config, like this:

<jsonSerialization maxJsonLength="Big ol' number"/>

...but I wouldn't recommend that.  Why?  Because the whole point of Json is to have light weight markup text so you can pass data around web services with less bandwidth.  If your Json is so big that the default size of the object isn't big enough to handle it, then maybe there's just too much data in there and it needs to be broken up some other way.  But hey, do what you want.  Pass multi gig Json objects around, set the IIS timeout to 120 minutes and put all your asp.net applications in their own app pools.  See what happens.

G'night.

Thursday, October 28, 2010

Looking forward

     I almost wrote another post on how and why I got into software development.  I was thinking a lot about that after I downloaded a Texas Instruments 99/4A emulator.  I was amazed at how much my fingers remembered.  Double tap the 1 key and start typing line numbers and commands.  Anyway, I'm not going to do that.  I'm going to talk about what's ahead for me in software development.

     Mobile development.  That's what I see when I look forward.  The place where I work is getting into iPhone development.  I tried to get my department to give the windows mobile platform a shot but even I couldn't take WinMo 6.x after a while.  Maybe Windows Mobile 7 will be better but for now it's the iPhone.  People like using their iPhones.  People love it when you write an application that gives them yet another reason to whip out the iPhone and start two finger tapping.

     So far I've been writing the back end web services that handle the data part of our iPhone applications and my co-worker, Kotaro, has been writing the front ends on his Mac in Objective C.  The web services part is great because since it's just XML/Soap, any platform could connect to it and make use of the services, with proper authentication of course.  What I'm trying to do now is expand my skill set to include actual iPhone development using tools from Mono Touch by Novell.  The Mono Project is an open source .Net framework that allows a developer to write .Net code and target Windows, Mac and Linux.  I want to do iPhone/iPad development with it but it'd be great to get familiar with those other platforms as well by writing code for them.

     Why learn a new development platform?  Same reason I learned the first one, because it's fun.

     I've also been thinking about the gaps in my skill set.  One of the problems that comes from being a self taught developer is that I've wasted many hours writing something that has already been written.  Also, there's this gnawing concern that there is so much about development, even on the Microsoft platform, that I don't know that...I don't know what I don't know.  Sometimes I come across posts like this and this and think, "Dangit!  I've been doing this over a decade and I've never even heard of some of this stuff!"  At first I tried to tell myself that it was just one guy's opinion (it is) and that there's lots I know that isn't on those lists (also true) and I've been doing this for years so I must be doing something right (right?).  But the more I thought about it, the more I realized that I was just a few Google searches and test projects away from being able to answer all of the questions in those two posts.  Just another visit from the binary thought system 0 (I'll never figure all this out) and 1 (Why shouldn't I be able to figure it out?).

     Still reading? Even after that 0 and 1 nonsense?  Okay.  I'm trying to go deeper.  In episode 6 of This Developers Life, Scott Hanselman and Rob Conery talk about "The Stack" and how much a developer should know about it.  Professional developers  are constantly running into things they don't know how to fix (at first).  Take a look at this Twitter stream and you will see.  The Stack is all the stuff between what a developer types and the 1s and 0s the system actually works with (sort of).  For example, when I write code in a high level language like Visual Basic .Net or C#, it looks something like this:

string firstname = "John";
string lastname = "Smith";
string fullname = firstname + " " + lastname;
Console.WriteLine(fullname);


     Not beautiful code, but you get the idea.  I click "Build" and several steps later it's processed into something like 10011010010101110001010...and the machine does something.  The point is, I don't really know how to program a computer at all.  I stand on the shoulders of giants standing on the shoulder of giants so I can reach high enough to pull the lever and make the computer spin.  I only know how to write descriptions of what a program should do and then I let the magic of MSIL and various compilers actually write the program for me.  So when I say I want to get deeper into the Stack, I mean that I want to learn more about what goes on after I type up all my C# or VB code and hit Build.  That means getting into things like C++ and Assembly.

     Now it's possible I'm going to get into the Stack and run screaming from what I find there.  There is a part of me that says I'm 36, I am what I am and it's hard enough to learn all the new stuff let alone all the old stuff.  

     Maybe.

     But thinking about this stuff reminds me of a story I read about a modern boat that ran aground several years back because of a GPS error.  The crew on board could have used their map or just looked out the window but the GPS said everything was fine so they went full speed ahead until the hull split open.

     So I'm going to write a program in C++ that does something useful but simple.  Then I'm going to write a program in Assembly.

     If you made it all the way to the end of this post and you want more, I suggest:
     The next post will be...a true life entry.

Wednesday, April 21, 2010

Time to learn

Several years ago I worked with a developer that did all of his development with classic ASP pages. It didn't matter what the task was, a classic ASP page was the answer. Instead of writing a console app or writing a .bat file to run an automated file manipulation task, he would reference COM objects from within the ASP page and run it under an account that had access to the file system and then schedule IE to run with that page as a command line argument. And it ran...most of the time. This guy was very comfortable with his classic ASP. During the time I knew him I never saw him write a windows application or a .net application of any kind. Classic ASP uber alles!

I am not like that.  I certainly have my comfort zones.  I stayed with classic ASP during the initial days of ASP.Net.  I didn't fully leave my spaghetti code ways behind until version 2.0 of the framework came out.  Then I left it behind for good.  But VB6?  I dropped it as soon as I tried my first .Net WinForms application.  I cannot quite explain why.  It was different enough that I found myself spending a lot of time relearning old tasks (like adding items to a drop down box and actually seeing the text).  But I could see the potential.  You'd think I would have seen it in ASP.Net from the get go but I've always been a console/backend/windows developer first and a web developer by necessity.

Anyway, version 2.0 of the framework came along and that got me excited about web development.  It seemed like there were a dozen new technologies to learn.  Right about the time I got up to speed on the relevant (to me) parts of framework 2.0, version 3.0 came out.  Then version 3.5...the version 3.5 sp1...and SQL Server 2008.  I threw up my hands and gave up trying to learn it all.  I picked a few things here and there and learned what I could.  When I found something really useful, like Linq-to-SQL, I would talk it up with the other developers in my department and try to get them using the new better ways.  Some took to the new ways, some kept on slogging the .Net 1.1 way.  You can bring a developer to water but you can't make him Linq.

For me, I usualkly learn so much about new technologies while working on a project that by the time it's finished, I want to rewrite the entire thing in the stuff I was learning while coding with the old stuff.

What is this post about?

This post is about all the new stuff that's come out recently(and somewhat recently) from Microsoft.  I was making a list of books I need to buy to get current on things and realized I was going to be spending a fortune.  Here are the technologies that I want to learn about:
  • MVC 2.0
  • WPF
  • Silverlight 4.0
  • .Net Framework 4.0
  • Powershell (So hard to leave my cmd ways behind, but I need to)
  • JQuery (I'm way behind on this)
  • IIS 7.0
  • SQL Server 2008 (somewhat advanced)
  • Windows 7 (It's cool, I like it, but I'm still stumbling around some)
That's a full year's worth of reading right there.  I'm going to have to go back to doing it like I did in the old days when I ways trying as hard as I could to get out of the technical support department and into development.  I'll buy a book (or two) about each technology and read them from start to finish.  I won't remember all of what I read, but general concepts and terms will stick.  Later, I'll be thinking about a problem and think, "Wait a second....I read something about this..." and I'll flip through a book or Google a certain term and find my solution.  The fun parts of reading these 800+ page behemoths is when I come across a better way to do something I do all the time.  I know that sounds strange but, yes, those are the fun parts.  If it wasn't fun I wouldn't be able to do this for a living.

Anyway, time to get reading. 

Saturday, March 27, 2010

Numlock Morse Code

In Neal Stephenson's novel Cryptonomicon, Randy Waterhouse finds himself in a prison in the Philippines.  Randy has a laptop with some very valuable information on it that some bad guys want, but since the information is encrypted, they can't get to it.  So they allow Randy to keep his laptop in his jail cell but the only place he can put it is on top of a short, locked, file cabinet that has been chained to the floor.  The battery has been removed so the only way to get power is to leave it plugged in on top of the filing cabinet.  The thing is, Randy doesn't even know what the information is yet, because it's encrypted too. He needs to decrypt the information, but not let the bad guys know he is decrypting it, or rather, he wants them to think he's doing it but give them the wrong information.

He can't show the real decrypted info on the laptop display because he is afraid that the bad guys are trying to use a Van Eck Phreaking antenna that is inside the filing cabinet so they can eavesdrop on his laptop screen (he's already made sure there are no hidden cameras).   So he comes up with some fake decryption that he shows on the screen, but the real info has to be displayed another way.  He writes a program that takes text and translates it into Morse Code.  The program turns the the scroll lock light on and off to simulate dots and dashes.  Now he knows the real info from the blinking light, and the bad guys get the fake info he showed on the screen.

I thought that was kind of cool so I wrote a program that does just that.  The only difference is my program blinks the num lock key instead of the scroll lock key (my keyboard doesn't have a scroll lock key).

If you were to load this application on your windows PC and run the following from the command line:

c:\waterhouse\waterhouse.exe /T:"sos"

You would get this:




Notice the /T:"sos" that comes after the name of the application.  The /T: switch says, "turn this text into Morse code."

You could also type this:

c:\waterhouse\waterhouse.exe /F:c:\morse.txt

/F: says to load a file and turn that into Morse code.  It can be a file on your computer, a UNC path or a file on the web (just prepend it with http://).  The contents of the file c:\morse.txt on my computer happens to be my name.  So when you hit enter, you see this:




Help is available by typing the /? or /help switches.

You can download the compiled application here. (Windows only)

You can download the source code here.

You can download Microsoft's free Visual Basic 2008 Express development environment here.

Wikipedia: Morse code

Sunday, May 17, 2009

Auto Complete Example Project

I've written an ASP.Net project that shows how to configure the Auto Complete Extender(ACE), get back the text and the ID, and pull data to show in a details view. If this is your first time using the ACE, pay special attention to the web service files and the javascript in the default.aspx page.

To run this project you'll need Visual Web Developer 2008 Express, MS SQL Express 2008, and the Adventure Works demo database(AdventureWorksDB.msi).

In addition to the ACE I also used an ASP Update Panel and some basic Linq To SQL.

You can download my example project here. You'll need to set the correct connection string in the web.config file to connect to your copy of the AdventureWorks database. If you need help with connection strings, try this site.

Saturday, May 16, 2009

More AutoComplete

I have been getting a lot of hits on the Google Search Appliance Auto Complete post. I thought I would add a few more notes concerning the Auto Complete control in the ajax.net toolkit. Let's say you have a long list of items in a drop down list. Wouldn't it be better to filter that list based on what the user types? Yeah, of course! That's why we have that functionality all over the web now. The only probelm is that the Auto Complete control isn't as easy to use as the other controls in the Ajax control toolkit.. For instance:

  1. You have to write a web service to handle the back in call to the data source. So if all of your data is in an MS SQL database, or Access, or XML, you have to write the query for that and put it in a web service and tag it with a WebMethod attribute. Read more about web services here.
  2. The webservice that the Auto Complete calls can have any name but it must have the following paramter signature: Public Function GetItemName(ByVal prefixText As String, ByVal count As Integer) As String(). The first variable must be a string and it has to be called prefixText. The second one must be called count and it has to be an Integer. Read more about the Auto Complete extender here.
  3. One final thing you need to know about the Auto Complete extender is that most of the examples you'll find online show how to get back the text that the user selected, but they don't show you how to get back the ID. Let's say you have a dropdown list of car parts. There could be thousands of them. The user types in a few letters, sees the part, arrows down to it and hits enter. What you need now in order to do look ups in your related tables is the ID of that item, not the text itself. How do you get that? Inside my webMethod function I do something like this: tempResult.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(itemname), itemID))
    In this example tempResult is List( Of String). By using this CreateAutoCompleteItem function I can create an item that the Auto Complete Extender knows should be split into a text value to display and an ID value that will actually be used. Now, the return type has to be a string array, so the last line of my function is "Return tempResult.toArray()". I like working with generic lists but you could just as easliy dimension a string array with the size based on the count paramter.
  4. Now, how do I get the value back from the ajax call? In the markup for the AutoComplete Extender, you need to specify a javascript function to be called after the user selects an item. Something like this: OnClientItemSelected="showItem". The showItem function will look something like this:
    function ShowItem( source, eventArgs ) {
    alert( " Key : "+ eventArgs.get_text() +" Value : "+eventArgs.get_value());
    }
  5. What's that? You don't want the value in a javascript alert, you want to assign it to an ASP.net control, like an asp:HiddenField or something like that? Then do a getElementById('hiddencontrolID').value = eventArgs.get_value(); somewhere in your javascript function.
  6. Now you are probably going to ask...what if it's in a User Control and there are lots of them on the page and I don't know what the ID is going to be for each asp:Hidden control? That's an answer for another blog post. If this one generates lots of hits I'll write it up.

Thursday, February 12, 2009

Auto Complete on the Google Search Appliance

At my job we have an .aspx page that displays search results from a Google Search Appliance. Nothing too fancy. The page passes the query, gets the XML results from the GSA, we pair that with an XSLT and sha-zam, search results. It was brought to my attention that some one higher up the chain wanted to know if we could have that "cool google suggest drop down thing" on our search page. Google has it. Amazon has it. Dang near every text box on FaceBook has it. Why don't we? Seveal people told me that there must be a way to enable it, because it's a GSA and Google runs it on their site. Now, I'm as guilty as the next guy when it comes to assuming how hard/easy something is going to be. I'm not pointing fingers. As with most things, there's a little more to it.

First off, the Ajax toolkit from Microsoft has an auto complete extender. It's great for running against SQL tables, or XML files or just about any data source. You can get back the ID of the record that the user selected and really make things snazzy. The question is, how do I use a GSA as a data source?

The GSA does return results in XML, but it doesn't do wild card queries. You can't do a search for "hea*" and get back head, hearing, heart and things like that. You get Dr.Hea and some mis-spellings and that's it. I did some looking on the Google Code site and found a "Search as you Type" project that seemed to do just what I wanted. It said in the documentation that you could turn any text box into a Google suggest box. It was written in PHP but I figured I could download it and convert the page to .Net. Most of it was in javascript files anyway so no biggie. Except that the page doesn't connect to a GSA. It has a pipe delimited text file that it uses as the demo source for the drop down. I looked through the readme.txt looking for some way to magically refernce the GSA. Nothing. What I had found was a Google Base code project that did the same thing as the ajax toolkit from Microsoft. I was right back where I started.

I fumed for a little bit. I drummed my fingers on my desk. I went back to Google's site and looked over their page source and javascript files. Then, as I was taking a swig of Red Bull, I realized what Google was doing. They weren't running against their index either.

Google is fast but not so fast that they can ajax call from your browser back to their index and back to your browser with search results each time you press a key (Update 7/12/2011:  Actually, they are that fast now.  Most of my speculations about Google in this post are obsolete). They have been in the search business for quite a while so there is no doubt that they know the top 1,000 search terms for words that start with each letter of the alphabet. The top 1000 As, the top 1000 Bs and so forth. Google had compiled a list of the Top 26,000 key words (something like that, I'm gusessing) and that's what they are running against when they do the Google suggest ajax call.. That's why when you do an obscure search it doesn't show anything but when you hit "search" you get results.

Now, back to my problem. It's not a problem anymore. I can run a report against our GSA, get back the top 10,000 or so search results, filter out the trash, and have everything I need in a nice and tidy XML document. I can put it in a SQL table or leave it in XML. I'll b able to sort it either way. Now I can use the ajax toolkit Auto Compete extender and in a short amount of time I have the same functionality as Google Suggest for our GSA. Only I'll be using .Net.

I'll post the code and link to the search page when I'm done. Shouldn't be long (will I ever learn to stop saying that).

Wednesday, February 11, 2009

Debugging and Windows Service in VB.Net

Perhaps this is helpful, perhaps not.  I've spent the last 45 min looking over various blog posts and .Net sites trying to find an easy way to debug an NT service.  I kept coming across, install the serivce, start it, attached  a debugger to a process...etc.  I know there is an easy way to do it because I've used it several years ago in .Net 1.1.  I gave up searching and went looking through old source code and found it. 'Tis below:


'****Modified by JWear on 4/12/2006****

Private Sub New()
If Debugger.IsAttached = True Then
' debug code: allows the process to run as a non-service
' will kick off the service start point, but never kill it.
' shut down the debugger to exit
'Open this page for help ' 'http://www.codeproject.com/dotnet/DebugWinServices.asp
Dim service As New YourService
Dim tempargs() As String
service.OnStart(tempargs)
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
Else
'Original Code Below
ServicesToRun = New System.ServiceProcess.ServiceBase() {New YourService}


System.ServiceProcess.ServiceBase.Run(ServicesToRun)
'Original Code Above
End If
'**************

End Sub

I left the page where I got it in the comments, a hat tip to the original site. The page is no longer available.