Thursday, February 23, 2012

What is Object Oriented programming?

Object Oriented programming started back when C++ came out.

The three tenents of Object Oriented programming are:

Inheritance
Encapsualtion
Polymorphism

Let's tackle these one at a time....

Inheritance

Let's say you have a class called Vehicle and defined as:

public class Vehicle
{
   protected int wheels;
   protected int seats;
   protected int speed;
   protected float fuel;

   public Vehicle( int Wheels, int Seats, int Speed, float Fuel )
   {
      wheels = Wheels;
      seats = Seats;
      speed = Speed;
     fuel = Fuel;
   }
   public virtual void Drive();
}

Now let's say that you need a class called Car and another called Motorcycle:

public class Car : Vehicle
{
   public Car( int Seats,  int Speed, float Fuel )
   {
      base.wheels = 4;
      base.seats = Seats;
      base.speed = Speed;
      base.fuel = Fuel;
   }
 
  public virtual void Drive()
  {
     // Drive the car
  }
}

public class Motorcycle : Vehicle
{
   public Motorcycle( int Seats, int Speed, float Fuel )
   {
       base.wheels = 2;
       base.seats = Seats;
       base.speed = Speed;
       base.fuel = Fuel;
   }

   public virtual void Drive()
   {
      // Drive the Motorcycle
   }
}

Notice that the Car and the Motorcycle have no local storage, only the Vehicle has data members.

Also notice the : Vehicle after Car and Motorcycle this indicates that Car and Motorcycle inherit from Vehicle.

Encapsualation

Now let's say that you create a Radio class for entertainment.

public class Radio
{
   private float station;
   private float volume;
   private bool on;

   public void Tune( float Station )
   {
      station = Station;
   }

   public void VolumeUp( float amount )
   {
     volume += amount;
   }

   public void VolumeDown( float amount )
   {
      volume -= amount;
   }

   public void ToggleOnOff()
   {
      on = !on;
   }
}

Now you'd like to add the radio to the Car but you don't think it belongs in Vehicle.

public class Car
{
    private Radio radio = new Radio();
   
    public void Tune( float Station )
    {
        radio.Tune( Station );
    }

    public void VolumeUp( float amount )
    {
       radio.VolumeUp( amount );
    }

    public void RadioOnOff()
    {
       radio.ToggleOnOff();
    }

    // the rest of Car is as before
}

You could say that the Radio is encapsualated within the Car.

Polymorphism

Let's say that you've created a Shape class as:

public class Shape
{
    public virtual float Area();
    public virtual void Draw();
}

Now you want to create some specific shapes:

public class Circle : Shape
{
    private int diameter;

    public Circle( int Diameter )
    {
       diameter = Diameter;
    }

    public virtual float Area()
    {
       // compute the Area of a circle
      return 0.0; // temp value until we actually compute the area
    }

    public virtual void Draw()
    {
       // draw the Circle
    }
}

public class Square : Shape
{
   int side;

   public Square( int Side )
   {
      side = Side;
   }

   public virtual float Area()
   {
      return side * side;
   }

   public virtual void Draw()
   {
      // draw the Square
   }
}

Next you want to randomly create either a Circle or a Square:

