Archive

Posts Tagged ‘.NET’

Unit Testing as a Method to Enforce Requirements

April 10th, 2008

I have recently started putting a lot of stock in automated unit testing. Not that I didn’t think unit testing was important in the past, I just didn’t know how to write them properly. A little instruction from a co-worker has corrected that situation and I am now writing proper unit tests. I like the test first approach, though I don’t know that I’ll be doing the full “TDD, no code without a test” thing just yet, but at the moment, I am writing tests first. Only time will tell if I can keep it up throughout the life of my project.

I recently ran into a situation that made me see some additional value in my tests. Beyond making sure everything works properly and lives through changes to the application, I am starting to see how my tests keep me in check and make sure I don’t stray from the requirements.

As an example we’ll assume we are testing classes from an application’s business layer. Each class in this layer will inherit from an abstract base class called “ServiceBase”. In this case, the ServiceBase is a generic class with some abstract members, but it also contains implementation code for a Save method.

The Save method accepts a business entity as an argument and decides whether to call Insert or Update in the underlying data access class. If the value passed in is null, the method throws an exception. This behavior is pretty standard, but some classes that inherit from it may have a need to perform some additional steps when saving. To account for this, I have also made the Save method virtual so any implementation that needs to can override the Save method.

Now we will create a couple of subclasses for ServiceBase. Let’s call them ProductService, CustomerService and OrderService. To start we create the ProductService class and make it inherit from the ServiceBase class. Now in order to make sure we have a complete set of unit tests, we create a test that expects an exception if a null item is passed to the save method. As long as the ServiceBase class throws the exception, it will pass for our test against the ProductService class. Now if we repeat the process (including the test) each class (ProductService, CustomerService, and OrderService), they will all have the ability to save an item, and each test that expects the exception should pass.

Now, let’s say the ProductService class has a need to write to a log when its Save method is called. This is easy, all we have to do is create an override for the Save method in our ProductService class. We add our logging code and all is good. We run our test and it fails.

Why did it fail? Because in my contrived story, we forgot to add the code that throws an exception if a null value is passed in. This is an honest mistake, but it’s ok because our test has saved us. This type of requirement cannot be enforced by the compiler through an interface or abstract base class. As far as the compiler is concerned, this code is completely valid. The unit test however, has alerted us to the fact that we did not implement the code according to our requirements (which was the basis for writing the test in the first place).

While this may be a no-brainer for those of you who have been practicing test driven development or just writing solid unit tests for a while, but for those of us who are just starting down this road this is an added benefit that may not seem obvious at first.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, C#, TDD, Unit Testing, programming , ,

RenderControl(), it isn’t just for page output

April 1st, 2008

This was originally posted on vanslaars.com in December of 2006.

In browsing through the unanswered posts on the asp.net forums, I came across an interesting question… somebody wanted to know how you would put the output from a GridView control in an email… since all of the ASP.NET Server controls end up producing html content, and the best way(actually the only way that I know of) to put a table into an email is with html, why not use the same mechanism for both? So how are controls rendered? Through their RenderControl method of course. This is actually a pretty simple task to accomplish and I found that there was more code to create temporary data than there was to actually embed the output in the email. So let’s take a look at the code:

protected void SendGrid()
{
MailMessage msg = newMailMessage();
msg.To.Add(<EMAIL HERE>);
msg.From = newMailAddress(<EMAILHERE>);
msg.Subject = "Testing";
msg.IsBodyHtml = true;
msg.Body = "<h1>Start Of Message</h1>";
msg.Body += GetGridHtml();
msg.Body += "<hr/>End of message";
SmtpClient mailServer = newSmtpClient("<MAIL SERVER ADDRESS>");
NetworkCredential mailLogin = newNetworkCredential("<USER NAME>",
"<PASSWORD>");
mailServer.Credentials = mailLogin;
mailServer.Send(msg);
}

private string GetGridHtml()
{
//Setup the gridview object
  GridView gv = new GridView();
gv.DataSource = CreateDataTable();
gv.DataBind();
StringWriter writer = new StringWriter();
HtmlTextWriter htmlWriter = newHtmlTextWriter(writer);
gv.RenderControl(htmlWriter);
return writer.ToString();
}

private DataTable CreateDataTable()
{
DataTable tbl = newDataTable();
tbl.Columns.Add("FirstName",typeof(string));
tbl.Columns.Add("LastName", typeof(string));
tbl.Columns.Add("Age", typeof(int));

DataRow row1 = tbl.NewRow();
row1["FirstName"] = "Bob";
row1["LastName"] = "Jones";
row1["Age"] = 32;

DataRow row2 = tbl.NewRow();
row2["FirstName"] = "Sally";
row2["LastName"] = "Smith";
row2["Age"] = 41;

DataRow row3 = tbl.NewRow();
row3["FirstName"] = "Jane";
row3["LastName"] = "Doe";
row3["Age"] = 26;

tbl.Rows.Add(row1);
tbl.Rows.Add(row2);
tbl.Rows.Add(row3);

return tbl;
}

