Thursday, December 17, 2009

Overlapping dates

Had an interesting problem a few nights ago which at first seemed like a really easy thing, but turned out to be a right pain in the face.  I figured I’d do a blog on it as it might help someone else later on.

A Simple Problem .. not !!

What I wanted to figure out was if two date ranges overlapped.  the logic of this was a lot harder to get my head around than I first expected.  As I was dealing with a range rather than static dates any of the existing DateTime functions were useless, also working with TimeSpans I find difficult.  The solution was to create a good Test case and keep playing around with the logic.

[Test(Description="Test over lapping dates")]
[TestCase("2009-12-17 13:00:00", "2009-12-17 17:00:00", "2009-12-17 13:00:00", "2009-12-17 13:00:00", true)]
[TestCase("2009-12-17 13:00:00", "2009-12-17 13:30:00", "2009-12-17 14:00:00", "2009-12-17 14:30:00", false)]
public void CompareDatesTest(string firstStartDate, string firstEndDate, string secondStartDate, string secondEndDate, bool expectedOverlap)
{
     DateTime first_start_date = DateTime.Parse(firstStartDate);
     DateTime first_end_date = DateTime.Parse(firstEndDate);
     DateTime second_start_date = DateTime.Parse(secondStartDate);
     DateTime second_end_date = DateTime.Parse(secondEndDate);
     //Compare
     Assert.IsTrue(DatesOverlap(first_start_date, first_end_date, second_start_date, second_end_date) == expectedOverlap, "booking overlap validation did not work");
}

the test case above will run two dates through my logic and return True if the first and second date rages overlap, False if they don’t.

My magic function

To work out the problem I had to convert the dates into Ticks.  This converts the date in the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001.  Using that conversion I can easily use the numerical Great-than Boolean functions…. so after much playing around with IF statements I came up with:

private bool DatesOverlap(DateTime firstStart, DateTime firstEnd, DateTime secondStart, DateTime secondEnd)
{
     return (firstEnd.Ticks >= secondStart.Ticks) && (secondEnd.Ticks >= firstStart.Ticks);
}

After doing all this I then did a quick Google to find someone had come up with the same solution.  D’oh!.

Friday, December 11, 2009

Reflecting Classes and content

Yesterday someone asked for a way to print out all the contents of a class including the values that were current assigned.  This initially seemed like an easy thing to do, but turned out to be a little more complicated that expected.

The Easy Way

First thing we need to understand about .NET classes is that they are all inherited from a base type called Object.  This base object has a handy little method called ToString(), which will return you a string representation of that object.  You would have used this dozens of times in your code.

