Online friends you have never met (not even online)

I was looking through my "spaces" messages and friend requests today and I noticed there are about 15 friend requests from people I do not know. Now, this might seem normal to some people, but I wonder what is compelling people to want to "be my friend". Did they read an entry on my blog that touched their heart? Or, are they trying to gather online friends, as if it is some contest. Or, is it something else?
 
I am a bit more liberal with linking to people on some sites than others, but I don’t think I have added many Internet "friends" whom I had not at least had an online conversation with. Yet, I have 15 people who have not even commented on this blog who want me to be their online friend.
 
If you are one of these people, please understand that I am not rejecting you. I write this blog to push out ideas, most of them insights in computer programming. It is not an attempt to gather online friends. If you are sincere about wanting me to add you, then let’s at least meet. Drop a comment and let’s converse.
 
There is a part of me that wonders what new scam can be perpetuated by adding someone as a friend. It is too much work, I would think, just to get my personal email, but maybe that is it? I am not sure, but I am not adding these people as friends until I meet them. End of story.
 
Now, if you are one who adds a lot of online friends you have not even met online, and see the wisdom in this practice, please drop a comment. I am open to hearing how this is a good thing.
 
Peace and Grace,
Greg

Working with the Flex Framework

This blog entry is about the Flex Framework. I just recently received a project from a vendor. It is written completely in Flex, except for a web service to get data to the application (unnecessary, I have found out, but I do like the SOA patterns, so this one gets kudos).
 
When I got the application, it was configured incorrectly, and everything was hardcoded. I had three things I pushed back on the team:
  1. Pulling from QueryString had to work in all environments
  2. I need to have the maps pulled from a configuration file
  3. I need to be able to set the web service location in configuration

Due to the other projects we have this team on, I ended up doing it myself.

NOTE: This application has to get tings off of the querystring, at least for now, due to constraints in the specifications. It will likely morph into a cleaner FORM post in the future.

Pulling from QueryString in all environments

The original code had the following line:

var params:String = Application.application.parameters.params;

Here is is in context:

public function initComp():void {
       
      var params:String = Application.application.parameters.params;
     
      if (params.length > 0) {
            readParams(params);
            currentState = "showMap";
            mapCont.addMapSource("1" , "lot1.swf", "Lot – 1", "Description for lot 1",
                  new mapPoint(33.934932, -84.174615), new mapPoint(33.930329, -84.16698),
                  980, 634);
           
            mapCont.addMapSource("2" , "lot2.swf", "Lot – 2", "Description for lot 2",
                  new mapPoint(32.847887, -96.865415), new mapPoint(32.84229, -96.857924),
                  863, 767);
                 
      }
      zoomBar.value = 1;
}

This routine is called from the mx:Application tag, which is fairly straightforward Flex. I am fairly certain I have some Flex Framework readers out here that can help me with this one. The line var params:String = Application.application.parameters.params; was not working on my machine. I kept getting a null instead of the value. When I install the application they compiled it works. I did not have a project file, if FlexBuilder creates one, so I did not have any compilation properties, if there are any. Enough of this aside; just ping me if you have an answer.

I went out and found that you can pull from JavaScript by working through a few hoops. First, I needed the routine to grab the querystring, which I found here. Here is the code in the JavaScript:

<script language="JavaScript" type="text/javascript">
      var jsReady = false;
     
function isReady() {
         
return jsReady;
      }
     
function pageInit() {
          jsReady =
true;
      }
     
     
function GetQueryString()
      {
           
var s = window.location.search.substring(1);
           
return s;
      } 
</script>

<
body scroll="no" onLoad="pageInit();">

Easy enough. I am not sure I like search.substring(1), as it is not explicit, but it works fine. Now to my Flex file. First I need an import to use the libraries that pull from JavaScript in the page.

import flash.external.ExternalInterface;

I now needed some code to call the JavaScript routine in action script. The initComp() routine was refactored to avoid having all of the load code. The original is shown above.

public function initComp():void
{
      //Pull the parameters from the querystring
      pullParameters();
      InitConfigLoader();
}

And here is the refactored routines to pull parameters:

private function pullParameters()
{
      params = Application.application.parameters.params;
     
      if(params == null)
      {
            params = EnsureParamsPulledFromQueryString(params);
      }
}

private function EnsureParamsPulledFromQueryString(params:String):String
{
    trace("params are null");
    //Have to run JavaScript for QueryString
    //BABELFISH: Tienen que funcionar el Javascript para QueryString
    var isAvailable:Boolean = ExternalInterface.available;

    //TODO: This should use a timer?
    if(isAvailable)
    {
        if(checkJavaScriptReady())
        {
            params = ExternalInterface.call("GetQueryString");
        }
    }

}

The magic is in the second routine, which fires off the GetQueryString method in JavaScript. Pretty slick, eh? If you want JavaScript to call into Flex, you also need to set up a callback method, but that is beyond what we are doing right now. Here is what happens.

  1. Try to pull parameters from the application object (old code)
  2. If fails, run the pullParameters method and pull from JavaScript GetQueryString
  3. This returns the querystring as a string

Now, this was not good enough for me, as the querystring was in this format:

index.aspx?000000001^vehicle1|000000002^vehicle2|000000003^vehicle3|000000004^vehicle4|000000005^vehicle5|000000006^vehicle6

NOTE: The index.aspx is merely a container at this time. That will change in future iterations.

I am not fond of non-delimited querystring values, as it leaves me no way to add addtional values. As this is not deprecated in the code, I had to leave this alone. The first condition I coded was the normal multi-parameter method of pulling:

    if(params.search("&") > 0)
    {
        //split the string
        //BABELFISH: parta la secuencia
        var splitQueryString:Array = params.split("&");
       
        //Find the correct variable and get rid of ‘vehicles’
        //BABELFISH: Encuentre el variable correcto y líbrese de ‘ vehicles’
        var i:uint;
        for(i=0;1<splitQueryString.length;i++)
        {
            if(splitQueryString[i].substr(0,8) == "vehicles")
            {
                params = splitQueryString[i].toString().replace("vehicles=", "");
                break;
            }
        }
    }