public class Factory
{
    public Shape Create()
    {
        Shape shape = new Shape();
        Random r = new Random( DateTime.Now.Second );
       
        switch( r.Next( 0, 1 )
        {
           case 0:
              shape = new Circle( r.Next( 10 ) );
              break;
           case 1:
              shape = new Square( r.Next( 10 ) );
              break;
        }

        return shape;
    }
}

Next let's say that you want to create a loop that draw circles and squares without knowing which one you have:
public DrawShapes()
{
  Factory f = new Factory();
  for( int i = 0; i < 10; ++i )
  {
     Shape s = f.Create();
     s.Draw();
  }
}

What you just saw was an example of Polymorphism.

Now that you understand the basics of Object Oriented programming, how do you go about designing your own classes?

Classes are generally nouns or things. Notice our example classes were Vehicle, Car, Motorcyle, Shape, Circle and Square.
Data within classes are generally either private or protected.
Methods within Classes are generally verbs or actions. Notice that our methods were Drive, Area, Draw, etc.
Methods are generally public but if you need a private helper method that's fine too.

And that's about all you need to know about Object Oriented programming.

Tuesday, February 21, 2012

What is this thing called C#?

C# is a computer programming language based on C and C++. If you've ever learned either of those languages C# will fit like a glove.

C# has all the operators of C and C++.

C# does away with the header files used in C++.

Like C and C++ every line of code in C# is terminated with a semicolon.

A simple variable declaration looks like:

string aString = "some string";

A simple test looks like:

if( aString == "some string" )
{
   // do something usefull
}

A for loop looks like:

for (int i = 0; i <= 10; ++i )
{
   // do something usefull
}

If you have a collection of objects, like:

List<string> aList = new List<string>();

You can use a for each loop:

for each( string str in aList )
{
   // do something with str
}

If you have a loop of indeterminate length, you can do something like:

bool flag = false;
while( flag == false )
{
  // do something usefull

 // when done simply:
  flag = true;
}

If you have a loop that needs to always go through a least 1 iteration, you can do something like:

bool flag = false;
do while ( flag == false )
{
   // do somethig usefull

   // when done simply
   flag = true;
}

To define a namespace, you simply do this:

namespace my.nameSpace
{
   // whatever you want in that namespace
}

To define a class, you simply do this:

public class myClass
{
    // these are the class members
    private int anInt;
    private string aString;

    public myClass ( int i, string s )  // this is the class constructor, it initilizes the class members
    {
       anInt = i;
       aString = s;
    }

    public anAction()
    {
       // perform an action on the class members
    }

    public anotherAction()
   {
       // perform another action on the class members
   }
}

To use your newly defined class, you simply

using my.nameSpace;

myClass _myClass = new myClass( 1, "some string" );

_myClass.anAction();
_myClass.anotherAction();

Of course the language of C# is not hard to learn and remember, the .Net framework is the challenging part of this equation. Your best on-line resource for the .Net framework is: http://msdn.microsoft.com/en-us/library

Saturday, February 11, 2012

How to create a MVC 3 web site

To create a MVC application, you need to understand three things:
1) The M in MVC stands for Model which is nothing more than a class within the Models namespace.
2) The V in MVC stands for View which is the web page but it uses a different syntax call Razor
which just means that you'll use a @ symbol at the front of the interesting parts.
3) The C in MVC stands for Controller which is in the Controllers namespace and this replaces the code behind file in ASP.Net.

Step 1: Open Visual Studio 2010 (which is the only version that supports MVC 3).
You'll need to install some Essential Software:
WebPI available at http://microsoft.com/web/downloads and click the download link. Download and run the installer. The name is a little confusing: this is the installer for the WebPI. The download is a regular Windows installer, which installs the WebPI tool. You'll use this tool to download and istall web application components.

The WebPI will start automatically, and you will see the selection window.

There are thrre categories aross the top of the screen. The components we are interested in are:

Visual Studio 2010 SP1,
ASP.NET MVC 3 Tools Update,
SQL Server Express 2008 R2 (this one is optional since our application doesn't need a database).

You will need at a minimum Windows XP Professional because IIS ships with only that version of Windows-XP. IIS ships with Windows-Vista and Windows-7 as well.
                                                                                                                                                                                                                                      
Step 2: Create a new ASP.NET MVC 3 Web Appliction and call it HelloWorld_MVC
Step 3: Select a Empty project template and select the Razor View Engine.
Step 4: Create some special folders under your project: Content, Controllers, and Models
Step 5: Right click on the Models folder and add a new Class called HelloWorldData.

This is what your HelloWorldData class should look like:

using System;
namespace HelloWorld_MVC.Models
{
  public class HelloWorldData
  {
    public Name { get; set; }
    public Greeting { get; set; }
  }
}

Step 6: Compile your project. This is very important because without compiling your project we won't be able to complete a future step.
Step 7: Right click on the Controllers folder and add a new Controller class called
HelloWorldController.

This is what your HelloWorldController class should look like:

using System;
using System.Web;
using System.Web.Mvc;
using HellowWorld_MVC.Models;
namespace HelloWorld_MVC.Controllers
{
  public class HelloWorldController
  {
    public HelloWorldController()
    {
    }
    public ActionResult HelloWorld_MVC()
    {
       HelloWorldData data = new HelloWorldData();
       return View( data );
    }
  }
}

Step 8: Right-Click on View and select Add View from the pop-up menu.
Step 9: The name is your method name by default, so we'll acept that.
Step 10: Check the box for Create a strongly typed view and select the HelloWorldData from the
dropdown list.
Step 11: Uncheck the Use a layout or master page checkbox.

Your web page should look something like:

@model HelloWorld_MVC.Models.HelloWorldData
@{
   ViewBag.Title = "Hello World MVC";
}
<h2>Hello World MVC</h2>
<div class="body">
@using( Html.BeginForm())
{
@Html.EditorForModel()
@Html.ActionLink( "Get Greeting", "HelloWorld_MVC", "HelloWorld" )
}
</div>

Step 11: This step is optional, but for instruction reasons, strongly recommended. Try running your site now and try clicking on the Get Greeting link. What happens? Don't worry right now, we're not done with our controller.
Step 12: Modify your controller as follows:

using System;
using System.Text;
using System.Web;
using System.Web.Mvc;
using HellowWorld_MVC.Models;
namespace HelloWorld_MVC.Controllers
{
  public class HelloWorldController
  {
    public HelloWorldController()
    {
    }
    [HttpGet]
    public ActionResult HelloWorld_MVC()
    {
       HelloWorldData data = new HelloWorldData();
       return View( data );
    }
    [HttpPost]
    public ActionResult HelloWorld_MVC( HelloWorldData data )
    {
      StringBuilder sb = new StringBuilder();
      sb.Append( "Hello " );
      if( data.Name.Length != 0 )
        sb.Append( data.Name );
      else
        sb.Append( "World" );
      data.Greeting = sb.ToString();
      return View( data );
    }
  }
}
Things to take note of:
1) We added an using statement: using System.Text;
2) We added a descriptor to our existing HelloWorld_MVC() function: [HttpGet]
3) We added a new HelloWorld_MVC function that takes a HelloWorldData parameter and gave it the [HttpPost] descriptor.

Step 13: Right-click on the View in the new method in your controller and select Go To View from the pop-up menu. if your previous View comes up, then that's great. If not, modify that View parameter list to include as the first parameter: "HelloWorld_MVC" as in View( "HelloWorld_MVC", data );

Run your project again, and now the Get Greeting link will work as expected.

Congradulations, you've sucessfully created your first ASP.Net MVC 3 site!

Friday, February 10, 2012

How to create an ASP.Net web site

Step 1: Open Visual Studio
Step 2: Create a new empty web forms project, name it: HelloWorld_Web
Step 3: Add a new Web Form to the HelloWorld_Web project, named Default.aspx

At this point, you should have a file that looks like:

<form id="form1" runat="server">
<div>
</div>
</form>

Step 5: Switch over to Design mode (look at the bottom of your web page file)
Step 6: Add a Label to the page, set it's text property to "What's Your Name"
Step 7: Add a TextBox to the page, set it's Name property to txtName
Step 8: Add a LinkButton to the page, set it's Name property to lnkGetGreeting
Step 9: While on the property page for the LinkButton, go to the Events tab and double-click in the Click field. This will open up the code behind file and place an event handler in there. This is what the event handler code should look like:


void lnkGetGreeting_Click( object sender, EventArgs args )
{
  StringBuilder sb = new StringBuilder();

  sb.Append( "Hello " );

  if( txtName.Text.Length != 0 )

    sb.Append( txtName.Text )

  else

    sb.Append( "World" )


  lblGreeting.Text = sb.ToString();

}


Step 10: Go back to Default.aspx. Add a Label to the page, set it's Name proerty to lblGreeting.

