Flex PMD - improve your code quality

I recently started to look into the Flex PMD open source project. It's supposed to help you analyze your Flex/AS3 code and help you see coding issues that may need to be fixed.

You can either just use the default ruleset for analyzing your code or create your own custom ruleset. There's an editor you can use to view the default ruleset which also describes each rule and shows examples of a code snippet which would cause it to be applied. You can also change the severity you want to apply when you run Flex PMD or remove rules you don't want to include in the project.

For example, in a current project I wanted to make sure that all custom events are overriding the clone function. If you drill down to the missing clone function rule, you can see a detailed description and example where it will be applied.



When you are done, you can easily export the ruleset if you have made any changes to it.

Once you're ready to run it, you have to download either the command line, ant or the maven version. I decided to use ant and there's a good example that you can build from easily.

An XML file is generated as output and you can either read it directly or use the online PMD Violations Viewer which shows you the result graphically.

If we want to see any custom events with a missing clone function, you can just drill down to the "EventMissingCloneFunction" and you'll see any events with a missing clone function.



Flex PMD really seems powerful but pretty simple to start using it.

Test ASP.NET MVC routes using MVC Contrib

Last time I showed one alternative way of testing routes using Moq and NUnit. It works well but it adds code bloat. The MVC Contrib project has a nice set of test helper methods which simplifies it.

It assumes you use NUnit and RhinoMocks. It also assumes you set your routes in the ASP.NET MVC RouteCollection object. If you reference your routes in your test project like I do, then this shouldn't be a big issue either.

Our previous test method looked like this:


[Test]
public void Test_If_Product_Route_Returns_Expected_Result()
{
RouteCollection routes = new RouteCollection();
POC_Stuff.MvcApplication.RegisterRoutes(routes);

var context = MvcMockHelpers.FakeHttpContext("~/products/videogames/nintendo");
RouteData routeData = routes.GetRouteData(context);

Assert.That(routeData.Values["category"].ToString() == "videogames");
Assert.That(routeData.Values["subcategory"].ToString() == "nintendo");
Assert.That(routeData.Values["controller"].ToString() == "Catalog");
}


The new test method using the MVC Contrib test helpers will look like this:

[Test]
public void Test_If_Product_Route_Returns_Expected_Result()
{
"~/products/videogames/nintendo".ShouldMapTo(x => x.Index("videogames", "nintendo"));
}


I don't think you can make it much more compact! It will even do the assertions for you, the test helper will assert the route data, the controller, the method and its parameters. If you want to make additional asserts, that is possible as well since it returns a RouteData object from the System.Web.Routing namespace.

The main test class in the MVC Contrib project is called RouteTestingExtensionsand the method that will assert the route for us is called ShouldMapTo and the code as of when this post was written looks like this:


///
/// Asserts that the route matches the expression specified. Checks controller, action, and any method arguments
/// into the action as route values.
///