The “CreateTableData” method is strictly to create some sample data to use as the datasource for the GridView control so we won’t focus on that, you could obviously use any valid datasource for your GridView. The “SendGrid” method is responsible for sending the email, to use this code you will need to enter the email information including the mail server and authentication information. This method also makes a call to “GetGridHtml” which is responsible for creating the GridView, binding the data to it and ultimately returning the Html output for the control. You’ll notice that once the new GridView is instantiated and DataBound, a StringWriter object is created and passed to the contructor for our HtmlTextWriter. RenderControl uses our HtmlTextWriter to load the rendered html to the underlying StringWriter and we use the StringWriter’s ToString method to return our html. The resulting html body for the email will contain an html table complete with column headings data from our datasource.

Another approach would be to loop through your datasource and create a standard html table, but with this approach we can take advantage of the internals of the GridView control, cutting down on code and making it much easier to make changes to the table structure directly through the datasource. I have a couple more ideas for RenderControl beyond page output that I will be posting in the near future. I’d be interested to hear of any other creative uses for RenderControl that you might have.. if you have anything you would like to share, feel free to leave a comment.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET , , , ,

Forcing an “open, save” prompt for known file types

March 31st, 2008

This was originally posted on vanslaars.com in December of 2006. It seemed pretty popular so I wanted to make sure it made it up on the new one.

Ever want to provide a link for a document that the user should download even though it will want to open directly in the user’s browser? Well, this isn’t as hard as you might think. Basically, all you need is a way to get some indirection between the clicking of the link and the transmission of the file to the user in order to tweak the response headers a bit. Using an HttpHandler makes this a breeze.

For this example, we will use a “.ashx” file, rather than creating a seperate HttpHandler assembly and registering it in the web.config, this way you can just drop the code in a file and see it work. I would highly recommend the Class Library approach for a handler that will be useful in multiple projects.

The basic project setup for this includes a directory in the root of my application called “PDF”, which holds a sample PDF document, the standard Default.aspx page and a “.ashx” handler file called “PdfHandler.ashx”. The code that will perform the file retrieval and force the dialog to appear is all in the “.ashx” file and the Default.aspx file will simply hold the following link code for testing purposes:

<a href="PdfHandler.ashx?fileName=css_cheat_sheet">Download CSS Cheatsheet</a>

As you can tell from the link, we will be calling the .ashx file from our link with a parameter called filename. The path and file extension for the file are not included since we want to limit the amount of information that is available in our querystring for the link.

In the Handler file (”PdfHandler.ashx”) we will add the following code to the “ProcessRequest” method:

string fileName = context.Request.QueryString[?FileName?];
if (!string.IsNullOrEmpty(fileName))
{
string filePath = context.Server.MapPath(string.Format(?~/PDF/{0}.pdf?,fileName));
context.Response.ContentType = ?application/pdf?;
context.Response.AddHeader(?Content-disposition?,
string.Format(?attachment;filename={0}.pdf?,fileName));
context.Response.WriteFile(filePath);
}

This code simply grabs the filename from the querystring, uses it to get the full path to the file through the MapPath method and then uses Response.WriteFile to send the file back to the user. This is not what I would call “production ready” code, but this is not the point of this example. The point here is the Header that is being added to the Response. The line that uses the AddHeader method is where the dialog comes in… setting the content-disposition to attachement and specifying a default filename will cause the browser to prompt the user to save the file. Without this, the PDF would be opened in Acrobat.

This is pretty simple to do, you just need to remember the proper syntax for the header since there is no strongly-typed way to set this through the Response object.

The first time I had to do this was in .NET 1.1 with a text file a few years back and it took quite some time to find the information, so hopefully this has made your life a little bit easier.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, ASP.NET, C#, programming , ,

LINQ with LINQPad

February 11th, 2008

My latest project at work has me working with LINQ to SQL. This is definitely cool stuff!

If you are not familiar with LINQ, it is a new feature of .NET 3.5 (C# 3.0/VB 9.0) and stands for Language INtegrated Query. It offers query syntax that can be used to query in-memory objects, XML, Databases, and more. You can learn more about LINQ here, here and here.

As I started working with LINQ, I found myself writing SQL queries and then working backwards to translate them into the appropriate LINQ syntax. This was fine to get the first couple of queries running and allowing me to get my project moving, but I wanted to be able to write LINQ queries without the SQL step and I wanted to be able to test them outside of the context of my application.

I found LINQPad, and it was exactly what I was looking for. To simplifiy, LINQPad allows you to write and run LINQ queries in a similar fashion to writing SQL queries in SQL Server Management Studio or Query Analyzer before that.

LINQPad comes pre-loaded with a couple hundred sample queries and can be used to run snippets of C# 3.0 or VB 9.0 code, not just LINQ queries!

If you are working with LINQ, this is a great way to practice, learn, test and just keep thinking in LINQ when simply querying your databases.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

.NET, C#, LINQ, Tools , , ,