Run your page, click the GetGreeting link without entering a name, you should see "Hello World" appear in the lblGreeting Label. Next, enter your name in the first text field and click on the GetGreeting link again, you should see "Hello <your name>" this time.

Thursday, February 9, 2012

How to create a simple WinForms Project?

Step 1: Start up Visual Studio.
Step 2: Create a new Windows Forms project called HelloWorld.
Step 3: Drag a Label control onto the Form and set it's Text property to "What's Your Name:'.
Step 4: Drag a TextBox control onto the Form and name it txtName.
Step 5: Drag a Label control onto the form, clear it's Text property and name lblGreeting.
Step 6: Drag a Button control onto the form and name it btnExit.
Step 7: Drag a Button control onto the form and name it btnGreeting.
Step 8: Right click away from the Form and select View Code from the pop-up menu.

When you first created the Windows Forms project, Visual Studio started you off with a blank form called Form1 and created this program.cs file:

using System;
using System.Windows.Forms;
 
namespace HelloWorld
{
  static class Program
  {
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault( false );
      Application.Run( new Form1() );
    }
  }
}
When you selected View Code from the pop-up menu you got something like this:

using System;
using System.Text;
using System.Windows.Forms;
 
namespace HelloWorld
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    } 
  }
}
Notice the using System.Text; line at the top of the form1.cs file, that is the namespace that includes the StringBuilder class that we are using.

With just that much code, if you run the form, it will resize, minimize, and close with the close button, but the btnExit and btnGreeting buttons will accomplish nothing yet.

To make the btnExit accomplish what it should be doing, add this to your Form1 class

    private void btnExit_Click( object sender, EventArgs e )
    {
      Application.Exit();
    }

To make the btnGreeting accomplish what it should be doing, add this to your Form1 class:

    private void btnGreeting_Click( object sender, EventArgs e )
    {
      StringBuilder sb = new StringBuilder();
 
      sb.Append( "Hello " );
 
      if ( txtName.Text.Length != 0 )
        sb.Append( txtName.Text );
      else
        sb.Append( "World" );
 
      lblGreeting.Text = sb.ToString();
    }

Now you can run the form again.

Try hitting the Get Greeting button without entering anything in the Text Box.

You should see that the lblGreeting was set to "Hello World".

Try putting your name into the Text Box and then hit the Get Greeting button again.

This time you should see "Hello <your name>"

Now, let's talk about what the btnGreeting_Click method was actually doing:

Since we are building a two part string, we used a StringBuilder class and named it sb. If we had left it at that we would have had a null object since all classes are objects. So that's why sb = new StringBuilder();

The next thing we do is sb.Append( "Hello " ); This appends the word "Hello" followed by a space to our empty sb.

What comes next is a test on the length of the string entered into the Text Box.

if( txtName.Text.Lenght != 0 )

If this condition is true, we append the txtName.Text onto our sb, with
sb.Append( txtName.Text);

If this condition is false, we append "World" onto our sb, with sb.Append( "World" );

Finally, we set the lblGreeting's Text property to the contents of our sb, with
lblGreeting.Text = sb.ToString();

Now we'll talk a little about the btnExit_Click method:

This event handler only has one thing to do, cause the application to exit. To accomplish this task, we use the Application class that is part of the Form class that our Form1 class inhereted from. Application.Exit();

There is only one more addition to make to make our form's title bar say "Hello World" instead of "Form1":

In the Form1 constructor, public Form1() after the call to InitializeComponent() add this line:
Text = "Hello World";

Congradulations, you've now created your first Windows Forms project!

But what was that program.cs file doing? In every Windows Forms project there has to be a starting place, and that starting place is a static method called Main in a class called Program. Now the class called Program is enclosed within a namespace called  HelloWorld.

Up above the namespace and class we have two necessary using statements;
using System;
using System.Windows.Forms;

These pull in the namespaces needed by our HelloWorld project.

The next two lines just set up some default actions on the Appliction class. It's the third line that very important for our purposes:
Application.Run( new Form1() );

When we say new Form1() we are getting a new instance of the class Form1. So this third line is telling the Appliction to Run a new Form1(); Which calls the constructor Form1() which calls InitializeCompentent(); which puts all of our controls on the form.