int X = 32;
Console.WriteLine("The value of X is:” + X.ToString());

image

This returns “The value of X is:32” which is fine for simple objects like int, float, DateTime but what about our custom classes?.  If you coded up something like the following:

public class SomeObject
{
    public string Firstname { get; set; }
    public string Surname { get; set; }
}

Now you’re test code would look like this:

SomeObject someObject = new SomeObject();
someObject.Firstname = "Tiberius";
someObject.Surname = "Percinus";
Console.WriteLine("The value of someObjectis: " + someObject.ToString());

image

This returns “The value of someObject is: UnitTests.ReflectionExample.SomeObject” which is not really helpful at all.  The normal way around this is to create an override on the ToString() method which returns a more meaningful result.

    public class SomeObject
    {
        public string Firstname { get; set; }
        public string Surname { get; set; }

        /// <summary>
        /// Local implementation of ToString based on class members
        /// </summary>
        public override String ToString()
        {
            StringBuilder sbuffer = new StringBuilder();
            sbuffer.Append("{");
            sbuffer.AppendFormat("Firstname = {0}, ", this.Firstname);
            sbuffer.AppendFormat("Surname = {0}, ", this.Surname);
            sbuffer.Append(" }");
            return sbuffer.ToString();
        }
    }

With this we create a large string with all of the local values returned in a meaningful way.

image 

This returns: “The value of someObject is: {Firstname = Tiberius, Surname = Percinus,  }”.

The Fancy Way

“OK”, I was told, “But this object has only two data items what happens if I’ve got 180?”.  Which is a very valid question.  The best answer to this is to use a technique called “Reflection” which allows you to crack open a class to access its values.

    using System.Reflection;

    public class SomeObject
    {
        public string Firstname { get; set; }
        public string Surname { get; set; }
         //  ……  assume another 180 properties are here ……  //
        public string LastProperty { get; set; }

        /// <summary>
        /// Local implementation of ToString based on reflection
        /// </summary>
        public override String ToString()
        {
            StringBuilder sbuffer = new StringBuilder();
            sbuffer.Append("{");
            PropertyInfo[] properties = this.GetType().GetProperties();
            foreach (PropertyInfo prop in properties)
            {
                sbuffer.AppendFormat("{0} = {1}, ", prop.Name, prop.GetValue(this, null));
            }
            sbuffer.Append(" }");
            return sbuffer.ToString();
        }
    }

Using the foreach loop and the GetType().GetProperties() methods we get an array of all properties in the class.  Then we just have string builder join them all together.

image

This will now return: “The value of someObject is: {Firstname = Tiberius, Surname = Percinus, … and on for all the properties … , LastProperty = ,  }”.

So why not do this all the time? Well the simple reason is that reflection adds a little more load on the processor, so for the majority of cases it’s best to stick to “the easy way”, unless you have a very, very large set of properties.

Tuesday, December 8, 2009

Conditional Pre-Complication is good for what ails you.

Recently found a comments in the code base that stated "Remove on Live!" in the description.  It was perfectly valid code, but unfortunately but there was no way any developer (other than the person who wrote it in the first place) will remove the code before compiling.  The good news is that there is a solution to this problem and that’s "Conditional Pre-Compilation Symbols".  That all sounds very complicated but its really simple.  It means you can mark a section of code, so that it is placed within a specific assembly.

Simple Conditional Pre-Complication

Here is an example of a function that will appear in all environments and assemblies.

//***********************************
// Test code; remove when running on live.
//***********************************
  if (X==Y || Z==A)

{  
      int AnotherX = Convert.ToInt32(X)|
      _log.DebugFormat("AnoterX has been set to {0}", X);
  }

Pleacing this within a Conditional Pre-Compilation Symbols would look like this:

#if(DEBUG)

   //***********************************
   // Test code; remove when running on live.
   //***********************************
   if (X==Y || Z==A
   {  

      int AnotherX = Convert.ToInt32(X)|
      _log.DebugFormat("AnoterX has been set to {0}", X);
    }

#endif

This means that the code still works fine on you're local PC and Miranda, but now that we're using CC.NET to do a "Release" build, this code will not be included in the assembly.

Doing something more funky

You're not limited to just removing code, you can also directly change the code as shown below:

#if(DEBUG)

      _log.DebugFormat("This is Debug Code");

#else

      _log.DebugFormat("This is Release Code");

#endif

You are also not limited to only using the pre-configured "DEBUG" or "RELEASE" variables, you can also set your own.  To do this, open the property page for your project and select the Build tab.  Here you can see a field called "Conditional compilation symbols".  Here you can enter a value like "Design", but you should also note the Configuration currently selected as this is important. 

image

Now in your code you can do this….

  #if(Design)

      _log.DebugFormat("This is only run when Design is entered in the properties");

  #endif

You can of course add as many build configurations as you wish, e.g. “Debug”, “Test”, “Stage”, “Live” etc. and CC.NET will happy ensure that each is built in turn correctly.

Wednesday, November 25, 2009

Generics your easy road to the simple life

There have been some comments recently asking what was the best way to use Generics in C#, so here’s a short blog which sheds some light.  Generics were probably the most powerful feature to go into .Net and they allowed developers to define structures, without committing to actual data types.  That may sound very complicated but its really not that hard to wrap your head around.

Simple Generic Lists

One of the simplest examples is taken directly from an existing Framework.  Within this we have lots of Collections classes for example CompanyCollection, ContactCollection, etc. and these are explicitly created with lots of code for getting a group, array of Company or Contact items from the CompanySearch class. 

It's usually seen in this type of context:

// Get a collection of companies

CompanyCollection compCollection = CompanySearch.Browes();

string companyName = compCollection[0].CompName;  // display the first company name

Generics give you the same thing out of the box using the List<> function.

// Get a collection of companies using Generics

List<Company> compCollection = CompanySearch.Browes();

string companyName = compCollection[0].CompName;

So what's the advantage?  Well for one we don't need the CompanyCollection.cs class file which will save a developer having to write it (cut/paste or use replicator and perhaps introduce bugs).  Secondly it's been developed using core functions so it's faster than anything you could write yourself.  Also it's guaranteed to give us a stable upgrade path as .Net progresses.

The Syntax

Taking this example a little further, I hear “What’s all this <> crap in the code?”.  Well simply, this is the class you are passing into a “generic” (i.e. self defined) method.  An easy way to describe this is to think of it as a cut/paste job for the class.  Below is an extract of the CompanyCollection class with a Browse method.

using System;
using System.Collections;

namespace BusinessObjects.Companies
{
    public class CompanyCollection : CollectionBase
    {
        public CompanyColelction Browse()
        {
              CompanyCollection results = new CompanyCollection();
              … some code to find a bunch of records and put them in results …
              return results;
        }
}

If you wanted the same thing for Contacts you would probably cut/paste the code into a new file and replace every occurrence of “"CompanyCollection” with “ContactCollection”.  With Generics you would say something like this.

using System;
using System.Collections;

namespace BusinessObjects.Companies
{
    public class GenericList<T>
    {
        public GenericList<T> Browse()
        {
              GenericList<T> results = new GenericList<T>();
              … some code to find a bunch of records and put them in results …
              return results;
        }
}

Here at compile time the .Net Framework will replace the “T” above with the object value you are passing to the method.

GenericList<Company> myCompanyCollection = new GenericList<Company>();  // replace “T”
myCompanyCollection.Browse();

and

GenericList<Contact> myContactCollection = new GenericList<Contact>(); // replace “T”
myContactCollection.Browse();

Hence in the compiled DLL, you do actually get two classes “generic classes” but you only have to write (or edit, debug, etc.) one!

Thursday, November 19, 2009

Some coding tips and advice

I've been doing some refactoring code recently and want to share some tips and tricks that could help developers in future efforts.  These are just suggestions so feel free to use or ignore any of them, but keep in mind that they would make things a little easier for everyone in the long run.

Temp Files and Paths

I've seen in a few places that developers have been placing files into the C:\temp directory.  Nothing wrong with this; however did you know that .NET makes it a lot easier now?

Before:    string fullFileName = @"c:\temp\" + someFileName;
The main problem here this is that it assumes that the "c:\temp\" directory exists and if you want to change it we have to recompile the source code.

After:      string fullFileName = String.Format("{0}{1}", Path.GetTempPath(),
                                                                                 Path.GetTempFileName());
The "Path" class in .NET will gives you lots of extra options for dealing with folders and files.  The "GetTempPath" method will return the value set in the %Temp% environment variable which is default in Windows.  "GetTempFileName" will give you a random filename which can be very handy if you are creating temp files.  Another handy methods are "GetFileNameWithoutExtension" which means you can add any extension you want to a file.

Getting rid of old code

You all know how much I *hate* to leave old code hanging around, but leaving an entire classes really gets me going!  The current Framework is chock full of classes that are old, duplicated or simply in need of a serious rewrite, but we can't delete them as there is the ever present "Possibility" of breaking the old ASP code.  To address this we can use the "Obsolete" attribute to show a class should no longer be used.

    [Obsolete("This class is a deprecated! use Company from DataAccessObjects Namespace.")]
    public class Company
    {     ......     }

We can also say something like this  [Obsolete("This class is a deprecated and will throw a compile error!", true)].  This is Visual Studio will generate a compile error, but it's probably not something you'd want to do unless you really wanted to spend a long time testing.

Never..Never.. Never.. Swallow Errors!

I've seen this type of code all over every project and it's really bad practice.

     try { someCode;
           someMoreCode; }
     catch (Exception e) { }
AAGHHH!!! having a catch with nothing in it is like driving drunk with your eyes closed and having no insurance, it's just saying "If I crash, just keep going and leave all that damage for someone else".

     try { someCode;
           someMoreCode; }
     catch (Exception e) { throw new e;}
This is a little (but not much) better than the last example; least this this we acknowledge that a problem took place.  The problem with this approach is that as we're throwing a "new e" so we actually loose the strack trace and if the error is deep in the bowls of the code you'll have a hard job finding the cause.

     try { someCode;
           someMoreCode; }
     catch (Exception e) { throw;}

This will give you both the error and the stack trace, but really at this point its probably easier to just say:

         someCode;
         someMoreCode;

So what's the moral of our story?  NEVER have a try-catch block unless you actually need to do something with it, log the error, throw a different error, it’s up to you but please do something in the catch block.

Creating Projects in the right folder

A very minor thing on the list is to keep an eye on the directory when you're adding a new project to an existing solution.  By default if I was to add a new project to a solution it will go under the root folder.  There however a text box on the New Project dialogue which gives you the option to add a subdirectory name.

Friday, November 13, 2009

PSTools .. it’s great to find a good tool for once!

I was looking for a way to run scripts on a remote server and found this great set of tools that are freely available from Microsoft.

PSTools; this is basically a set of tools that let you manage a remote server as if it was a local one.  this contains a number of different commands which are all listed on the website.  I’m going to integrate the PSExec command into the project Build Scripts.

Monday, November 9, 2009

Unit Testing types for developers

Well you all know I'm a big fan of Unit Testing but did you know all the different types of tests you can run?  In this Blog I'll go over some of the examples:

A simple class to test

First we need a simple class to test so I'll use a very, very simple addition and division example called SimpleClass.  It contains two methods Add and Division both of which take two integers and return results.  Here is the basic code....

    public class SimpleClass
    {
        /// <summary>
        /// Add two values
        /// </summary>
        /// <param name="first">first value to add</param>
        /// <param name="second">second value to add</param>
        /// <returns>sum of both values</returns>
        public int Add(int first, int second)
        {
            return first + second;
        }

        /// <summary>
        /// Divide two values
        /// </summary>
        /// <param name="first">first value to divide</param>
        /// <param name="second">second value to divide</param>
        /// <returns>division of both values</returns>
        public decimal Divide(int first, int second)
        {
            return first / second;
        }
    }

Lets get down to the testing.

First off all you need a class decorated with the attribute [TestFixture] this will tell NUnit GUI to run the test from the external program.  Here you can see a basic test thats you've probably see a few times before.

    [TestFixture]
    public class TestingExamples
    {
        [Test(Description="Basic Test")]
        public void SimpleClass_Test_A_Simple_Method()
        {
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(10, 20);
            Assert.IsTrue(result == 30, "Result was not correct!");
        }
    }

It's saying pass the values 10 and 20 into the Add method and expect to get the result 30.  Simple really, and probably the type of test you'l want to write over and over again.  Howere there are other options available.

Repeat Test

        [Test(Description = "Repeat Test"), Repeat(30)]
        public void SimpleClass_Repeat_Test()
        {
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(10, 20);
            Assert.IsTrue(result == 30, "Result was not correct!");
        }

By adding the Repeat(30) attribute to the test as shown this will run the test 30 times.  In this example it's not really a very useful test but if for example you want to test load on a server or perhaps populate a number of rows in a database it can be very useful.

Multipule Value Test

        [Test(Description="Multivalue Test")]
        [TestCase(10,20,30)]
        [TestCase(1,2,3)]
        [TestCase(7,6,13)]
        public void SimpleClass_TestCase_With_Many_Inputs(int
firstInput, int secondInput, int expectedResult)
        {
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(firstInput, secondInput);
            Assert.IsTrue(result == expectedResult, "Result was not correct!");
        }

Here I'm calling the test 3 times but passing 3 different values and testing against 3 different results.  By using the [TestCase] attribute you can just add more and more values to the same test.

Expected Exception Test

        [Test(Description = "Expected Exception Test")]
        [ExpectedException(typeof(DivideByZeroException),
ExpectedMessage = "divide", MatchType = MessageMatch.Contains)]
        public void SimpleClass_TestCase_Divide_By_Zero()
        {
            SimpleClass simpleClass = new SimpleClass();
            decimal result = simpleClass.Divide(0, 0);
        }

Here is a divide test that throws a divide by Zero error.  By using the ExpectedException attribute we catch the error thrown by the .Net function and then checks it's the correct one, in this case System.DivideByZeroException.  It also checks the message text for the text "divide" and uses the MessageMatch.Contains attribute to indicate the text can exist anywhere in the error message.

Explicit

        [Test(Description = "Only Run when Explicitly chosen"), Explicit]
        public void SimpleClass_Explicit_Test_Of_Method()
        {
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(10, 20);
            Assert.IsTrue(result == 30, "Result was not correct!");
        }

This is an interesting one for us in that it will only run when you "explicitly" select it to run using TestRunner or the Nunit GUI, if not it will be ignored during test runs.  You'd use this function if you wanted to have a UI test or specific test that won't run on the Build server.

MaxTime and TimeOut

        [Test(Description = "Maxtime Test"), MaxTime(20)]
        public void  SimpleClass_Max_Time_In_Mili_Seconds()
        {
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(10, 20);
            Assert.IsTrue(result == 30, "Result was not correct!");
        }

        [Test(Description = "Timeout Test"), Timeout(20)]
        public void SimpleClass_Ensure_Long_Running_Process_Does_Not_Time_Out()
        {
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(10, 20);
            Assert.IsTrue(result == 30, "Result was not correct!");
        }

Timed tests are great for performance tests, here we specify that both tests need to run within 20 miliseconds.  What's the difference between them?  Well not a lot really so it's probably best to stick to Timeout and ignore MaxTime.

Platform

        [Test(Description = ".Net exclude test"), Platform(Exclude = "NET-2.0")]
        public void SimpleClass_Exclude_DotNet_Tests()
        {
            // Other options relevant to us
            // WinXP, Win2003Server, Vista, Net-1.1, Mono
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(10, 20);
            Assert.IsTrue(result == 30, "Result was not correct!");
        }

Probably not something we'd use very often but it may be useful in the future.  Here we specify that we this test should not be run under .Net 2.  Again the test is not important here what is important is that we can say things like only run a test on a Windows 2003 Server or only run the test on XP.

Random Values

        [Test(Description = "Random value generation test")]
        public void SimpleClass_Random_Values(
            [Values(10, 20, 30)] int firstValue,
            [Random(1, 50, 5)] int secondValue)
        {
            // run 15 times.. 3 values by 5 random numbers
            SimpleClass simpleClass = new SimpleClass();
            int result = simpleClass.Add(firstValue, secondValue);
            int testResult = firstValue + secondValue;
            Assert.IsTrue(result == testResult, "Result was not correct!");
        }

Finally sometimes you just can't be assed coming up with test data so in this case we use the [Random] attribute.  By saying [Random(1,50,5) int ]  I'm saying choose a number between 1 and 50 and run that test 5 times.  I've also added 3 additional [Values] 10,20 and 30 this means the test will run 15 times, i.e. 3 by 5

Monday, October 26, 2009

Adding an Application Icon using MonoTouch

Minor thing this time, I just wanted to add an icon to my application and wanted to see how that could be done with MonoTouch.


First off you need a PNG files, on a Mac its easy to get a PNG by just using the <Shift><Command>4 command. I happened to we watch Dr Who at the time so I dragged it across the area I wanted and bingo I get the file on my Desktop.


Now we create a folder called Resources in the project solution by right clicking the project and selecting Add / New Folder and enter the name "Resources". Next you drag the PNG file from the desktop into the folder and select "Copy" from the dialogue which will place the file into the project.


OK, now we're at the stage of linking it up. Right click the project and select "Options". In the Project Options dialogue go down to the "Build" section and select the "iPhone Application". Here you'll see the "Application Icon" option where you can select the icon from the list.



Adding Gestures to OpenGL application

In my last post I created a spinning 3DCube using MonoTouch which was a big step for me into the area of graphics. This time I want to try to control the objects rotation using gestures. Simply put, I want the default behavior to be a spinning cube, but if I press the screen the spinning should stop and I should be able to move the view manually using my finger.

Starting and stopping the animation

First need to make the View aware of the Touch events by adding the Touch Began and TouchEnded events. Edit the Cube3DView.cs class and add the event delegates.

[MonoTouch.Foundation.Export(&quot;touchesBegan:withEvent:&quot;)]

public override void TouchesBegan (MonoTouch.Foundation.NSSet touches, UIEvent evt)

{

Console.WriteLine(&quot;Click began&quot;);

StopAnimation();

}

[MonoTouch.Foundation.Export(&quot;touchesEnded:withEvent:&quot;)]

public override void TouchesEnded (MonoTouch.Foundation.NSSet touches, UIEvent evt)

{

Console.WriteLine(&quot;Click ended&quot;);

StartAnimation();

}

When doing this I noticed that there was a bug in the original code, setting the AnimationTimer to null did not stop the image rotation. So I had to invalidate the timer altogether, I’m not sure why at this stage but I’ll get back to it…

public void StopAnimation ()

{

AnimationTimer = null;

AnimationTimer.Invalidate ();

}


Changing the orientation with a finger

At first this seemed like a simple step to just change the orientation angle of the rotation but as you’ll see it’s never quite as easy at that. First off I needed to find the point on the view where we start the touch and the point where the finger was taken off the screen. This can then be passed back into the rotation function.

First I needed to add some extra code to store the X and Y coordinates. In the Code3DView.cs file we add two private variables.

PointF location; // global for drag

PointF _startLocation; // global for tourch start

Now we add come code to the TouchBegin and TouchEnd methods, we also add a new TouchMoved method. I’ve highlighted the code changes below.

[MonoTouch.Foundation.Export(&quot;touchesBegan:withEvent:&quot;)]

public override void TouchesBegan (MonoTouch.Foundation.NSSet touches, UIEvent evt)

{

var touch = (UITouch) evt.TouchesForView (this).AnyObject;

startLocation = touch.LocationInView(this);

StopAnimation ();

}


[MonoTouch.Foundation.Export(&quot;touchesMoved:withEvent:&quot;)]
public override void TouchesMoved (MonoTouch.Foundation.NSSet touches, UIEvent evt)
{
var touch = (UITouch) evt.TouchesForView (this).AnyObject;
location = this.Frame.Location;
location.X = touch.LocationInView(this).X;
location.Y = touch.LocationInView(this).Y;
}

[MonoTouch.Foundation.Export(&quot;touchesEnded:withEvent:&quot;)]
public override void TouchesEnded (MonoTouch.Foundation.NSSet touches, UIEvent evt)
{
float angle = TrigonometryHelper.Angle(startLocation.X, _startLocation.Y, _location.X, _location.Y);
GL.Rotate (angle, 1.0f, 1.0f, 1.0f);
StartAnimation ();
}

You’ll see that I had to add a new helper class to the project called TrigonometryHelper this is a simple set of code to help me calculate some of the values. Google is your friend when it comes down to this type of thing. Create a new empty class called TrigonometryHelper.cs and past in the following code.

using System;
namespace DCudeDemo
{
public static class TrigonometryHelper
{
public static float Angle(double px1, double py1, double px2, double py2)
{
// Negate X and Y values
double pxRes = px2 - px1;
double pyRes = py2 - py1;
double angle = 0.0;

// Calculate the angle
if (pxRes == 0.0)
{
if (pxRes == 0.0)
angle = 0.0;
else if (pyRes > 0.0)
angle = System.Math.PI / 2.0;
else
angle = System.Math.PI * 3.0 / 2.0;
}
else if (pyRes == 0.0)
{
if (pxRes > 0.0)
angle = 0.0;
else
angle = System.Math.PI;
}
else
{
if (pxRes < 0.0)
angle = System.Math.Atan(pyRes / pxRes) + System.Math.PI;
else if (pyRes < 0.0)
angle = System.Math.Atan(pyRes / pxRes) + (2 * System.Math.PI);
else
angle = System.Math.Atan(pyRes / pxRes);
}
// Convert to degrees
angle = angle * 180 / System.Math.PI;
return float.Parse(angle.ToString());
}
}
}

This is a class that I’m sure will begin to expand in functionality later.


Compiling and running the application now allows you to change the orientation of the cube with your finger.


















Sunday, October 25, 2009

3D Cube using MonoTouch on the iPhone


I've been trying out some OpenGL code on the iPhone which is way out of my comfort zone. It's the first time i've posted anything using MonoTouch also, but with any luck if I can continue to work in this area it may lead to some new innovations. My first project in this area would be to create a 3D cube and rotate it. Sounds simple, but finding posting and same code using MonoTouch turn out to be impossible. "How hard can it be?" I said to myself, well .. lets see....

Creating the project

MonoTouch and MonoDevelop makes this very easy indeed, just start the IDE and select File/New/Solution, select iPhone/iPhone MonoTouch Project and give it the name 3DCubeDemo.




Click Forward and then OK.


This will give you a standard project structure with a Main.cs file which is the same as the ApplicationDelegate and a MainWindow.xib file which is the InterfaceBuilder file for defining the interface.



Adding our View


First step is to create a view onto which we can apply our 3D Cube. Double Click the MainWindow.xib file which should start Interface Builder.


Drag a new view Control from the "Windows, Views & Bars" section in the Library onto the Window.



Change the View class field to "Cube3DView" and the Interface Name to Cube3DView.


Select the App Delegate and Create a new outlet called cude3DView. Then connect this to the view by dragging the link to the View called Cube3DView.




Save the file and close InterfaceBuilder.


Doing the code thing...


When you save the file in interface Builder you'll see that it automatically updates your MainWindow.xib.designer.cs file with a partial class called Cube3DView and add a property to the AppDelegate called cube3Dview. This is all fine if we just wanted to use the out of the box UIView methods but in this case we need a bit more access. best thing to do is modify the property so it returns a full Cude3DView class as opposed to the default UIView.

[MonoTouch.Foundation.Connect("cube3DView")]
private MonoTouch.UIKit.UIView cube3DView {

get {

return ((MonoTouch.UIKit.UIView)(this.GetNativeField("cube3DView")));
}

set {
this.SetNativeField("cube3DView", value);
}

}

becomes

[MonoTouch.Foundation.Connect("cube3DView")]
private Cube3DView cube3DView {

get {

return ((Cube3DView)(this.GetNativeField("cube3DView")));
}

set {
this.SetNativeField("cube3DView", value);
}

}


and
// Base type probably should be MonoTouch.UIKit.UIView or subclass

[MonoTouch.Foundation.Register("Cube3DView")]
public partial class Cube3DView {
}

becomes

// Base type probably should be MonoTouch.UIKit.UIView or subclass
[MonoTouch.Foundation.Register("Cube3DView")]
public partial class Cube3DView : MonoTouch.UIKit.UIView {
}

Note: This is a problem for the moment as once you edit the view again in InterfaceBuilder it will overwrite your changes. I'll keep looking out for better solutions using partial classes.

Creating the Model and link to OpenGL.

Create a new class file called Cube3DViewand place the following code into the file. I've bolded some of the more interesting areas;

using System;
using System.Drawing;
using MonoTouch.CoreAnimation;
using MonoTouch.CoreGraphics;
using MonoTouch.Foundation;
using MonoTouch.OpenGLES;
using MonoTouch.UIKit;
using MonoTouch.ObjCRuntime;
using OpenTK.Graphics;
using OpenTK.Graphics.ES11;
using OpenTK.Platform;
using OpenTK.Platform.iPhoneOS;

namespace DCudeDemo
{
public partial class Cube3DView : UIView {
int BackingWidth;
int BackingHeight;
iPhoneOSGraphicsContext Context;
uint ViewRenderBuffer, ViewFrameBuffer;
uint DepthRenderBuffer;
NSTimer AnimationTimer;
internal double AnimationInterval;

const bool UseDepthBuffer = false;

[Export ("layerClass")]
public static Class LayerClass ()
{
return new Class (typeof (CAEAGLLayer));
}

[Export ("initWithCoder:")]
public Cube3DView (NSCoder coder) : base (coder)
{
CAEAGLLayer eaglLayer = (CAEAGLLayer) Layer;
eaglLayer.Opaque = true;
eaglLayer.DrawableProperties = NSDictionary.FromObjectsAndKeys (
new NSObject []{NSNumber.FromBoolean(false), EAGLColorFormat.RGBA8},
new NSObject []{EAGLDrawableProperty.RetainedBacking, EAGLDrawableProperty.ColorFormat}
);
Context = (iPhoneOSGraphicsContext) ((IGraphicsContextInternal) GraphicsContext.CurrentContext).Implementation;

Context.MakeCurrent(null);
AnimationInterval = 1.0 / 60.0;
}

void DrawView ()
{
float[] cube = {
-0.5f, 0.5f, 0.5f, // vertex[0]
0.5f, 0.5f, 0.5f, // vertex[1]
0.5f, -0.5f, 0.5f, // vertex[2]
-0.5f, -0.5f, 0.5f, // vertex[3]
-0.5f, 0.5f, -0.5f, // vertex[4]
0.5f, 0.5f, -0.5f, // vertex[5]
0.5f, -0.5f, -0.5f, // vertex[6]
-0.5f, -0.5f, -0.5f, // vertex[7]
};


byte[] triangles = {
1, 0, 2, // front
3, 2, 0,
6, 4, 5, // back
4, 6, 7,
4, 7, 0, // left
7, 3, 0,
1, 2, 5, //right
2, 6, 5,
0, 1, 5, // top
0, 5, 4,
2, 3, 6, // bottom
3, 7, 6,
};

float[] cubeColors = {
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
};

Context.MakeCurrent(null);
GL.Oes.BindFramebuffer (All.FramebufferOes, ViewFrameBuffer);
GL.Viewport (0, 0, BackingWidth, BackingHeight);

GL.Enable(All.CullFace);
GL.MatrixMode (All.Projection);
GL.LoadIdentity ();
GL.Ortho (-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
GL.MatrixMode (All.Modelview);
GL.Rotate (3.0f, 0.0f, 2.0f, 1.0f);

GL.ClearColor (0.5f, 0.5f, 0.5f, 1.0f);
GL.Clear ((uint) All.ColorBufferBit);

GL.VertexPointer(3, All.Float, 0, cube);
GL.EnableClientState (All.VertexArray);
GL.ColorPointer (4, All.Float, 0, cubeColors);
GL.EnableClientState (All.ColorArray);
GL.DrawElements(All.Triangles, 36, All.UnsignedByte, triangles);

GL.Oes.BindRenderbuffer (All.RenderbufferOes, ViewRenderBuffer);
Context.EAGLContext.PresentRenderBuffer ((uint) All.RenderbufferOes);
}

public override void LayoutSubviews ()
{
Context.MakeCurrent(null);
DestroyFrameBuffer ();
CreateFrameBuffer ();
DrawView ();
}

bool CreateFrameBuffer ()
{
GL.Oes.GenFramebuffers (1, ref ViewFrameBuffer);
GL.Oes.GenRenderbuffers (1, ref ViewRenderBuffer);

GL.Oes.BindFramebuffer (All.FramebufferOes, ViewFrameBuffer);
GL.Oes.BindRenderbuffer (All.RenderbufferOes, ViewRenderBuffer);
Context.EAGLContext.RenderBufferStorage ((uint) All.RenderbufferOes, (CAEAGLLayer) Layer);
GL.Oes.FramebufferRenderbuffer (All.FramebufferOes,
All.ColorAttachment0Oes,
All.RenderbufferOes,
ViewRenderBuffer);

GL.Oes.GetRenderbufferParameter (All.RenderbufferOes, All.RenderbufferWidthOes, ref BackingWidth);
GL.Oes.GetRenderbufferParameter (All.RenderbufferOes, All.RenderbufferHeightOes, ref BackingHeight);

if (GL.Oes.CheckFramebufferStatus (All.FramebufferOes) != All.FramebufferCompleteOes) {
Console.Error.WriteLine("failed to make complete framebuffer object {0}",
GL.Oes.CheckFramebufferStatus (All.FramebufferOes));
}
return true;
}

void DestroyFrameBuffer ()
{
GL.Oes.DeleteFramebuffers (1, ref ViewFrameBuffer);
ViewFrameBuffer = 0;
GL.Oes.DeleteRenderbuffers (1, ref ViewRenderBuffer);
ViewRenderBuffer = 0;

if (DepthRenderBuffer != 0) {
GL.Oes.DeleteRenderbuffers (1, ref DepthRenderBuffer);
DepthRenderBuffer = 0;
}
}

public void StartAnimation ()
{
AnimationTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (AnimationInterval), () => DrawView ());
}

public void StopAnimation ()
{
AnimationTimer = null;
}

public void SetAnimationTimer (NSTimer timer)
{
AnimationTimer.Invalidate ();
AnimationTimer = timer;
}

public void SetAnimationInterval (double interval)
{
AnimationInterval = interval;
if (AnimationTimer != null) {
StopAnimation ();
StartAnimation ();
}
}
}
}

I can't really take all the credit for this script as it's mainly a modification of the 2D sample provided on the MonoTouch site. There were however a number of changes needed to work this into a 3D model. The "cube[]" array of floats contains all the data for the model, these are simple X, Y, Z coordinates positioned from 0,0,0 at the centre. The triangles byte array for geometry, where I get a bit fuzzy on the whole thing, check out the iPhone OpenGL article which I used as a base for my example. The other functions should be self explanatory GL.Rotate, GL.VertexPointer and GL.DrawElements are where all the data comes together.

Once you compile you'll get the error "The type or namespace 'OpenTK' could not be found" error. OpenTK is simply the Mono implementation of the OpenGL infrastructure so all you need to do is add this as a project reference. <Ctrl> Click the References folder in your solution and select "Edit References...".



Click the OpenTK reference and click OK.


Finally we need to initialize this new class correctly in the Main.cs file. Open the Main.cs file and add the following using commands at the top of the file.

using OpenTK.Platform;


using MonoTouch.OpenGLES;


Modify the Main entry point to the application so it tells the UIApplication that we will be making use of OpenGL.


static void Main (string[] args)

{

using (var c = Utilities.CreateGraphicsContext(EAGLRenderingAPI.OpenGLES1)) {

UIApplication.Main (args);

}

}


Modify the AppDelegate "FinishedLoading" method so that it initializes the animation;

public override bool FinishedLaunching (UIApplication app, NSDictionary options)

{

// If you have defined a view, add it here:

// window.AddSubview (navigationController.View);

window.MakeKeyAndVisible ();

cube3DView.AnimationInterval = 1.0 / 60.0;

cube3DView.StartAnimation();

return true;

}


Compile and run the application and you should see the following appear in the simulator:



How good is that!?!

Friday, October 2, 2009

Old Include files are a pain

Noticed an issue with migrating old ASP application to our new CruiseControl deployment model today.  That is, using of ASP include files *.inc in your project causes Visual Studio to not deploy these to the “Published” sites as it does not understand the file extension. 

image    

In the example above you can see that the Build Action is “None”.

To get around this you need to manually set the Build Action property to “Content” in Visual Studio.

image

From that point on the file will be automatically included with the deployment of the site.  This will not affect any of the new ASP.NET solutions, only the very old ASP solutions.

Tuesday, September 15, 2009

Using Selenium Tests and MasterPages

It was recently noted to me that running Selenium UnitTests can be a problem when the developer is using MasterPages and UserControls. This is due to the fact that when recording the test on one PC, the ControlID used my change depending on the server used.

A normal Selenium Test will produce code such as this :

    [TestFixture]
    public class WebTest
    {
        … code sniped as not needed for demo …

        [Test]
        public void MySeleniumTest()
        {

            selenium.Open("/somesite/default.aspx");
            selenium.Click("ctl02_ctl00_ButtonLaunch");
            selenium.WaitForPageToLoad("30000");
            selenium.Click("ctl02_ctl00_ButtonSubmit");
        }

    }

The ControlID to click is found using the code "ctl02_ctl00_ButtonLaunch"; however on another server it may be generated as  “ctl002_ctl00_ButtonLaunch” or “ctl02_ct0100_ButtonLaunch”, which would cause the test to fail.

To address this you add the following code to the test class or to a base selenium test class, if you have a number of tests running;

//******************************************************************/
//
//                  Helper Methods
//
//******************************************************************/

/// <summary>
/// Simple function to pre-append masterpage text to a control
/// </summary>
/// <param name="control">text name of the control</param>
/// <returns>control name with additional text</returns>
private string ControlName(string control)
{
    return ControlName(control, 0);
}

/// <summary>
/// Simple function to pre-append masterpage text to a control
/// </summary>
/// <param name="control">text name of the control</param>
/// <param name="iteration">number to look for</param>
/// <returns>control name with additional text</returns>

private string ControlName(string control, int iteration)
{
    int counter = 0;
    string pattern = String.Format(@"\bid=.[^ ]*{0}\b", control);   //@"id=.*?{0}"
    string reference = String.Empty; // the correct reference
    MatchCollection matches = Regex.Matches(selenium.GetHtmlSource(), pattern, RegexOptions.IgnoreCase);
    foreach (Match match in matches)
    {
        // work out the control name from the ref:master:control format
        control = match.Value.Replace("id=", "");
        if (counter >= iteration) break;
        counter++;
    }
    return control;
}

This simply uses the HTML to search for the correct ControlID using regular expressions. I’ve added an Overload in case you use the same UserControl on the same page a number of times so you can target a specific version.  If excluded it will simply return the first.

Now all you need to do is edit your test code to the following:

        [Test]
        public void MySeleniumTest()
        {

            selenium.Open("/somesite/default.aspx");
            selenium.Click(ControlName("ButtonLaunch"));
            selenium.WaitForPageToLoad("30000");
            selenium.Click(ControlName("ButtonSubmit"));
        }

Friday, September 11, 2009

Using ASP.NET Ajax controls

Here is a simple tutorial of the simplest of the Ajax functions called the “Partial Page Update”, this shows how to use the built in Visual Studio 2008 controls.  You will see from this that there is no need to write any of that old JavaScript plumbing and how simple it is to implement. 

Setting up your project

Start a new Visual Studio Project called AjaxDemo.

image

Add two text boxes to your default.aspx page called TextBox1 and TextBox2. then add a button called “Button1” with the text “Press Me”, the code is shown below:

<form id="form1" runat="server">
<div>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><p />
    <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><p />
    <asp:Button ID="Button1" runat="server" Text="Press Me" />
</div>
</form>

Next on the code behind (default.aspx.cs) add the following code to the Page_Load function which populates the text boxes with the current time.

protected void Page_Load(object sender, EventArgs e)
{
    TextBox1.Text = DateTime.Now.ToLongTimeString();
    TextBox2.Text = DateTime.Now.ToLongTimeString();
}

Run the application and it should look like this:

image

Pressing the button will cause a refresh of the page and both fields to be updated.

Implementing the Partial Page Update Ajax commands

To allow for Ajax on your page you need to add a ScriptManager Control.  this should be placed on the page before any other controls are rendered.  I find putting in on the Master Page works best, that way you don’t have to worry about it later.

1) Drag the ScriptManager from the tools in Visual Studio onto the design or code surface.

image

2) Next you need to add an UpdatePanel around the controls you want to take part in the partial update.  In this case I’m going to wrap TextBox2 and Button1.  Again simply drag the item from the tool box to your design or code surface.  move your controls between the UpdatePanel tags and add a <ContentTemplate> tag around the controls.

image

The code should look something like this:

<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><p />
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
    <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><p />
    <asp:Button ID="Button1" runat="server" Text="Press Me" />
    </ContentTemplate>
    </asp:UpdatePanel>
</div>
</form>

Now press Play on your solution to see it in action.

 image

Pressing the button now will cause the second textbox to become updated but not the first as it is outside the update panel.  Also there will be no full Post Back event for the page refresh.

Friday, August 14, 2009

New version of Google Search Engine

In case anyone missed this news, Google are releasing a new version of their search engine to the public http://www2.sandbox.google.com/.  I did not see any real difference with the existing one but maybe you will.

Apparently: “For the last several months, a large team of Googlers has been working on a secret project: a next-generation architecture for Google’s web search. It’s the first step in a process that will let us push the envelope on size, indexing speed, accuracy, comprehensiveness and other dimensions. The new infrastructure sits “under the hood” of Google’s search engine, which means that most users won’t notice a difference in search results. But web developers and power searchers might notice a few differences, so we’re opening up a web developer preview to collect feedback.”

http://googlewebmastercentral.blogspot.com/2009/08/help-test-some-next-generation.html

Tuesday, August 11, 2009

Encrypting your web.config file

Ever see a connection string in a configuration file with the Username and Password available to the world?  I know I have, far to many time to be good.  But; did you know that you can quite easily Encrypt and Decrypt this on-the-fly using built in .Net functionality?!?!  Well you can and it’s very easy to do too.

Setting up your project

First create a simple ASP.NET web application in Visual Studio 2008.

  • Edit the current web.config file and add a valid connection string:

<connectionStrings>
  <add name="MyAppConnection" connectionString="Server=dubwsdev001;Database=DevDatabase;Integrated Security=false;User Id=xxxxx;PWD=xxxxxxxxx;" />
</connectionStrings>

  • Edit the default.aspx file

Add two labels and two button to your form or just copy/paste the following code:

<form id="form1" runat="server">
<div>  
    <asp:Label ID="lblStatus" runat="server"></asp:Label>
    <br />
    <asp:Label ID="lblConnection" runat="server"></asp:Label>
    <br />

    <asp:Button ID="btnEncrypt" runat="server" onclick="EncryptConfig" Text="Encrypt" />
        &nbsp;&nbsp;
    <asp:Button ID="btnDecrypt" runat="server" Text="Decrypt" onclick="DecryptConfig" />

    <br />

</div>
</form>

It should look something like the following:

image

  • Edit the code behind “default.aspx.cs” file to populate the lblConnection text label with the connection string we have in the web.config file.  Do this by adding the following code:

using System.Web.Configuration;

protected void Page_Load(object sender, EventArgs e)
{
     string strConnection= WebConfigurationManager.ConnectionStrings["MyAppConnection"].ConnectionString;
     lblConnection.Text = strConnection;
}

protected void EncryptConfig(object sender, EventArgs e)
{

}

protected void DecryptConfig(object sender, EventArgs e)
{

}

Starting the application should result in the following:

image

Encrypt / Decrypt on-the-fly

To do this we need 3 private methods .. one to Encrypt the files, one to decrypt the file and one to see if encryption is already in place (i.e. you don’t want to encrypt an already encrypted section).  So we add these to the button methods in the code behind.

protected void EncryptConfig(object sender, EventArgs e)
{
    if (IsEncrypted(Request.ApplicationPath))
        return;   // alredy done so ignore

   EncryptConnString(Request.ApplicationPath);
    btnDecrypt.Enabled = true;
    btnEncrypt.Enabled = false;
    lblStatus.Text = "The connection string is currently is encrypted ";
    lblConnection.Text = WebConfigurationManager.ConnectionStrings["MyAppConnection"].ConnectionString;
}

protected void DecryptConfig(object sender, EventArgs e)
{
    if (!IsEncrypted(Request.ApplicationPath))
        return;   // alredy decrypted so ignore

    DecryptConnString(Request.ApplicationPath);
    btnEncrypt.Enabled = true;
    btnDecrypt.Enabled = false;
    lblStatus.Text = "The connection string is currently is not encrypted!";
    lblConnection.Text = WebConfigurationManager.ConnectionStrings["MyAppConnection"].ConnectionString;

}

The IsEncrypted, EncryptConnnString and DecryptConString are our methods that do all the work.  Here I’ve implemented them in the page, but there is no reason why it can’t be done in a helper class or within a common framework.

IsEncrypted

Probably the simplest method to understand the “var config” simply opens the configuration file that is passed from the button press.  The path is noted in the ASP.NET request object in a property called ApplicationPath.

private static bool IsEncrypted(string strPath)
{
    var config = WebConfigurationManager.OpenWebConfiguration(strPath);
    return config.GetSection("connectionStrings").SectionInformation.IsProtected;
}

If the of the Section “connectionStrings” has been encrypted a property called IsProtected is set to true.  remember this is all automatic, you don’t have to write any code to check this!

EncryptConnString and DecryptConnString

Here is were it gets a little more complicated, as above the OpenWebConfiguration method will return you an instance of the current web.config file. the commend “section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider")” however; actually does all the work.  The provider is already built into the .NET and will give you 128bit encryption on whatever section you have selected.  In this case it’s the “ConnectionStrings” area.

private static void EncryptConnString(string strPath)
{
    var config = WebConfigurationManager.OpenWebConfiguration(strPath);
    var section = config.GetSection("connectionStrings");
    if (section.SectionInformation.IsProtected) return;
            section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
    config.Save();
}

DecryptConnString is the same as EncryptConnString but calls the UnprotectSection method.

private static void DecryptConnString(string strPath)
{
    var config = WebConfigurationManager.OpenWebConfiguration(strPath);
    var section = config.GetSection("connectionStrings");
    if (!section.SectionInformation.IsProtected) return;
    section.SectionInformation.UnprotectSection();
    config.Save();
}

Run your web application again and press the “Encrypt” button.

image

Notice that the label now says the connection section has been Encrypted; however the connection string is still read correctly!  Now if you open the web.config file using Visual Studio you’ll see the following:

image

Lets see a hacker get past that baby!!

Press “Decrypt” on your application and the web.config will return to :

image

Best of all there is no code to write!!!!!!!

Thursday, August 6, 2009

Using BING Maps in your ASP.NET Applications

I was using the Google Maps API last week on a project and realised that the who JavaScript thing was a bit of a pain to debug.  Although it works fine, it’s fast and is easy to use it still gave me pause for thought.  so looking around for an alternative I decided to give the Microsoft offing a quick once around the block.

Installation

First off you’ll need Visual Studio 2008 to be installed and to down load the Windows Live Tools for Microsoft Visual Studio which contains all the DLLs you’ll need.  It also comes with other bit and pieces, but this post only relates to the mapping element.

After saving the file to your local drive execute the WindowsLiveTools.msi.

image

Click next and follow all the onscreen prompts.

Adding a Map to your site

Microsoft have made it very easy to adding a map to your website, once the software has been installed you get a set of new tools in Visual Studio.

Open up any ASPX Page in design view and select the “Map” icon within the Virtual Earth group on your tool bar:

image

Drag this icon to your' page.

image

Next you need to select a ScriptManager from within the “Ajax Extensions” group and drag this to your page too.

Press Play to debug your application and make sure it’s working.

image

By default you open up over the North American continent which is not the best for an Irish company.  So to fix this we have to go into the page code behind.  Open up the default.aspx.cs file and add the following code:

protected void Page_Load(object sender, EventArgs e)
{
    Map1.Center.Latitude = 53.33306;
    Map1.Center.Longitude= -6.24889;
}

Press Play again and you should see the following:

image

Doing Directions

One of the key advantages to mapping is the ability to get directions from one place to another.  Microsoft have made this really, really easy by just creating a generic list of string with valid addresses.

Create two text boxes on the page with a submit button.

 image

In the code behind add the following to the on click event for the button.

using Microsoft.Live.ServerControls.VE;

protected void btnRoute_Click(object sender, EventArgs e)
    {
        RouteOptions options = new RouteOptions();
        options.SetBestMapView = true;  // will zoom into the route
        List<string> address = new List<string>();
        address.Add(tbxFrom.Text);
        address.Add(tbxTo.Text);
        Map1.GetDirections(address, options);
    }
}

Press play on the application; type the following into the fields and press the “Route” button:

From: East Point Business Park, Dublin, Ireland
To:     O’Connoll Street, Dublin, Ireland

image

Here is the result….  simple and easy…

Tuesday, July 7, 2009

Generating SQL Diagrams using MS Visio 2003

You can build a set of database diagrams using Visio 2003 SP1.  It’s not the best solution but it does work to some extent.  Like all reverse engineering tools it assumes that you have implement some form of relationship mapping and constraints in within the database.

1) Open Visio and Select “Database/Database Model Diagram”

image

2) From the menu choose Database / Reverse Engineer

image

3) Set up your connection to the database

image

choose SQL Server / click New.

image

Select System Data Source and click Next.

image

Select SQL Server and click Next and Finish

image

Enter a meaningful name and enter the DB Server you want to work against (in this case Dubwsdev001), click Next and Next again to use Network Authentication.

image

Select your database and click Next and Finish and then OK.  Click Next at the Reverse Engineering Wizard dialogue.

image

Select the times you want to reverse engineer and click Next.

image

Select the Tables/Views you want to work with and click Finish.

image

You should now see the table in your Visio page. 

Remember that this reflects the table structure exactly, so if there are lots of columns, you’ll see lots of columns.  After a few hours playing around you’ll probably find doing it by hand is easier.

Alternative Solution

You can also use SQL 2005 or 2008 Management Studio to create database diagrams, however we don’t have a copy of that here.