I am fairly certain there is a better syntax here (I could write it shorter in C#, at least), so I am going to learn more Flex to see if I can shorten this up a bit. I am asking here if the string has an ampersand (&), which indicates more than one querystring argument. I then look for the string with vehicles, split it and grab the right hand part of the string. The replace is fairly crude, but it works. This covers this type of string:

index.aspx?debug=true&vehicles=000000001^vehicle1|000000002^vehicle2|000000003^vehicle3|000000004^vehicle4|000000005^vehicle5|000000006^vehicle6

Tested and it works. But what if there is only one argument. It will not find the ampersand, but it will find an equals sign (=). So, I add this condition.

    else if(params.search("=") > 0)
    {
        //See if this is vehicles or something else
        //BABELFISH: Vea si éste es vehículos o algo más
        if(params.substr(0,8) == "vehicles")
        {
            params=params.replace("vehicles=", "");
        }
        else
        {
            params = "";
        }
    }

I have now got something that will pull the string when it is correctly set up as key/value. I also avoid the wrong key, if the single key does not contain the information I want. Any of these URLs yield the correct answer:

index.aspx?000000001^vehicle1|000000002^vehicle2|000000003^vehicle3|000000004^vehicle4|000000005^vehicle5|000000006^vehicle6

index.aspx?vehicles=000000001^vehicle1|000000002^vehicle2|000000003^vehicle3|000000004^vehicle4|000000005^vehicle5|000000006^vehicle6

index.aspx?debug=true&vehicles=000000001^vehicle1|000000002^vehicle2|000000003^vehicle3|000000004^vehicle4|000000005^vehicle5|000000006^vehicle6

And, I have been pessimistic enough that these URLs do not crash anything:

index.aspx
index.aspx?debug=true

One problem solved.

NOTE: As I went to "press" on this, I found that this type of URL could crash the application, so I have to refactor again.

index.aspx?debug=true&

Working with a configuration file

Coming from an ASP.NET world, I use configuration files all of the time. While you cannot change elements on the fly and have the application continue to run without rebooting (not completely true, as you can have your own "config" files), you can customize installs on different machines. What this means, to me, is I can run a variety of like web applications with different skins (configured) and even turn on an off features in config. This is critical to my work, as it stands today, as we produce customized websites with identical funcationality (at least most of it). One engine, multiple sites is a much better option than multiple engines, multiple sites — at least from a maintenance standpoint. Surprised But I digress, as we all know how important configuration is.

As far as I can tell config.xml, the Flex config file, compiles into the application. It is also copied to the output directory, which I do not understand, as I see no way to pull from it at run time. If somebody knows a built in way, let me know. Here is the solution I employed.

I found a blog entry from Ryan Guill which details a component called configLoader (you can find the blog entry here). I included the componet inside my Flex project under the com/util package (create folders and you create package names). Pulling with this is fairly simple. First, you have to pull in import statements to include the package.

import com.util.ConfigLoader;
import com.util.ConfigLoaderEvent;

Next, I have my Init for the config loader.

private function InitConfigLoader()
{
      configLoader = new ConfigLoader("config.xml");
      configLoader.addEventListener(ConfigLoaderEvent.COMPLETE,configLoader_complete_handler);
      configLoader.addEventListener(ConfigLoaderEvent.FAULT,configLoader_fault_handler);
      configLoader.load();
}

Pretty standard. Load the file and careate events to listen to events. This is also straight from the blog page. When it finishes loading, I end up in the routine configLoader_complete_handler, which looks like this:

public function configLoader_complete_handler ( e:ConfigLoaderEvent ) : void
{          
      configXML = e.data; 
      useConfig(configXML);     
}

And, I procede to tear out the XML in the useConfig routine.

public function useConfig( xml:XML ) : void
{
    var i:uint;
    for(i=0;i<xml.maps.map.length();i++)
    {               
        var mapId:String = xml.maps.map[i].ID;
        var source:String = xml.maps.map[i].mapSource;
        var mapName:String = xml.maps.map[i].name;
        var mapDescription:String = xml.maps.map[i].description;
        var ulMapPoint:mapPoint = new mapPoint(xml.maps.map[i].upperLeftLat, xml.maps.map[i].upperLeftLong);
        var lrMapPoint:mapPoint = new mapPoint(xml.maps.map[i].lowerRightLat, xml.maps.map[i].lowerRightLong);
        var x:Number = xml.maps.map[i].imageX;
        var y:Number = xml.maps.map[i].imageY;
       
        mapCont.addMapSource(mapId, source, mapName, mapDescription, ulMapPoint, lrMapPoint, x, y);       
    }   
}

The XML for this routine is here:

<config>
    <webServicePath>http://localhost/MyWebService/webServiceModule.aspx</webServicePath>
    <maps>
        <map>
            <ID>1</ID>
            <name>Lot – 1</name>
            <imageX>600</imageX>
            <imageY>400</imageY>
            <description>Lot 1 Description</description>
            <mapSource>lot1.swf</mapSource>
            <upperLeftLat>33.934932</upperLeftLat>
            <upperLeftLong>-84.174615</upperLeftLong>
            <lowerRightLat>33.930329</lowerRightLat>
            <lowerRightLong>-84.16698</lowerRightLong>
        </map>
        <map>
            <ID>2</ID>
            <name>Lot – 2</name>
            <imageX>600</imageX>
            <imageY>400</imageY>
            <description>Lot 3 Description</description>
            <mapSource>lot2.swf</mapSource>
            <upperLeftLat>32.847887</upperLeftLat>
            <upperLeftLong>-96.865415</upperLeftLong>
            <lowerRightLat>32.84229</lowerRightLat>
            <lowerRightLong>-96.857924</lowerRightLong>
        </map>
    </maps>
    <screen width="500" height="350" />
</config>

Pulling the web service to get data is also easy, so I now have an application that can run on any system, with multiple maps configured. There are still a few things I need to do, but it is much better than it was a few hours ago. I also refactored the web service into testable libraries, which I briefly covered in my last blog entry.

Peace and Grace,
Greg

Why I love TDD

I just got back a project from a new vendor we are working with. I have to pass this project on to a client of ours, but first I want to make sure all of the .NET code is obfuscated. No big deal overall, as we expected this company was mid-level developers and I would have to dink it.
 
As expected, all of the code was contained in the asmx, so I decided I would start moving code to another project. I run through and figure out the lowest level item, which is to create a dictionary object for the string that will be sent to the webservice from a web app (don’t ask, it gets rather complicated. So, what do you do? Write a test. The code looks something like this:
 
[TestMethod()]
[
DeploymentItem("CompanyName.Client.dll")]
public void CreateDictionaryTest()
{
   
string stringtoBreakUp = "{string here}";
   
Dictionary<string, string> expected =
                              
TestHelper.GetExpectedDictionaryForTest();
   
Dictionary<string, string> actual =
                       
DataBaseHelper_Accessor.CreateDictionary(stringtoBreakUp );

    foreach (string key in actual.Keys)
    {
       
Assert.AreEqual(expected[key], actual[key], "Difference in value for key " + key);
    }
}

 
I run the test and it naturally fails (there is no implementation). So I implement the code to something like this (the original code was in VB, so I left it like that — just in case you wanted to know):
 

Private Shared Function CreateDictionary (ByVal str As String) _

                                          As Dictionary(Of String, String)

 

    ‘Using Generic Dictionary to make things easier (.NET 3.5)

    ‘BABELFISH: Usando el diccionario genérico para hacer cosas más fáciles (.NET 3.5)

    Dim dict As New Dictionary(Of String, String)

 

    ‘Array desde la cadena de Esns

    ‘ENGLISH: Array from the chain of Esns

    Dim arrEsn As String() = str.Split("|")

 

    ‘Add all items to a reusable dictionary

    ‘BABELFISH: Agregue todos los artículos a un diccionario reutilizable

    For i As Int32 = 0 To arrEsn.Length – 1

        ‘Descompongo clave, valor

        ‘*** Divide Hash into ESN and description

        Dim subArr As String() = arrEsn(i).Split("^")

 

        ‘Adding ESN and Description

        ‘BABELFISH: Adición de ESN y de la descripción

        dict.Add(subArr(0), subArr(1))

    Next

 

    Return dict

 End Function

 
The original routine made a rather complex SQL string and a hashtable. It was doing the work twice, so this is the first refactor. The reason for the BABELFISH comments is the developers here are offshore in South America. I am making sure they can read what I am doing, even if it is bad Spanish. Open-mouthed
 
The test now passes. This, of course is an easy test. Now, here are a list of tests I need to do to get to the end.
  1. Create a SQL String – This is just to be able to do things the way the developers did it and will be deprecated once I move to sprocs
  2. Get Vehicle List – This is a simple Get a DataSet test. And, yes, I am not using mocks at first, so this test will both altered and moved to an integration test harness
  3. Adorn the DataSet test – This one is to add the extra info sent on the original string that is ripped into a dictionary. While it is a bit crude, I prefer massaging the data up front to playing games when you bind
  4. Integration test of Getting a list of vehicles using the old signature (list string only)

In order to facilitate, I am going to move the ESN string to a TestHelper (not the actual name, but it is the purpose), so my test changes to this:

[TestMethod()]
[
DeploymentItem("CompanyName.Client.dll")]
public void CreateDictionaryTest()
{
   
string stringtoBreakUp = TestHelper.GetEsnString();

   
Dictionary<string, string> expected =
                              
TestHelper.GetExpectedDictionaryForTest();
   
Dictionary<string, string> actual =
                       
DataBaseHelper_Accessor.CreateDictionary(stringtoBreakUp );

    foreach (string key in actual.Keys)
    {
       
Assert.AreEqual(expected[key], actual[key], "Difference in value for key " + key);
    }
}

The change here is highlighted. Why move this to another class? I will need this same information over and over again. Looking at the test that gets a list from the database (the integration test), you see this:

string Esns = TestHelper.GetEsnString();
DataSet expected = TestHelper.GetDataSetOfVehiclesForTest();

 
It doesn’t get much easier to put the same data in each routine than to use a single method (code smell 101 – repeat code is BAD). By creating this helper class, I can feed each of my routines. But, it gets even sweeter. When I move the tests to an integration class, they can use the same helper. And, when I refactor to mocks, I already have a routine that helps me define what the mock should look like and deliver. Sweet!!!!
 
But, this is not even why I love TDD. When I got to my final test, which will likely remain an integration test, I went red after implementation. It delivers the exact same data set as the previous test, so it should not fail. But it did. In a non-TDD world, I would have searched for the problem for a long time, seeing the results of the issue on the UI. In TDD, I see that I have no data in the DataSet. I know the routine that grabs the data works, as it was just tested, so I can be confident the problem is in the current routine. A quick look at the routine reveals what I have not hooked  up correctly … and I do not even have to use the debugger to find it. Can life be sweeter than this.
 
If you have not been sold yet, you probably never will. But, I can’t sell all of the people all of the time.
 
Peace and Grace,
Greg

Consuming XML in ASP.NET 2.0+

The question came into the Microsoft Expression Web forum. I would have answered it there, but two things happened:

  1. Microsoft is dinking with the site tonight and it is broken as soon as you sign in with passport.
  2. I felt this was better here

Let’s ignore #1 for now, as it is out of my control and focus on #2. While this post was in Expression, it is a problem that everyone who attempts to consume XML will run into. Here is the question, so you have the context:

I have an Access 2007 Database and I want to export data in an XML format for inclusion into my web site.  While Access will export the file, it is in a format EW does not accept when I try to create a Grid View.

<?xml version="1.0" encoding="UTF-8" ?>
- <dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2008-06-18T11:20:50">
- <WebMachines>
<MachineID>6407</MachineID>
<TypeMachine>AUTO SCREW MACHINES, SWISS, CNC-MILL & SUB SPDL</TypeMachine>
<Year>2000</Year>
<Manufacturer>Nomura</Manufacturer>
<Model>NN-13TB</Model>
<Control>Mitsubishi Meldas 520L</Control>
<Condition>Very Good</Condition>
<List>2000 Nomura NN-13TB Mitsubishi Meldas 520L</List>
<Code>A8175MS</Code>
<Featured>0</Featured>
</WebMachines>

Now the XML data that is in the Sample file Members.xml works fine.  I guess I am confused why EW will not accept an XML file from an up-to-date version on Access 2007???

<members>
<member isactive="true" groupcolor="#FFCC3333" name="Tom Jackson" datejoined="10/06/2006" />
<member isactive="false" groupcolor="#FFA4AB28" name="Stacey Footheart" datejoined="11/10/2006" />
<member isactive="true" groupcolor="#FFA6D877" name="Jack Herdin" datejoined="6/10/2006" />
<member isactive="true" groupcolor="#FF138C48" name="Kim Getruds" datejoined="4/15/2006" />
<member isactive="false" groupcolor="#FF5FADB9" name="Larry Nusom" datejoined="7/12/2006" />
<member isactive="true" groupcolor="#FF3B1076" name="Gary Heart" datejoined="9/21/2006" />
</members>

Is there anyway to export data from a Access 2007 database that EW will accept cleanly?  I have tried every possible way to export an XML file format that EW will accept. I thoughts these programs were suppose to work with each other cleanly?

I will show two ways to skin this cat. Before doing that, we need to clean up the XML a bit. First, all ampersands need to be convered to &amp;. The same is true if there is any other reserved word. The second is to close out the </dataroot>. And the third is to get rid of the hyphens (I assume it was copied out of Internet Exploder.

<?xml version="1.0" encoding="UTF-8" ?>
<dataroot xmlns:od="urn:schemas-microsoft-com:officedata" generated="2008-06-18T11:20:50">
<WebMachines>
<MachineID>6407</MachineID>
<TypeMachine>AUTO SCREW MACHINES, SWISS, CNC-MILL &amp; SUB SPDL</TypeMachine>
<Year>2000</Year>
<Manufacturer>Nomura</Manufacturer>
<Model>NN-13TB</Model>
<Control>Mitsubishi Meldas 520L</Control>
<Condition>Very Good</Condition>
<List>2000 Nomura NN-13TB Mitsubishi Meldas 520L</List>
<Code>A8175MS</Code>
<Featured>0</Featured>
</WebMachines>
</dataroot>

<asp:xml>

Our first method of solving this is the ASP.NET XML control. Since the person was attempting to do this in Expression, let’s start there.

  1. Add the XML file to the website (App_Data is the best location, IMO)
  2. Drag the XML node <WebMachines> onto the page
  3. Preview

If you have a single WebMachines tag, you end up with a vertical display of the column nodes. If you have more than one, you end up with a grid. Fairly simple stuff. The XSL does all of the dirty work and you can edit the XSL file created or use the presets.

GridView and XmlDataSource

This is a bit more involved, but still fairly simple. As the XML is not using attributes (the default for auto generated columns), you will have to tell how to render the GridView.

First, drag an XmlDataSource control on the page. Browse for the xml file and select it for the first text box. Do not fill the XSLT textbox (2nd down), but do set the XPATH to /dataroot/WebMachines.

Then, drag a GridView on the page and set it to the XmlDataSource. You then will have to add templated columns and drag a label into each one. Here is the first column (MachineID):

<asp:TemplateField HeaderText="ID">
  <ItemTemplate>
    <asp:Label runat="server" ID="lblMachineID" Text=’<%#XPath("MachineID")%>’/>
</ItemTemplate>
</asp:TemplateField>

The XPATH is the key here when you are not using attributes. The complete source of the page is as follows, although I am only showing a few of the "columns" in the XML file.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<%@ Page Language="C#" %>

<html dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Untitled 1</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:xmldatasource id="XmlDataSource1" runat="server" datafile="Test.xml" xpath="/dataroot/WebMachines">
    </asp:xmldatasource>
        <br />
        <asp:gridview id="GridView1" runat="server" datasourceid="XmlDataSource1" autogeneratecolumns="false">
          <Columns>
         <asp:TemplateField HeaderText="ID">
           <ItemTemplate>
             <asp:Label runat="server" ID="lblMachineID" Text=’<%#XPath("MachineID")%>’/>
         </ItemTemplate>
         </asp:TemplateField>         
         <asp:TemplateField HeaderText="Machine ID">
           <ItemTemplate>
             <asp:Label runat="server" ID="lblTypeMachine" Text=’<%#XPath("TypeMachine")%>’/>
         </ItemTemplate>
         </asp:TemplateField>
                   <asp:TemplateField HeaderText="Year">
           <ItemTemplate>
             <asp:Label runat="server" ID="lblYear" Text=’<%#XPath("Year")%>’/>
         </ItemTemplate>
         </asp:TemplateField>
                 <asp:TemplateField HeaderText="Manufacturer">
           <ItemTemplate>
             <asp:Label runat="server" ID="lblManufacturer" Text=’<%#XPath("Manufacturer")%>’/>
         </ItemTemplate>
         </asp:TemplateField>
                           <asp:TemplateField HeaderText="Model">
           <ItemTemplate>
             <asp:Label runat="server" ID="lblModel" Text=’<%#XPath("Model")%>’/>
         </ItemTemplate>
         </asp:TemplateField>
        </Columns>    
    </asp:gridview>
    </form>
</body>
</html>

Wasn’t that quite easy? Of course, the tools do not do all of this for you, which may be "problematic" for some, but the syntax is still completely declarative.

Peace and Grace,
Greg

ASP.NET MVC Preview 3: PLaying with ViewPage

Note: This entry may ramble a bit, as it is being written as I experiment.
 
I have now been in the waters long enough to be baptized and wanted to play around a bit while I blog. This first post is based on an issue I noticed in Preview 2 with the MVC Membership Starter Kit (blogged in my last entry) and how I played around with it.
 
Suppose you wish to include some JavaScript in your page and feed it from view data. Let’s do something really simple that is potentially error prone. We are going to create a simple form with a button and we are going to use ViewData. Simple enough, eh? To make this simple, let’s just whack the default set up. After all this is just a test, right? In this, we will create a JavaScript that displays a message.
 
So, create a new MVC project from the template. Then, open the controller and put the following in the index() action result method:
 
public ActionResult Index()
{
    ViewData[
"Title"] = "Home Page";
    ViewData[
"Message"] = "Welcome to ASP.NET MVC!";
   
//Add this line
    ViewData["AlertMessage"] = "This is a message in a popup";

    return View();
}

 
Now, move to the view and place the JavaScript bits in the View.
 
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%= Html.Encode(ViewData["Message"]) %></h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
   
</p>
    <script>
    /* <![CDATA[ */
    alert('<%= ViewData["AlertMessage"] %>’);
   
/* ]]> */
    </script>

</
asp:Content>
 
The portion highlighted is all that I added to the mix. If we run the page now, we have a popup with an alert message. The next step is to add a button to the form, so we can pretend this is a form. So, I add the following:
 
    <% using(Html.Form("Home", "SimpleSubmit"))
       {
%>
      
       <%
=Html.SubmitButton("submit","Submit", null) %>
      
    <% } %>
 
While this is not a test, let’s run a red … green … refactor exercise anyway, even if it is backwards (should have tested the controller first). I open the page again and there is a button. Clicking the button produces an error:
 

Server Error in ‘/’ Application.


The resource cannot be found.

Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

Requested URL: /Home/SimpleSubmit


Version Information: Microsoft .NET Framework Version:2.0.50727.1434; ASP.NET Version:2.0.50727.1434

 
This is just what I expected! Smile Now, we will implement this in the controller as a method called SimpleSubmit() – yes, the name sucks, but this is an inane example to illustrate a point.
 
        public ActionResult SimpleSubmit()
        {
            ViewData[
"Title"] = "Home Page Submitted";
            ViewData[
"Message"] = "You just clicked my button!";

            return View("Index");
        }

 
Run the app again and click the submit button and what happens? Empty message in the popup. This is a bit nicer than preview 2, which would error out.
 
Oh, since this is an empty popup, I am going to assume we only want a popup when there is a message. One way to do this is to check if the ViewData contains this key.
 
    <% if(ViewData.ContainsKey("AlertMessage"))
       {
%>
   
<script>
    /* <![CDATA[ */
        alert('<%= ViewData["AlertMessage"] %>’);
   
/* ]]> */
    </script>
    <% } %>

This at least keeps things a bit sane, but it is not completely to my liking. How about if I control the class that feeds the page? First, we code a simple class:

public class TestClass
{
   
public string Title { get; set; }
   
public string Message { get; set; }
   
public string AlertMessage { get; set; }

    public TestClass(string title, string message, string alertMessage)
    {
        Title = title;
        Message = message;
        AlertMessage = alertMessage;
    }
}

 
Now, this does not buy me much, but it does allow me to simplify my Index() method, which makes it a decent enough refactor. The Index method now looks like this:
 
    public ActionResult Test()
    {
       
TestClass test = new TestClass("Home Page"
            , "Welcome to ASP.NET MVC!"
            , "You just clicked my button");
       
return View("Test", test);
    }
 
To make this actually work, I have one other small step. I have to change the Index declaration to take the TestClass.
 
    public partial class Index : ViewPage<TestClass>
    {
    }
 
There is another syntax you can use here if you want to avoid having an empty code behind file, which is detailed on Troy Goode’s blog. The basic syntax is:
 
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage`1[ [MyCompany.MyProject.TestClass,MyCompany.MyProject] ]" %>
 
In this, you are stating the name of the class followed by the name of the assembly it is contained in. As I mentioned, Troy has further details in this post.
 
Now, the first thought may be "you need to change the code in the page", but that is not correct. When you make a simple class like this, it can pull directly from the elements using the syntax we are already using. To prove this, let’s change the page, but avoid the Master Page, which contains the following line:
 
<title><%= Html.Encode(ViewData["Title"]) %></title>
 
The page will be changed to the following:
 
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="TestMVC.Views.Home.Test" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%= ViewData.Model.Message %></h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
   
</p>
    <% using(Html.Form("Home", "SecondSimpleSubmit"))
       {
%>
      
       <%
=Html.SubmitButton("submit","Submit", null) %>
      
    <% }
%>
    <%
if(ViewData.Model.AlertMessage != String.Empty)
       {
%>
   
<script>
    /* <![CDATA[ */
        alert('<%= ViewData.Model.AlertMessage %>');
   
/* ]]> */
    </script>
    <% } %>
</asp:Content>
 
Run the page and it works fine, so we can use one of two syntaxes when we are using ViewPage<T> with a class with simple properties:
 
alert(‘<%= ViewData["AlertMessage"] %>’);
 
or
 
alert(‘<%= ViewData.Model.AlertMessage %>’);
 
NOTE: If you are using a build prior to Preview 3 for some reason, you will have to use ViewData.Property instead of ViewData.Model.Property.
 
Now, this really does not provide me much at this point in time, but it does give me the potential to simplify rather large JavaScript sections (something more than an alert, by adding a public property for AlertJavaScriptBlock (I will work on the names later), which allows me to do something like:
 
    <% if(!ViewData.Model.IsPostBack){ %>
       <%
=ViewData.Model.AlertJavaScriptBlock %>
    <% } %>
 
There has to be a way to write this even more tersely, but I will have to figure out what <%= %> corresponds to in code (something similar to Response.Write?). If you know, just ping me, as I would love to keep the syntax as tight as possible. Regardless, "injecting" the entire JavaScript block when needed, I avoid a lot of code in the view. This is important to me as I already have components outputting a large amount of client side JavaScript (a MapQuest API component primarily).
 
One problem solved. I now have to go to themes and dink a bit further with Membership. I am sure I will blog more about these adventures.
 
Peace and Grace,
Greg

Debugging versus Testing (MVC, Web 2.0)

I have been playing with ASP.NET MVC lately and I hvae noticed one interesting artifact of the methodology, at least for time being. WIth ASP.NET, you have a good debugging experience. With MVC, you have a good testing experience.
 
This is not a blanket statement, of course, as debugging is quite easy in MVC, as long as you are in the controller. But, consider the following scenario (yes, I will give the solution to this problem, as well).
 
You fire up the MVC Membership starter kit. You hook it up to SQL Server (blog entry here). You are now able to log in. Go to change password and you end up with a NullReferenceException on this line (highlighted)
 

<script type="text/javascript">
/* <![CDATA[ */


  function starterKit_mvc_membership_validateChangePassword()
  {


    var pwd_minChars = <% =(int)ViewData["MinimumPasswordLength"] %>;

Nothing really stellar here. This is just a bug in the software. Normally, when you find a bug like this, you would go to the call stack and find out what the calling member was sending in. You would also get a good spot to set your breakpoints. This is not as straightforward, however, in MVC, because the call stack is pretty much non-existent once you are filling the view. You cannot step back into the controller and find the reason for the error.
 
In the future, Microsoft may have a solution for this. For now, you have to work with the new way of thinking and do a bit of investigation. Since this is the PasswordChange view in the FormsAuthentication folder, I am looking for hte FormsAuthenticationController. The code is not here, however, because it is a derived class.
 

public class FormsAuthenticationController
    : StarterKits.Mvc.Membership.Controllers.
BaseFormsAuthenticationController

 
So I set my breakpoints in the BaseFormsAuthenticationController instead. Line 709 yields the answer (or rather line 709 and scouring the entire PasswordChange() routine yields the answer). The only thing in ViewData is a Boolean:

// success!
ViewData["Success"] = true
;
return RenderView( "PasswordChange" );

The code ran perfectly and my password has changed, but I am still treated with an error trying to fill the JavaScript on the form. NOTE: Will hit possible solutions later.
 
The problem here is not Troy’s code, it is the experience. We all end up with bugs in our code as we write applications. In fact, we expect bugs as we code, and that is why test driven development is so important. It helps us find the bugs quickly. The problem here is a disconnect between the UI bits and the backend. And, it is not unique to MVC. A few weeks ago, I blogged about clashes between ASP.NET AJAX and the MapQuest tiled map API. I have also had issues with over engineered CSS clashing with CSS packed with controls.
 
The debugging experience on the client is very rudimentary at the present time. And, there is a huge gulf between backside debugging and client side debugging. In general, I find myself using Firefox a lot when I am working with server code that outputs client side code. Currently, Firefox has the best client side debugging tools, which leaves a huge opportunity for Microsoft, as these tools cannot adequately link the two disparate parts of the Web 2.0 application in a single debugging environment. To be fair to Microsoft, they have tried with Visual Studio and Internet Explorer. If you flip off the Disable Script Debugging checkbox, you can end up with some JavaScript debugging goodness. But, you are still debugging one set of code in isolation, even if you are using the same tool.
 
I wish I had an answer on how to solve the problem. While we want a debugger that allows us to go through the entire chain of events, it gets rather complex to link views to controllers in the debugger. It is even more difficult to follow code from server side to the client side. I am optimistic that it is not impossible, but wonder if it is possible without further bloating the development environment to the point that the experience is degraded.
 
Silverlight overcomes this problem, to a large extent, as the code is all .NET. There are still some gotchas, but you have a clean separation of client and server in Silverlight … at least if you develop the server end like a service. Software as a Service – what a unique concept! Wink MVC has the ability to overcome this problem, as well, but is a bit more complex as views are not running the code in a traditional sense. The separation is also NOT clean, at least not in the plethora of examples on the web. The same is true with web 2.0 technologies, although they are maturing a bit and people are getting the SOA/SAAS idea.
 
I am sold on the TDD aspects of MVC. As I have stated before, I am not sold that it is the only way, but MVC really does force separation of concerns. I am not sold on the current view model, especially with views peppered with ASP like code. I am sure that will change over time once the Framework understands all of the fundamental controls.
 
Now, back to the problem at hand, since somebody will ask if I don’t spout off. My first thought is one of two solutions:
  1. Create the JavaScript completely server side and inject it
  2. Flip to a different view for confirmation

#2 will be easier, but I need to solve #1 regardless to use the tiled maps (MapQuest currently) in MVC. An injection type model is easier to debug, as all of the code is server side until it is placed on the page. It does lead to having to test the UI to get the bits down and completely debug the solution, but a view of tags and code leads to the same issue. At least with an injection of client side code model, I can debug the JavaScript separately from the code that builds it. Smile

Peace and Grace,
Greg

Setting up the ASP.NET MVC Membership Starter Kit with SQL Server

I just got a chance to download and begin looking at the new ASP.NET MVC Membership bits from Troy Goode (www.squaredroot.com). The project is a starter kit that puts the standard ASPNETDB membership bits (the ones you can create with aspnet_regsql) in the MVC Framework.
 
When I first downloaded, I had a hard time getting things to work using his standard ASPNETDB instance when it was hooked up to SQL Server (not SQL Express). At first, I thought I was having a problem connecting to the database, but I created a little page called test.aspx and did the following:
 

namespace MvcMembership
{
   
public partial class test : System.Web.UI.Page
    {
       
protected void Page_Load(object sender, EventArgs e)
        {
            TryDatabaseConnection();
            TryMembership();
        }

        private void TryMembership()
        {
           
try
            {
                Response.Write(
string.Format("App name: {0}<br/>",Membership.Provider.ApplicationName));

                MembershipUser user = Membership.GetUser();
                Response.Write(
"Success on Membership<br/>");
            }
           
catch (Exception ex)
            {
                Response.Write(
"Failed on Membership<br/>");
                Response.Write(
string.Format("Error Type: {0}<br/>", ex.GetType().ToString()));
                Response.Write(
string.Format("Message: {0}<br/>", ex.Message));
                Response.Write(
string.Format("Source: {0}<br/>", ex.Source));
            }
        }

        private void TryDatabaseConnection()
        {
           
string connString = ConfigurationManager.ConnectionStrings["ASPNETDBConnectionString"].ToString();
           
SqlConnection connection = new SqlConnection(connString);

            try
            {
                connection.Open();
                Response.Write(
"Success on Database Connection<br/>");
            }
           
catch (Exception ex)
            {
                Response.Write(
"Failed on Database Connection<br/>");
            }
           
finally
            {
                connection.Dispose();
            }
        }
    }
}

I was able to connect to the database, but not the Membership bits. Rather than go through all of the steps, I will tell you what you need to do get this running quickly.

First, create your ASPNET Membership database. The easiest way to do this:

  1. Open a VIsual Studio 2008 Comand Prompt
  2. Type aspnet_regsql and hit enter
  3. Click next
  4. Keep the default "Configure SQL Server for application services" and click next
  5. Choose the database and click next, next and then finish

If you like to be a maverick, the install scripts are also located at %windir%/Microsoft .Net/Framework/v2.0.50727. It does not really matter how you create the database.

You now need to go to the sample MVC Membership web application and edit the web.config. By default, it is implicit and only contains the following Membership bits.

    <connectionStrings>
        <
add name="ASPNETDBConnectionString"
        
connectionString="Data Source=.SQLEXPRESS;AttachDbFilename=|DataDirectory|ASPNETDB.MDF;Integrated Security=True;User Instance=True"
        
providerName="System.Data.SqlClient" />
    </
connectionStrings>


<roleManager enabled="true" />

You need to fill this in. First, replace the connection string with the connection string to your database:

    <connectionStrings>
        <
add name="ASPNETDBConnectionString"
        
connectionString="Server=(local);Database=ASPNETDB;UID={Membership User};PWD={user password};"
        
providerName="System.Data.SqlClient" />
    </
connectionStrings>

You then need to fill in the implied bits with real bits. This means the <roleManager enabled="true" /> will become something like:

<membership userIsOnlineTimeWindow="20" defaultProvider="AspNetSqlProvider">
  <
providers>
    <
add connectionStringName="ASPNETDBConnectionString"
        
minRequiredPasswordLength="8"
         minRequiredNonalphanumericCharacters="1"
        
requiresQuestionAndAnswer="true"
         applicationName="/"
        
passwordFormat="Encrypted"
        
passwordAttemptWindow="10"
         enablePasswordReset="true"
        
enablePasswordRetrieval="true"
        
name="AspNetSqlProvider"
        type="System.Web.Security.SqlMembershipProvider" />
  </
providers>
</
membership>
<
roleManager defaultProvider="RoleManagerProvider"
             enabled="true"
             cacheRolesInCookie="true"
             cookieName=".ASPROLES"
             cookieTimeout="30"
             cookiePath="/"
             cookieRequireSSL="false"
             cookieSlidingExpiration="true"
             cookieProtection="All">
  <
providers>
    <
add name="RoleManagerProvider"
         type="System.Web.Security.SqlRoleProvider"
         connectionStringName=" ASPNETDBConnectionString "
         applicationName="/" />
  </
providers>
</
roleManager>

Notice the highlighted section. It is important. The normal value here is hashed, but I want to be able to reverse engineer the passwords for admin purposes (a feature I will have to add to the MVC bits). To use encrypted, I will have to work with the machineKey section of the config. This looks like this:

    <machineKey validationKey="{Validation Key Here}"
        decryptionKey="{Decryption Key Here}"
        validation="3DES"/>

If you need to gen keys, you can use Ben Strackany’s key generator. You will need a Code Project account (free) to download the project:
http://www.codeproject.com/KB/aspnet/machineKey.aspx

If you do not have an account on Code Project, and don’t want one, Peter Bromberg has created a sample page that will create these keys, as long as you want to use SHA1 for validation (yes, you can alter this):
http://www.eggheadcafe.com/articles/20030514.asp

The final step is seeding the database. The easiest way is to open the web configuration tool. When it connects to the database, it will create a record in aspnet_applications for the / application. You will have to go through the wizards to create your administrator accounts.

I have also included a script for you to run, if you are not big on using the web configuration tool. If you use the script, you will have to set up the following machineKey section in your web.config, as the passwords are encrypted using these settings (NOTE the validation key is on two lines as spaces truncates things — you must fix that in your web.config when you copy and paste this):

<machineKey
validationKey=
"2AB9BB5084E7E8E34ECAA89E37B542E50D0C7E486D606804021812400A6E2EEDAF80F5E4
798B44EC71B0403F91D33B3208C170A34453B2A51A9EDA27839C6552
"
decryptionKey="B2F58C16DEBB63B7CE25D5CD239CCDB0D71E160FE7FD65BC6CD1D0C98BAD29FA"
validation="SHA1" decryption="AES" />

Here is the script:

/***********************************************
*     ASP.NET MVC Application Seeder
*   ——————————————–
*     User Name:  Administrator
*     Password:   password!1
*
*     Security Question:
*     What is the velocity of an unladen sparrow?
*
*     Security Question Answer:
*     European or African?
***********************************************/

– Create the application
insert into aspnet_applications (ApplicationName
                               
, LoweredApplicationName
                               
, ApplicationId
                               
, [Description])
values (‘/’
        , ‘/’
        , ’3A168FD5-07E8-49FB-9C95-F8D15A9DA6E7′
        , ‘Default application for the sample ASP.NET MVC Applicatio’)
GO

– Create the administrator role
insert into aspnet_roles (ApplicationId
                                         
, RoleId
                                         
, RoleName
                                         
, LoweredRoleName
                                         
, [Description])
values (’3A168FD5-07E8-49FB-9C95-F8D15A9DA6E7′
            , ’072EA006-37E8-42DE-8FCA-BE790BF61BFA’
            , ‘Administrator’
            , ‘administrator’
            , ‘Administrator role for the sample ASP.NET MVC Applicatio’)
GO

– Create the Administrator user
insert into aspnet_users (ApplicationId
                                    , UserId
                                    , UserName
                                    , LoweredUserName
                                    , IsAnonymous
                                    , LastActivityDate)
values (’3A168FD5-07E8-49FB-9C95-F8D15A9DA6E7′
            , ‘DE313B04-D60B-4E6B-B790-8F56FDB96C17′
            , ‘Administrator’
            , ‘administrator’
            , 0
            , GetUtcDate())
GO

– Create the user membership bits
insert into aspnet_membership(ApplicationId
                              , UserId
                              , [Password]
                              , PasswordFormat
                              , PasswordSalt
                              , MobilePIN
                              , Email
                              , LoweredEmail
                              , PasswordQuestion
                              , PasswordAnswer
                              , IsApproved
                              , IsLockedOut
                              , CreateDate
                              , LastLoginDate
                              , LastPasswordChangedDate
                              , LastLockoutDate
                              , FailedPasswordAttemptCount
                              , FailedPasswordAttemptWindowStart
                              , FailedPasswordAnswerAttemptCount
                              , FailedPasswordAnswerAttemptWindowStart
                              , Comment)
VALUES (’3A168FD5-07E8-49FB-9C95-F8D15A9DA6E7′
            , ‘DE313B04-D60B-4E6B-B790-8F56FDB96C17′
   
, ‘e4esufQBWoB7uWAAaCMH5TgeqPmozkIp+YAYDrq9NInu+1ovT+GWfuDjLZPMMAiT’
   
, 2, ‘EzaAKgyIzgckUbbEzmW0lQ==’
   
, NULL
    ,
‘admin@company.com’
   
, ‘admin@company.com’
   
, ‘What is the velocity of an unladen sparrow?’
   
, ‘e4esufQBWoB7uWAAaCMH5W3g/LF9xTjDpDr0yA88cwd53dNpxV8JGkzVZPQV0a+cxrJ1v+osHSg7RLqTRU4Vaw==’
   
, 1
    , 0
    , GetUtcDate()
    ,
CAST(0x00009AB8015CEC03 AS DateTime)
    ,
CAST(0x00009AB8015CEBD4 AS DateTime)
    ,
CAST(0xFFFF2FB300000000 AS DateTime)
    ,
0
    , CAST(0xFFFF2FB300000000 AS DateTime)
    ,
0
    , CAST(0xFFFF2FB300000000 AS DateTime)
    ,
‘Administrator for the sample ASP.NET MVC Application’)
GO

– Link the Administrator user to the Administrator role
insert into aspnet_usersinroles (UserId
                                                , RoleId)
values (‘DE313B04-D60B-4E6B-B790-8F56FDB96C17′
            , ’072EA006-37E8-42DE-8FCA-BE790BF61BFA’)
GO

You should now be able to log in with the admin credentials (listed in the flower box at the top of the SQL script).

Beyond learning how to hook the ASP.NET MVC site into SQL Server Standard, Dev or Enterprise, you have learned how to fix membership bits. Just follow the steps in this blog post to fix an errant membership database. Here is the order of troubleshooting:

  1. Can I connect to the database?
    If no, you have to fix the connection string.
  2. Can I connect to membership? Things to check if not
    a) Do I have web.config set up correctly for membership?
    b) Do I have web.config set up correctly for roles? (if you are using roles)
    c) Do I have an application node in aspnet_membership?
    d) Am I using the correct machine keys?

Hope this helps!

Peace and Grace,
Greg

Testing Patterns for Data

Yesterday, I posted about using enums versus a persistent store. I got a comment back from another proponent of TDD and separation of concerns (original post here). I have included the entire comment, as I want to make sure to give credit to the good ideas in the comment and show that my post is not aimed at the comment, but a tangent that popped into my mind. The comment was merely a catalyst for this entry:
 
I’m torn on this issue. In the Visual FoxPro world, we put all kinds of metadata in dbfs. These days, I don’t like putting anything outside the scope of my unit tests. I think the options in the list are the result of user stories, so should live in the application, not the db. Furthermore, putting the metadata in the DB puts it beyond the scope of thorough change management in general, not just unit tests.
 
All I am focusing on here is the "outside of the scope of my unit tests" bit. I am also envisioning what a newbie to TDD might mean if he had stated the same thing, and counter the thought process.
 
With a "normal" testing pattern, like a "normal" development exercise, you often end up with a chain from one end to the other. But, you can solve this problem with dependency injection. While this is relatively new to Microsoft, having released their first application block in this arena last month (The Unit Application Block), mocks have long been a part of unit testing frameworks. Both nunit, a unit test framework ported from Java’s junit, and mbunit have mocks. As an aside, mbUnit uses RhinoMocks, a great open source mock object framework. With the plethora of choices here, there is no reason to go to the database to get enum values, as you do not have to include production values to test.
 
In addition, there are patterns that allow you to easily inject test bits into your code, like the Repository Pattern. You have to think a bit "upside down" to use the patterns (paradigm shift), but there are plenty of examples on the web. In fact, there is a really nice example of the Repository Pattern in Rob Connery’s video series for the MVC Storefront (MVC Framework ECommerce project) – about 2 minutes in he mentions not wanting to go to a database – tres kewl. Here are some links:
 

Here is the basic step by step:

  1. Create an interface – this is primarily to avoid tight coupling. Rob’s interface is
    public interface ICatalogRepository {
        IQueryable<Category> GetCategories();
    }


    NOTE: This gets more complex as time goes on; this is just enough code to set up a test.
    Also note that the design here is to make the interface as simple as possible and still get the word done.
  2. He codes a very basic service (This will actually be coded after the tests, so it is just stubbed) – the idea here is to get the design down before coding. This step is optional, as the service is not used for a few steps.
    public class CatalogService
    {

        public IList<Category> GetCategories() {
           
    throw new NotImplementedException("Write a Test!");
        }
    }

    NOTE: I love the exception message here! Open-mouthed
    This part becomes important soon, but I have included it primarily for the error message.

  3. He creates a test repository class that spits out fake data. This is the main point of this blog entry. I have added some comments to the code so you see what is going on.
    public class TestCatalogRepository : ICatalogRepository {

        public IQueryable<Category> GetCategories()
        {
           
    IList<Category> result = new List<Category>();

            for (int i = 1; i <= 2; i++)
            {
               
    //Create parent object
                Category c = new Category();
                c.ID = i;
                c.IsDefault = i == 1;
                c.Name =
    "Parent" + i.ToString();
                c.ParentID = 0;
                c.Image =
    new CategoryImage("thumb", "full");

                //Create children objects (hierarchy)
                int subCategoryID = 10 * i;
               
    for (int x = 10; x < 15; x++)
                {
                    Category sub =
    new Category();
                    sub.ID = subCategoryID;
                    sub.Name =
    "Sub" + x.ToString();
                    sub.ParentID = i;
                    sub.Image =
    new CategoryImage("thumb", "full");
                    result.Add(sub);
                    subCategoryID++;
                }
                result.Add(c);
            }

            return result.AsQueryable<Category>();
        }
    }

    This might seem like a lot of code to write before tests, but it is actually setting up fake data for the test. Note that this uses the interface ICatalogRepository. Now, let’s get to some testing.

  4. First test is to ensure the Repository Return set is not null
    [TestMethod]
    public void CatalogRepository_Repository_Categories_IsNotNull() {
        ICatalogRepository rep =
    new TestCatalogRepository();
        Assert.IsNotNull(rep.GetCategories());
    }

    Now, if you wanted to test your TestRepository, you would test this method first, but the important thing here is we are making sure our test class is solid before we go to testing the code that will use a repository (our service). We are also testing the test in this case.

  5. Now you add a method to the service to instatiate it with a repository. Baby steps.
    public class CatalogService : Commerce.MVC.Services.ICatalogService
    {
       
    ICatalogRepository _repository = null;
       
    public CatalogService(ICatalogRepository repository)
        {
            _repository = repository;
           
    if (_repository == null)
               
    throw new InvalidOperationException("Repository cannot be null");
        }

        public IList<Category> GetCategories()
        {
           
    throw new NotImplementedException("Write a Test!");
        }
    }
  6. And the test is written like so
    [TestMethod]
    public void CatalogService_Can_Get_Categories_From_Service()
    {
        ICatalogRepository rep =
    new
    TestCatalogRepository();
        catalogService =
    new
    CatalogService(rep);

        IList<Category> categories = catalogService.GetCategories();
        Assert.IsTrue(categories.Count > 0);
    }

  7. Now you fire the test and it fails with a NotImplementedException, as expected. This is the re in red … green … refactor.
    For those who are not into TDD, you might wonder why you force a test to fail first. The best answer I can think of is to ensure you have not aready implemented the code and also to ensure you have not accidentally written something that is already true. As developers are generally over optimistic, this is more important than one might think.
  8. Now we add just enough code for our test to pass.
    public IList<Category> GetCategories()
    {
       
    return _repository.GetCategories().ToList();       
    }
  9. Our test passes, so we go to the next step, which is to test the parent-child relationshps …

I don’t want to transcribe the entire video, so I will quit here, but you should now see that by passing in the object that gets the data, you can make a test object quite easily, without employing depency injection. This pattern is not applicable everywhere, of course, but it works here. You should also note that testing involves methodically going from test to code. Rob’s example might make a purist a bit peeved, but I am fine with working with stubs for your red light condition.

When I said "upside down" earlier, I was speaking of passing the Repository to the service so the service can be tested with more or less "arbitrary" test code. It is also a paradigm shift when one thinks about what is being tested versus where we usually being our code. In so many applications, we start writing the database first or the UI first and we work from end to end. In Rob’s example, you are working on the business logic first and moving outward to the UI and database. There are two benefits to this method:

  1. We are thinking in terms of business needs rather than application needs. This may seem like a subtle distinction, and in many ways it is, but the change in thought pattern is quite profound.
  2. We are working out use cases rather than pages or tables. This is not subtle. We are working the usage of our system first, rather than attempting to bolt on a user experience afterward.
    NOTE: This is what I like to call "use case driven development"

To summarize, there are quite a few ways to avoid going to a database in a unit test. Two mentioned here are mocking the data in a mock object and flipping the pattern so your service takes an object as part of its constructor. I will have to save mocks for another day, as my verbal diarrhea has eaten up all of the time I have to write this post. Crying

Peace and Grace,
Greg

Why enums are not a good replacement for lookup tables

Here is the issue, in a nutshell. You have a drop down you want to fill. You have two choices*:
  1. Put the options in a database table
  2. Put the options in an enum

* NOTE: I realize there are other choices, like hardcoding your drop down, etc., but I am trying to choose the saner options. Wink

Both are perfectly good options, in certain situations. In general, however, you want the option that has the easiest path for change. This is not the enum. Now, there are instances where the enum option is going to be easier. In those situations, you probably want to put the enum in a library separate from your working bits, especially if you have tightly coupled your objects to your back end. I am going on tangents now that I have already discussed. Click here for a bit about separation of concerns.

Here is the situation I am looking at. First, the enum:

public

enum Foo : int
{
    [Description(
"Bar Option 1"
)]
    Bar = 1,
    [Description(
"Bar Option 2"
)]
    Bar2 = 20
}

Nice use of attributes to add descriptions, right? And, you can code something like so to pull the descirptions for your DropDownList:

ddEvent.Items.Insert(0,
new ListItem(enum_support.GetDescription(Foo.Bar), Convert.ToString((int)Foo.Bar)));

ddEvent.Items.Insert(0,
new ListItem(enum_support.GetDescription(Foo.Bar2), Convert.ToString((int)Foo.Bar2)));

At this time, it seems we are rather clever. But the boss asks to update the drop down to say change "Bar Option 1" to read "Power Up" and "Bar Option 2" to read "Power Down". You are now recompiling libraries for a simple label change. Ouch!

There is another issue with storing these items in an enum in this fashion. When I want to produce a report, I have to invoke something like this to fill in the report.

lblEvent.Text = r.Event.ToString();

I can’t simply pull the data from the database. I could add a lookup table to match the enum, but I then risk having the table and the enum out of sync. To keep it in sync, I could either generate the enum on the fly (in memory only) or code generate the enum, but why should I have this extra step? It makes no sense.

There are good reasons to use enums. Enums are great, for example, when you have an input for a method that can only take a limited set of values. You use the enum to avoid having to check values on the int being passed in. But this type of enum is specific to the class or classes in the library. It is not a global enum.

I am a proponent of using a persistent store for metadata. I have nothing against an enum class coded inside some helper library, but if the enum is used globally it better be in a helper library rather than located in the first library that uses it. The word is REFACTOR. ALthough I am not against these types of enums, I still believe that most of your global enums should be lookup tables. And, if you are grabbing data with numerics that correspond to the enum, I would state it is mandatory that you create a lookup table rather than an enum. By mandatory, I do not mean the enum will not work, just that it is less flexible (extensible) and requires much more work to update (compile versus SQL change).

Peace and Grace,
Greg

Deploying a local database to your ISP (SQL Server Database Publishing Wizard)

I have seen a few posts lately where people are having a hard time getting a database up to their ISP. While there are tutorials on using SQL Express and an embedded database (in the App_Data folder), I have seen very few posts that deal with publishing to a database directly. I am going to cover the SQL Server Database Publishing Wizard.

Before going forward, you have to have SQL Server installed locally. This can be SQL Server Express. You should also have Visual Web Developer installed, although I do not think this is mandatory, as the tutorial will show.

Direct Publishing

First, let’s take the direct route. It is the easiest way to get the database up. The less direct route will use most of the same steps, although it is a bit more complex, as you have to run the script on the server.

First, download the SQL Server Database Publishing Wizard 1.1 from Microsoft. The page can be found here. It is a fairly simple install, so I won’t go through its steps. Once you are installed, we can go on.

1. Start the Database Publishing Wizard – In Vista, you can type in the search box (just above the start button) to quickly get to it. If you have already upgrade from Vista to Windows XP ;-P, you can go to Program Files >> Microsoft SQL Server Database Publishing Wizard >> Database Publishing Wizard and start it there.

Start

2. Click Next on the Welcome Screen

3. Select your local database to log into. For most of you, you will only have to change localhost (the default) to .SQLEXPRESS, as shown below:

Step1
SELECT SOURCE SERVER

NOTE: Since this is a web site, you can copy and paste your connection string for ASPNETDB into the bottom box and get in that way.

Select-Database 
CONNECTION STRING METHOD

4. Click next and select a database. If you have provided a connection string, one will be pre-selected for you.

Step2
SELECT DATABASE

5. Click next.

Now, here is where paths may diverge a bit. If you have the ability to log onto your hosting database server via a web service, you can do it rather simple. We are going to show that way first.

 

Step3
SELECT AN OUTPUT LOCATION

6. Click on Publish to Shared Hosting Provider (where the arrow is pointing) and then click the More button.

More 
SELECT A HOSTING PROVIDER

7. Click the New Button (circled above) and then fill in the form.

Host
CREATE A HOSTING PROVIDER

8. In this instance, I have no databases, so I going to click New and create one.

StopMakingSense
CREATE A NEW DATABASE

9. Click OK, pick the database you created and then click OK. Then click finish and publish your database.

My Provider has no web service

You have finished the first five steps and find you have no web service. Here is the longer way. This time, leave the Select an Output Location as Script to file and click finish.

Publish
CONFIRMATION SCREEN

There are three things to check here.

  1. You are publishing the correct database
  2. You know where it is publishing to (you will need this to publish)
  3. You are publishing BOTH Schema and Data

If you follow the instructions above, you should only be concerned with the middle one, as you need to find the file. Now, click finish again. When it is complete, you should see a screen like this:

EndGame
COMPLETED

Publishing the Database

If you have a script, you need to publish it. You will need the server name and credentials your ISP gave you to log into the database server. You will also need a tool to do it. Since you probably have SQL Server Express 2005, you should also have the SQL Server Management Studio Express. If not, you can download from here. I will use SQL Server Management Studio (full version, not express); the only difference is my screens may look a bit different than yours. Here are the steps:

1. Open the Management Studio

2. Alter the Server name and user id and password to log into your server. The pieces you will have to change are circled below. You will also have to change authentication to SQL Server Authentication to enter user id and password.

LogIntoSqlServer

3. Select your database in the Object Explorer (upper left side of the tool) or click View >> Object Explorer if it is not showing. With an ISP, you will see a long list generally (unless they have filtered permissions properly), so select yours.

Choose-Database

4. Click on the New Query Button

New-Query

5. Click on the Open File button and find your file (alternatively you can choose either File >> Open >>. File or the keystroke Control + O).

Open-File-button

6. Click the Execute button (or press F5)

Execute

Your database is now deployed to the server.

Fixing the Website

If you developed locally, you will have the wrong connection string. Let’s fix that.

1. Open your web development tool (this can be Visual Studio, Visual Web Developer Express, Expression Web, Dreamweaver, etc.).

2. Open the web.config file

3. Find the <membership> section so you know which connection string to change (bold below):

<membership>
  <providers>
    <add
      name="AspNetSqlMembershipProvider"
      type="System.Web.Security.SqlMembershipProvider, …"
     
connectionStringName="ASPNETDB"
      enablePasswordRetrieval="false"
      enablePasswordReset="true"
      requiresQuestionAndAnswer="true"
      applicationName="/"
      requiresUniqueEmail="false"
      passwordFormat="Hashed"
      maxInvalidPasswordAttempts="5"
      minRequiredPasswordLength="7"
      minRequiredNonalphanumericCharacters="1"
      passwordAttemptWindow="10"
      passwordStrengthRegularExpression=""
    />
  </providers>
</membership>

4. Go the <connectionStrings> section and find that connection string. In this case, we are looking for ASPNETDB.

<connectionStrings>
    <add name="ASPNETDB" value="Data Source=.SQLEXPRESS;AttachDbFilename=&quot;C: somewebsiteApp_DataASPNETDB.MDF&quot;;Integrated Security=True;Connect Timeout=30;User Instance=True"/>
</connectionStrings>

5. Change the connection string to the one for your host

<connectionStrings>
    <add name="ASPNETDB" value="server={server name};database={your database name:;UID={user id};pwd={password};"/>
</connectionStrings>

You will obviously have to change {server name} to the actual server, like p3swhsql-v15.shr.phx3.secureserver.net for one of Go Daddy’s servers. But, once that is done, you should be rocking.

Hope this helps …

Peace and Grace,
Greg

Twitter: @gbworld

Follow

Get every new post delivered to your Inbox.