And now you understand how a Windows Forms project gets started.

Monday, February 6, 2012

Implementing HTTP File Upload with ASP.NET MVC


Implementing HTTP File Upload with ASP.NET MVC including Tests and Mocks

A number of folks have asked me how to "implement the ASP.NET File Upload Control" except using ASP.NET MVC. This is a really interesting question for a number of reasons and a great opportunity to explore some fundamentals.

First, ASP.NET MVC is different since we don't get to use ASP.NET Server Controls as we're used to them. There's no "server controls" in the way that we're used to them.

Second, it'd be important to write Unit Tests for something like File Upload, and since ASP.NET MVC tries to be Unit Test friendly, it's an interesting problem to do tests. Why is it interesting? Well, ASP.NET MVC sits on top of ASP.NET. That means ASP.NET MVC didn't do any special work for File Upload support. It uses whatever stuff is built into ASP.NET itself. This may or not be helpful or interesting or even easy to test.

It seems then, that this is a good exercise in understanding a number of things:
  • HTTP and How File Upload works via HTTP
  • What ASP.NET offers for to catch File Uploads
  • How to Mock things that aren't really Mock Friendly
  • And ultimately, How to do File Upload with ASP.NET MVC
Here we go.

HTTP and How File Upload works via HTTP

It's always better, for me, to understand WHY and HOW something is happening. If you say "just because" or "whatever, you just add that, and it works" then I think that's sad. For some reason while many folks understand FORM POSTs and generally how form data is passed up to the server, when a file is transferred many just conclude it's magic.

Why do we have to add enctype="multipart/form=data" on our forms that include file uploads? Because the form will now be POSTed in multiple parts.
If you have a form like this:
1
2
3
4
5
6
7
<form action="/home/uploadfiles" method="post" enctype="multipart/form-data">
    <label for="file">Filename:</label>
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" value="Submit" />
</form>
The resulting Form POST will look like this (slightly simplified):
POST /home/uploadfiles HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------7d81b516112482
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 324

-----------------------------7d81b516112482
Content-Disposition: form-data; name="file"; filename="\\SERVER\Users\Scott\Documents\test.txt"
Content-Type: text/plain

foo
-----------------------------7d81b516112482
Content-Disposition: form-data; name="submit"

Submit
-----------------------------7d81b516112482--
Notice a few things about this POST. First, notice the content-type and boundary="" and how the boundary is used later, as exactly that, a boundary between the multiple parts. See how the first part shows that I uploaded a single file, of type text/plain. You can interpolate from this how you'd expect multiple files to show up if they were all POSTed at once.

And of course, look at how different this would look if it were just a basic form POST without the enctype="multipart/form=data" included:
 
POST /home/uploadfiles HTTP/1.1
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 13

submit=Submit

See how the content type is different? This is a regular, typical form POST. Perhaps atypical in that it includes only a Submit button!

The point is, when folks add a ASP.NET FileUpload Control to their designer, it's useful to remember that you're buying into an abstraction over something. In this case, you're using a control that promises to hide the whole multipart MIME way of looking at things, and that's totally cool.
Back To Basics Tip
Know what your library is hiding from you and why you chose it.
As an aside, if you looked at an email of yours with multiple attached files, it would look VERY similar to the body of the first HTTP message as multipart MIME encoding is found everywhere, as is common with most good ideas.

What ASP.NET offers for to catch File Uploads

The FileUpload control is just a control that sits on top of a bunch of support for FileUploads in ASP.NET, starting with the classes Request.Files and HttpPostedFile. Those are the things that actually do the hold on to the parsed Files from an HTTP Request. You can use them to get a hold of a stream (a bunch of bytes in memory that are the file) or just save the file.