/// The controller.
/// The routeData to check
/// The action to call on TController.
public static RouteData ShouldMapTo(this RouteData routeData, Expression> action)
where TController : Controller
{
routeData.ShouldNotBeNull("The URL did not match any route");

//check controller
routeData.ShouldMapTo();

//check action
var methodCall = (MethodCallExpression) action.Body;
string actualAction = routeData.Values.GetValue("action").ToString();
string expectedAction = methodCall.Method.Name;
actualAction.AssertSameStringAs(expectedAction);

//check parameters
for (int i = 0; i < methodCall.Arguments.Count; i++)
{
string name = methodCall.Method.GetParameters()[i].Name;
object value = null;

switch ( methodCall.Arguments[ i ].NodeType )
{
case ExpressionType.Constant:
value = ( (ConstantExpression)methodCall.Arguments[ i ] ).Value;
break;
case ExpressionType.MemberAccess:
value = Expression.Lambda(methodCall.Arguments[ i ]).Compile().DynamicInvoke();
break;
}
value = (value == null ? value : value.ToString());
routeData.Values.GetValue(name).ShouldEqual(value,"Value for parameter did not match");


These doesn't seem to be too many developers in the community talking about this great test helper but I hope you see the value it adds.

Routes in ASP.NET MVC

The routing enginge that ASP.NET MVC is quite powerful and allows mapping between an URL and the controller and controller action. The routing was originally released in ASP.NET 3.5 SP 1 but I suspect few use it with WebForms. You can easily add new routes and have multiple different routes.

As an example, let's assume we want to have a route where we easily can list various products and also a separate route for events that we offer during various dates. A good piece of advice by Scott Hanselman is to add a comment above your route to make it more clear what the expected route is which I normally do. All the routes are normally wired in the global.asax.

Our first route to display a subcategory will look like this: http://localhost/product/videogames/nintendo . The crafted route will look like this.


// http://localhost/product/category/subcategory
// http://localhost/product/videogames/nintendo
routes.MapRoute(
"Category", // Route name
"products/{category}/{subcategory}", // URL with parameters
new
{
controller = "Catalog", action = "Index", category = "Listed",
subcategory = "All Items"
}
);


We added defaults for the controller, action, category and subcategory but of course that is optional. Our controllers will accept the category and subcategory and act on it.

Our controller class will need to get the category and subcategory to be able to act on it. Our controller in this example looks like this:


public class CatalogController : Controller
{
//
// GET: /Catalog/

public ActionResult Index(string category, string subcategory)
{
ViewData["Message"] = string.Format("Category {0}, Subcategory{1}"
, category, subcategory);
return View();
}

}


In our next route, we want it to be displaying a specific event on a specific date and as an example it will look like this: http://localhost/events/2009/05/25 . We will craft it like this:


// http://localhost/events/year/month/day
// http://localhost/events/2009/05/25
routes.MapRoute(
"Event", // Route name
"events/{year}/{month}/{day}", // URL with parameters
new
{
controller = "Event",
action = "Index"
}
);


A corresponding controller that will be handling this request has to be able to handle the year, month and day:


public class EventController : Controller
{
//
// GET: /Event/

public ActionResult Index(string year, string month, string day)
{
ViewData["Message"] = string.Format("Event for mm {0} / dd {1} / yyyy {2}"
, month, day, year);
return View();
}

}


If you have many routes set up, it may be difficult to figure out why a route isn't being executed as expected. I hope most people by now are familiar with Phil Haack's excellent URL Routing Debugger.

If we try to hit our product URL by incorrectly specifying the URL http://localhost/product, the Routing Debugger shows that the expected route is not being routed correctly.


This can save a ton of time if you have many routes set up in the same project.

The one thing we're still missing is unit tests. We should have started with the unit tests but in this example we're showing the example in reverse order to make the routing mechanism more clear. The ASP.NET MVC framework supports many different unit test and mocking frameworks, I prefer the combination of NUnit and Moq but you can use any of the other supported .Net unit testing/mocking frameworks.

In order to test the routing mechanism, we need to be able to mock the HttpContext. I prefer to use the class MvcMockHelpersthat Scott Hanselman has blogged about instead of writing it from scratch. Our test case for the product route will be quite simple since the plumbing is already done:


using System;
using System.Web;
using System.Web.Routing;
using Moq;
using NUnit.Framework;

[TestFixture]
public class RouteTest
{
[Test]
public void Test_If_Product_Route_Returns_Expected_Result()
{
RouteCollection routes = new RouteCollection();
POC_Stuff.MvcApplication.RegisterRoutes(routes);

var context = MvcMockHelpers.FakeHttpContext("~/products/videogames/nintendo");
RouteData routeData = routes.GetRouteData(context);

Assert.That(routeData.Values["category"].ToString() == "videogames");
Assert.That(routeData.Values["subcategory"].ToString() == "nintendo");
Assert.That(routeData.Values["controller"].ToString() == "Catalog");
}
}


We call the RegisterRoute method of the Global.asax to get the actual routes. After we get the fake HttpContext with our URL, we just need to verify if we see the expected result.

There are other ways to set up the routing with some of the other frameworks like MvcContrib which we will look at next time.

ASP.NET MVC - Post to controllers

When you first start out using the ASP.NET MVC framework, it might not be apparent the many different ways you can solve the same problem. One example of this is when you want to post form data from a view to a controller.

Most of the official examples when the ASP.NET MVC framework was in early preview showed how to use the HttpRequest object to gather the form data inside the controller.


public ActionResult Edit()
{
SalesOrderForm form = new SalesOrderForm();

string customerName = Request.Form["CustomerName"];
string address = Request.Form["CustomerAddress"];
string orderNumber = Request.Form["OrderNumber"];

return View(form);
}


In this way, you can use the Request object and pull the data out. I don't like to tie the controller directly to the HttpRequest object without any abstraction and I really dislike having use magic strings. It brings back not so fond memories of classical ASP for those that have used the Microsoft stack long enough. Thankfully, very few examples uses this way of gathering the form data.

An alternative way to pass the form data is to create an action method in the controller which will accept the values posted from the view. The view form fields must match the same names in the controller. A subset of our view shows the fields we are concerned with.


<% using (Html.BeginForm()) { %>

Fields



<%= Html.TextBox("CustomerName") %>




<%= Html.TextBox("Address") %>




<%= Html.TextBox("OrderNumber") %>






<% } %>


The controller action method must have matching variable names. The action method is pretty simple in our case and we just need the matching variable names.


[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(string customerName, string address, string orderNumber)
{

string myCustomerName = customerName;
string myAddress = address;
string orderNumber = orderNumber;

// Persist the data into our repository

return View();
}


It's a pretty simple exercise to match them but quickly gets unruly if we have more than a handful of parameters we need to pass in. Thankfully, there are a few better ways to handle it. In the next scenario we will use the FormCollection object and use the MVC framework to map it to a view model.


public class SalesOrderForm
{
public string CustomerName { get; set; }
public string Address { get; set; }
public string OrderNumber { get; set; }
}



[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(FormCollection formCol)
{
SalesOrderForm form = new SalesOrderForm();

UpdateModel(form);

// Persist to our repository

return View(form);
}


Our action method only needs to accept the FormCollection object. We instantiate our view model object and call the UpdateModel method which is method of the base class System.Web.Mvc.Controller. Any controller class that you create using the Visual Studio MVC template is subclassed from it and have this method available. Through reflection, it converts between the properties and the form data passed in. This gives us a pretty clean way of mapping the form data to our view model.

There is an even cleaner way to map the form data to a view model.


[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit([Bind(Prefix = "")]SalesOrderForm salesForm)
{
// Persist to the repository

return View(salesForm);
}


By using the Bind attribute, the controller will attempt to match up the properties with the form data. I think this is the cleanest way to map between the view and the view model and this is the way I usually handle form data that is posted to the controllers.

Handling SOAP faults with HttpWebResponse object

When you call web services, in normal cases you would use the web service proxy objects that gets generated when you add a web reference and not send in an HTTP POST to the web service. I had an interest case recently where we had to build a test client that accepted invalid SOAP requests with malformed XML as well as well-formed SOAP requests.

If the web service returns a normal response, we can handle the response and just parse the returned XML. The code is what you would expect

 
try
{

WebResponse webResponse = webRequest.GetResponse();

if (webResponse != null)
{
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
response = sr.ReadToEnd().Trim();
}
}
catch (Exception ex)
{
// Handle the request
}


However, if the web service throws a SOAP fault when we try to get the response, the stack trace of the exception will not return the SOAP fault that you would expect. Instead we just a fairly generic error message and an HTTP 500 Internal Server error.



What's going on? If we use a HTTP sniffer to see the actual raw response we get some clues.
 
HTTP/1.1 500 Server Error
Server: Sun-ONE-Web-Server/6.1
Date: Wed, 15 Apr 2009 00:42:33 GMT
Content-length: 978
Content-type: text/xml; charset=utf-8
X-Powered-By: Servlet/2.4 JSP/2.0
X-Charles-Received-Continue: HTTP/1.1 100 Continue

 
soapenv:ServerSchema validation failed for request.5
Schema validation failed for request.
string value 'MVP_CUSTOMER' is not a valid enumeration value for CustomerType in namespace
http://acme.com/ws/customerorder/v1
MVP_CUSTOMER





It's apparent that the web server interprets a SOAP fault as an HTTP 500 error so it has nothing to do with HttpWebResponse class doing something invalid. When we sniffed the HTTP traffic, we could see the detailed SOAP fault information so why can't see it when we catch an exception?

We need to catch a WebException and then cast the WebException.Response into an HttpWebResponse object. Once we have a valid HttpWebResponse object, we can read the response stream and get the SOAP fault information out. We can then extract the information and turn it into a useful error messages for the logfile or the users.

 
try
{

WebResponse webResponse = webRequest.GetResponse();

if (webResponse != null)
{
StreamReader sr = new StreamReader(webResponse.GetResponseStream());
response = sr.ReadToEnd().Trim();
}
}

catch (WebException wex)
{
// We issued an HttpWebRequest, so the response will be an
// HttpWebResponse.
HttpWebResponse httpResponse = wex.Response as HttpWebResponse;

// Grab the response stream.
using (Stream responseStream = httpResponse.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
// Grab the body of the response as a string for parsing.
string failureReason = reader.ReadToEnd();

// If it failed with a SOAP fault, parse the response body into a usable exception.
ThrowIfSoapFault(failureReason);

// If it was not a SOAP fault, rethrow the original exception.
throw;
}
}

}



Most of the code shown in this example can be found at MSDN.

SiteFinity - using SWF files

I've finally had a chance to continue with my POC to try to integrate my SWF file into SiteFinity. It went pretty smoothly but there was quite a bit of manual work. I haven't had a chance to look at version 3.6 of SiteFinity yet, I hope later versions would have a control that would handle the browser initialization of the SWF file and helping take care of the reference to the SWF file.

I've heard a lot of buzz about swfobject which is a JavaScript based framework that instantiates Flash based content regardless of browser, I decided to try it out to see how I would like it. After working for a Fortune 500 company, you learn to worry about what license any open source projects uses, swfobject uses the MIT license which is a plus. It has a nice wizard that will help you set up the appropriate attributes which really helps when you're unfamiliar how to use it in the beginning.

In SiteFinity, the only way I have found from my initial research is to add it to the Master Page. Hopefully there's a better way than to be forced to have the user get the JavaScript downloaded to the browser or have to add a custom user control if you just have a handful of pages where you use SWF files. I decided to just link to the Google Code repository but you probably want to include it in your website in production scenarios.



I just uploaded my SWF file to the Files section in SiteFinity and then added it via an OBJECT tag in a Generic Control. I have not been able the get the file reference of the SWF file to be resolved inside the OBJECT so I can use a relative reference like for the server side controls in SiteFinity. Instead, I've had to put the full URL to the file which is a pain point if you have separate QA and Production environments. It appears that others in the SiteFinity forums also have struggled with this but hopefully I'm just overlooking something.



The actual page shows the SWF file as we would expect.



It is a relatively easy process to add a SWF to SiteFinity but hopefully there will be an easier way to add it in the future and control it better.

eBay integration in Flex

Work has been quite demanding lately but hopefully I will be able to post more regularly now.

I had planned to integrate eBay into SiteFinity via custom user controls but I decided to instead write the integration in Flex and integrate that into SiteFinity. It will make it easier for my client to add new versions since I only need to give them the SWF file and they can upload it themselves. I already know that we will need to support both search functionality for eBay auctions and ability to list items for auction and possibly other types of functionality. I decided to create a POC first and integrate that into SiteFinity before adding more interesting functionality. I focused on getting the infrastructure set up before making it look spiffy. In this post I'll show how to create the Flex binary. The SWF and source code has been posted here.



I decided to use one of the Flex MVC frameworks because I already know I will need to support several screens and it will make it easier to support. I picked the Mate framework, because it fits so nicely into Flex and it's non-intrusive. Mate strongly encourages you to separate the logic into views, event maps, events and business objects shown below.



The communication between the view and event handlers is handled via the Event Bus. An event is dispatched from the view and the event bus figures out which event map that listens for the event that was dispatched. The event map calls services and/or business objects. Commonly the event map also have injectors that binds properties in the view to business objects.

The event map in my POC is relatively simple displayed below.



This event map listens for the event SearchRequestEvent.GET and calls a business class SearchInvoker. This class makes a call to eBay using their Flash based API and dispatches either a success event or a fault event that gets handled inside the event map.

The event map also has Injectors that sets up the binding between properties in the view to the SearchManager. These injectors are initialized first before any custom events gets dispatched from the view.



The next step will be to add the SWF to SiteFinity.