Since we can't use ASP.NET Server Controls in ASP.NET MVC, we'll use these classes instead. Here's how you usually grab all the files from an upload and save them:
1
2
3
4
5
6
7
8
9
10
foreach (string file in Request.Files)
{
   HttpPostedFile hpf = Request.Files[file] as HttpPostedFile;
   if (hpf.ContentLength == 0)
      continue;
   string savedFileName = Path.Combine(
      AppDomain.CurrentDomain.BaseDirectory,
      Path.GetFileName(hpf.FileName));
   hpf.SaveAs(savedFileName);
}
Of course, you might want to change the directory and filename, maybe check the mimeType to allow only certain kinds of files, or check the length to limit your uploads, but this is the general idea.

Note that Request.Files has been around since 1.x and isn't a strongly typed collection of anything, so the GetEnumerator() of .Files that we're using in the foreach returns strings that are then used as keys into the Files[] indexer. It's a little wonky as it's old.

However, don't let me get ahead of myself, let's write the tests first!

How to Mock things that aren't really Mock Friendly

After creating a new ASP.NET MVC Project and making sure to select a test framework, I'll drop into a Controller Test and make a new TestMethod that kind of looks like I expect my method to be used.
?
1
2
3
4
5
6
7
8
9
10
11
[TestMethod]
public void FakeUploadFiles()
{
   HomeController controller = new HomeController();
   ViewResult result = controller.UploadFiles() as ViewResult;
   var uploadedResult = result.ViewData.Model as List<ViewDataUploadFilesResult>;
   Assert.AreEqual(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "foo.doc"), uploadedResult[0].Name);
   Assert.AreEqual(8192, uploadedResult[0].Length);
}
This is incomplete, though, as I'm writing the tests before I the implementation exists. I need to think about how this should be implemented, and as I learn what should be mocked, I need to go back and forth between the tests and the implementation.

If we tried to compile this test, it won't, until I add a few types and methods. Once it actually compiles, but before I write the method itself, I'll want to see it FAIL. If you get a test to PASS on the first try, you don't really know yet if it CAN fail. Making it fail first proves that it's broken. Then you get to fix it.
Back To Basics Tip
Remember, in TDD, if it ain't broke, you don't get to fix it.
image
There's a bit of a chicken and the egg because it's unclear what will need to be mocked out until I start the implementation. However, this draft method above generally says what I want to do. I want to my controller to have a method called UploadFiles() that will grab the uploaded files from Request.Files, save them, then put a type in the ViewData saying which files were saved and how large they were.

Ok, take a breath. The following code may look freaky, but it's really cool actually. You can use any Mock Framework you like, but I like Moq for it's fluency.

We're having to "mock" things because we need to lie to our controller, who's expecting an HTTP Post, remember? It's going to go and spin through Request.Files and try to save each file. Since we want to test this without the web server or web browser, we'll want to tell the Moq framework about our expectations.
Back To Basics Tip
Be careful to mock context and assert outputs but don't mock away the whole test!
I've commented the code to explain...
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[TestMethod]
public void FakeUploadFiles()
{
   //We'll need mocks (fake) of Context, Request and a fake PostedFile
   var request = new Mock<HttpRequestBase>();
   var context = new Mock<HttpContextBase>();
   var postedfile = new Mock<HttpPostedFileBase>();
   //Someone is going to ask for Request.File and we'll need a mock (fake) of that.
   var postedfilesKeyCollection = new Mock<HttpFileCollectionBase>();
   var fakeFileKeys = new List<string>() { "file" };
   //OK, Mock Framework! Expect if someone asks for .Request, you should return the Mock!
   context.Expect(ctx => ctx.Request).Returns(request.Object);
   //OK, Mock Framework! Expect if someone asks for .Files, you should return the Mock with fake keys!
   request.Expect(req => req.Files).Returns(postedfilesKeyCollection.Object);
    
   //OK, Mock Framework! Expect if someone starts foreach'ing their way over .Files, give them the fake strings instead!
   postedfilesKeyCollection.Expect(keys => keys.GetEnumerator()).Returns(fakeFileKeys.GetEnumerator());
   //OK, Mock Framework! Expect if someone asks for file you give them the fake!
   postedfilesKeyCollection.Expect(keys => keys["file"]).Returns(postedfile.Object);
   //OK, Mock Framework! Give back these values when asked, and I will want to Verify that these things happened
   postedfile.Expect(f => f.ContentLength).Returns(8192).Verifiable();
   postedfile.Expect(f => f.FileName).Returns("foo.doc").Verifiable();
   //OK, Mock Framework! Someone is going to call SaveAs, but only once!
   postedfile.Expect(f => f.SaveAs(It.IsAny<string>())).AtMostOnce().Verifiable();
    
   HomeController controller = new HomeController();
   //Set the controller's context to the mock! (fake)
   controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
   //DO IT!
   ViewResult result = controller.UploadFiles() as ViewResult;
   //Now, go make sure that the Controller did its job
   var uploadedResult = result.ViewData.Model as List<ViewDataUploadFilesResult>;
   Assert.AreEqual(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "foo.doc"), uploadedResult[0].Name);
   Assert.AreEqual(8192, uploadedResult[0].Length);
   postedfile.Verify();
}

How to do File Upload with ASP.NET MVC

Now, what is the least amount of code in our Controller do we need to write to make this test pass? Here we get to use the Request.Files method that ASP.NET (not ASP.NET MVC) has had for years, and use it as advertised. It works in the tests and it works in production.
Important Note: We have to use the HttpPostedFileBase class, rather than the HttpPostedFile because every Request, Response, HttpContext and all related ASP.NET intrinsic abstractions are one layer farther way in ASP.NET MVC. If you get an HttpRequest in ASP.NET, then in ASP.NET MVC at runtime...
  • you'll get an HttpRequestWrapper while running under a Webserver
  • you'll get a dynamically generated derived Mock of an HttpRequestBase while running outside a Webserver (like inside a test) when you've made your own ControllerContext.
In each case, the instances you'll get are both (ultimately) of type HttpRequestBase, but it's this extra layer of abstraction that makes ASP.NET MVC easy to test and ASP.NET WebForms less so. I hope these Wrappers will be included in a future release of WebForms. The fact that they live in the System.Web.Abstractions.dll and not System.Web.Mvc.Abstractions.dll tells me someone has their eye on that particular ball.
At any rate, here's the Controller that takes File Upload requests:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class ViewDataUploadFilesResult
{
   public string Name { get; set; }
   public int Length { get; set; }
}
public class HomeController : Controller
{
   public ActionResult UploadFiles()
   {
      var r = new List<ViewDataUploadFilesResult>();
      foreach (string file in Request.Files)
      {
         HttpPostedFileBase hpf = Request.Files[file] as HttpPostedFileBase;
         if (hpf.ContentLength == 0)
            continue;
         string savedFileName = Path.Combine(
            AppDomain.CurrentDomain.BaseDirectory,
            Path.GetFileName(hpf.FileName));
         hpf.SaveAs(savedFileName);
         r.Add(new ViewDataUploadFilesResult()
            { Name = savedFileName,
              Length = hpf.ContentLength });
      }
      return View("UploadedFiles",r);
   }
}
At the bottom where I ask for the "UploadedFiles" view, and I pass in my list of ViewDataUploadFilesResults. This will appea in the ViewData.Model property. The View then displays them, and that's ALL the View does.

?
1
2
3
4
5
<ul>
<% foreach (ViewDataUploadFilesResult v in this.ViewData.Model)  { %>
       <%=String.Format("<li>Uploaded: {0} totalling {1} bytes.</li>",v.Name,v.Length) %>
<%   } %>   
</ul>

Conclusion

I always encourage people to take the little bit of time to use Fiddler or SysInternals or look at your call stack or just to take a breath and remind oneself, "so how is this supposed to work?" Otherwise, one is just cargo-cult programming.

This post was a long answer to the question "How do I do FileUpload with ASP.NET MVC?" but I feel better having written in this way.

Saturday, February 4, 2012

A Brief Explanation of HttpModule and HttpHandler

A Brief Explanation of HttpModule and HttpHandler

An HTTP request from client to server can be explained as a chain of IIS, AspNET_ISAPI, Asp.NET Work Processor, HttpModules and HttpHandlers. The last part of the chain which is HttpHandler, creates the HTML and sends the result to HttpModule. AspNet_IASPI.dll is used for Asp.NET pages. And chain completes in reverse order this time, as shown below:


HttpModules and Usage:

We can use several predefined methods of the Global.asax file to perform actions on start/end of the application, on start/end of the request etc., and an HttpModule  do the same thing with more modularity. So, an HttpModule can be thought as a modular alternative of Global.asax file and its usage is recommended.


 

For creating an HttpModule, you should implement IHttpModule interface, and then Init and Dispose methods. We can use HttpApplication object:


using System;
using System.Web;
namespace CodeBalance.Web
{
    public class ExampleHttpModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            app.BeginRequest += new EventHandler(newBeginRequest);
        }
        public void Dispose()
        {
            // dispose operations, if necessary
        }
        void newBeginRequest(object sender, EventArgs e)
        {
            HttpApplication context = (HttpApplication)sender;
            string Url = context.Context.Request.RawUrl;
            if (!Url.Contains("SystemMonitoring.aspx"))
            {
                // show error page
            }
        }
    }
}

You can easily add/remove HttpModule via web.config file:

 



HttpHandlers and Usage:

HttpHandlers define actions for different type of requested files. They also can perform actions even if that file does not exist. An HTML page can perform all of the operations of an HttpHandler. But an HttpHandler has better performance and has more modularity than pages.


 

For creating an HttpHandler, you should implement IHttpHandler interface and then IsReusable and ProcessRequest methods. We can use HttpContext's Request and Response objects:


using System;
using System.Web;
namespace CodeBalance.Web
{
    public class ExampleHttpHandler : IHttpHandler
    {
        public void IsReusable(HttpApplication app)
        {
            // readonly.determines if this handler can be used in another requests
        }
        public void ProcessRequest(HttpContext context)
        {
            context.Response.Write("Hello World!");
        }
    }
}

You can easily add/remove HttpHandler via web.config file:

Another way to differentiate between a HttpModule and an HttpHandler is this:

HttpModules are used to redirect url's or to attach a HttpCookie to the http stream.

HttpHandlers are used to server a custom data type to the http stream. One of many examples would be if you had photos in a database that you wanted to display on a page, you're only option is an HttpHandler.





 

Thursday, February 2, 2012

15 Best Practices for Exception Handling

1) Don't manage business logic with exceptions. Use conditional statements instead. If a control can be done with if-else statement clearly, don't use exceptions because it reduces readability and performance (e.g. null control, divide by zero control).

2) Exception names must be clear and meaningful, stating the causes of exception.

3) Throw exceptions for error conditions while implementing a method. E.g. if you return -1, -2, -3 etc. values instead of FileNotFoundException, that method can not be understand.

4) Catch specific exceptions instead of the top Exception class. This will bring additional performance, readability and more specific exception handling.

5) Null control with conditionals is not an alternative to catching NullPointerException. If a method may return null, control it with if-else statement. If a return may throw NullPointerException, catch it.

6) Try not to re-throw the exception because of the price. Bu if re-throwing had been a must, re-throw the same exception instead of creating a new exception. This will bring additional performance. You may add additional info in each layer to that exception.

7) Define your own exception hierarchy by extending current Exception class (e.g. UserException, SystemException and their sub types) and use them. By doing this you can specialize your exceptions and define a reusable module/layer of exceptions.

8) Use types of exceptions clearly. Fatal: System crash states. Error: Lack of requirement. Warn: Not an error but error probability. Info: Info for user. Debug: Info for developer.

9) Don't absorb exceptions with no logging and operation. Ignoring exceptions will save that moment but will create a chaos for maintainability later.

10) Don't log the same exception more than once. This will provide clearness of the exception location.

11) Always clean up resources (opened files etc.) and perform this in "finally" blocks.

12) Exception handling inside a loop is not recommended for most cases. Surround the loop with exception block instead.

13) Granularity is very important. One try block must exist for one basic operation. So don't put hundreds of lines in a try-catch statement.

14) Produce enough documentation for your exceptions (at least JavaDoc).

15) Giving a number/code for each different exception message is a good practice for documentation and faster communication.