This is the 2nd part to my OpenRasta introduction (see part 1 here) in which I’m going to cover Handlers and OperationResults.
Handlers are very much like MVC Controllers, except that there is no base class or interface to implement
This makes them incredibly lightweight and a dream to work with.
The OpenRasta equivalent of MVC Actions are Operations. These look very similar to their MVC counterparts except we return an OperationResult instead of an ActionResult.
OperationResults represent HTTP Status codes, and you should strongly consider the choice of OperationResult that you use.
public class FooHandler
{
private readonly IFooService fooService;
public FooHandler(IFooService fooService)
{
this.fooSerivce = fooService;
}
public OperationResult Get(int id)
{
var foo = fooService.Get(id);
if(foo == null)
return new OperationResult.NotFound();
return new OperationResult.OK(foo);
}
}
(similarly to my last post, I’ll ignore the fact that we shouldn’t be sending domain objects out of our handlers for brevity of the example)
In the above case, if the IFooService cannot find the request Foo object, we return an OperationResult.NotFound which is a direct representation of HTTP Status 404.
If it is found, we return an OK (HTTP 200) passing the Foo “resource” out as the ResourceResponse for encoding later in the pipeline.
OpenRasta code is designed with discoverability in mind, intellisense is your friend. Start typing:
new OperationResult.
and see the complete list of HTTP Statuses you can return. Different results have different arguments, for example:
new OperationResult.SeeOther {RedirectLocation = "~/somewhere" }
In OpenRasta, Operations have the name of the HTTP Verb you want them to respond to (you can override this behaviour with named operations, more on this later).
This means that you have a Handler per Resource, which is an excellent means of helping enforce S.R.P.
The last part we need is the registration.
ResourceSpace.Has.ResourcesOfType<Foo>()
.AtUri("/foo/{id}")
.HandledBy<FooHandler>()
.RenderedByAspx("~/Views/Foo.aspx");
The brilliant fluent configuration API makes the above code very self explanitory, but just to clarify:
ResourceSpace.Has.ResourcesOfType<Foo>() // Tell OpenRasta about our Foo type
.AtUri("/foo/{id}") // Providing the URI where Foos reside. The brackets are parameter templating just like MVC
.HandledBy<FooHandler>() // Here we tell OpenRasta which class handles requests for Foos
.RenderedByAspx("~/Views/Foo.aspx"); // Here we set a WebForms codec, using the given view
How much simpler could this be?
Next post we’ll look at Pipeline Contributors
Huddle are hosting an OpenRasta Code Camp on the 18th February at their London offices. You want to go to this.
You can read more about the event here and register for the event here.
You haven’t heard of OpenRasta? For those living under a rock, to quote from the wiki:
OpenRasta is a resource-oriented framework for .NET enabling easy ReST-ful development of web sites and services. OpenRasta is designed to run on .net 2.0 and above, and can co-exist peacefully with your existing ASP.NET and WCF deployments.
However, this statement alone does not come close to describing the awesomeness of OpenRasta.
OpenRasta is “resource-oriented”, this really cannot be understated. OpenRasta elegantly embraces the way HTTP is designed which immediately removes countless issues you encounter when using the likes of ASP.NET MVC.
For those who need an HTTP referesher, consider URIs. The clue is in the name, Uniform RESOURCE Identifier. A resource can be anything, to take Seb’s example from his Progressive.NET talk, a teacup.
Now you can’t send a teacup over the wire, but we can send an encoded projection. In MVC, you might do something like:
public ActionResult Get()
{
var cup = teacupService.Get();
return View("TeaCup", cup);
}
which will use the WebForms view engine to combine the TeaCup.aspx template with the cup resource (I’m going to overlook the fact that you shouldn’t be sending your domain objects out directly for brevity).
This is ok, but what happens when you want the teacup in JSON format? You can do one of two things. Either you create a whole new Action method:
public ActionResult GetAsJson()
{
var cup = teacupService.Get();
return Json(cup);
}
which immediately creates all sort of code smells; duplication, encoding concerns in the method names (and therefore url) and the method itself. Meh.
Or you could remove some of this duplication by having a single action method and checking the accept headers yourself inside the action method, but come on, seriously. Why should you have to do all this boilerplate/plumbing code yourself? I might as well just be using an HTTP Handler. What power is the Controller giving you if you’re having to do everything yourself?
Do not fear. OpenRasta is here! Lets see how we do the same thing in OpenRasta:
public class TeaCupHandler
{
public OperationResult Get()
{
var cup = teacupService.Get();
return new OperationResult.OK(cup);
}
}
(obviously I’m ignoring error handling here)
But wait, I hear you cry! Where do I specify the encoding? In the configuration of course, somewhere completely separate to the above handler method, as it isn’t its concern.
ResourceSpace.Has.ResourcesOfType<TeaCup>()
.AtUri("/teacup")
.HandledBy<TeaCupHandler>()
.AsJsonDataContract()
.And.AsXmlDataContract()
.And.RenderedByAspx("~/Views/TeaCup.aspx");
Look at that! One line of code for each type of encoding we want! *joys* The lovely fluent `.And.` allows you to chain up as many different types of encoding support as you like. And because OpenRasta is completely pluggable and extendible (no, it REALLY is, not like in the way MVC claims) you can write your own codecs with extreme ease.
So, that was a very brief introduction to encoding in OpenRasta. In future posts I will cover HTTP verbs and handlers in greater detail, and show you the power of the pipeline!
You use a convention!
public class StringPropertyConvention : IPropertyConvention, IPropertyConventionAcceptance
{
public void Apply(IPropertyInstance instance)
{
instance.Length(4001);
}
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType == typeof (string));
}
}
Make sure you register the conventions with the automapper.
Peace
If you need to get access to the date part of a DateTime through HQL, the easiest way is to use a custom dialect:
public class CustomDialect : SQLiteDialect
{
public CustomDialect()
{
RegisterFunction("DateOnly", new StandardSQLFunction("date", NHibernateUtil.String));
}
}
public class CustomDialect : MsSql2005Dialect
{
public CustomDialect()
{
RegisterFunction("DateOnly", new SQLFunctionTemplate(NHibernateUtil.DateTime, "DATEADD(dd, 0, DATEDIFF(dd, 0, ?1))"));
}
}
Because I use SQLite for my integration tests and MSSQL2005 for my runtime database, I need two different dialects, one for each provider. Using the custom function name “DateOnly” I can have the same HQL work on both databases
You can then use this function, like so:
select DateOnly(x.Date), count(x.Id)
from someEntity x
group by DateOnly(x.Date)
Win.
Time and time again I encounter repositories which are just a free-for-all mess, so here is a definitive guide to SVN and project code organisation for the tidy-inept.
Most people will use their repository for multiple projects. For this reason it is a sensible idea to have top level folders which semantically group your code. How you do this depends largely on what code/projects you have in SVN. Here’s an example:
root
- Customer A
-- Project X
-- Project Y
- Customer B
-- Project Q
-- Project X
Next, under each Project you should have:
Project X
- trunk
- branches
- releases
- tags
Sometimes its more appropriate to have the releases folder under branches (as they technically are branches), it doesn’t really matter. What is important is that you are branching your releases!
.NET Project Organisation
Here is how I organise my projects:
/
/lib
/src
/src/<projectname>.sln
/src/<projectname><assembly-specific-names>
/tools
/rakefile.rb
Nice and clean
The lib folder holds all your 3rd party assemblies which your project utilises.
The src folder contains…you guessed it, your source code!
The tools folder contains mainly build tools and test runners. Mine also has the NHibernate Profiler in there, too.
The rakefile is my build script, if you enjoy angled-bracketed-unneccessaryness this could be your NAnt or MSBuild file.
Next, externals. If your project shares code with another, this shared code should be under a separate project, and included via an svn:external under the lib folder. For example:
/lib/<folder-for-external>
Useful Resources
Here are some great examples of best practices for code and svn organisation.
And here is an excellent book on the subject!
One tidy life….Done!
Following on from my recent post how to test asp.net mvc views existence, I found myself with in a very similar situation! This time however, it was FileResult instead of ViewResult.
I’m not making any excuses, this is far from the prettiest or most flexible solution, but for my setup it works perfectly
Have some code:
public abstract class ControllerTest<TController> where TController : IController
{
protected void AssertFileIsCorrectAndExists(FileResult result, string filename)
{
// hack of death!!!!
var webProjectPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, Path.Combine("../../../", typeof(TController).Assembly.GetName().Name)));
// crudely trim leading ~/
if (filename.StartsWith("~/"))
filename = filename.Substring(2);
var fullPath = Path.Combine(webProjectPath, filename);
Assert.IsTrue(File.Exists(fullPath), "File `" + fullPath + "` does not exist");
}
Following a recent embarrassing episode where I had been banging on about how unit testing saves the world, then released a broken site, I decided a solution to prevent this happening again was necessary!
I currently test my MVC ViewResults like this:
public class when_requesting_a_login_form : ControllerTest<LoginController>
{
private ViewResult result;
protected override void Act()
{
this.result = this.SubjectUnderTest.LogIn() as ViewResult;
}
[Test]
public void the_login_view_should_be_returned()
{
this.result.ViewName.ShouldEqual("Login");
}
}
However this doesn’t check that the Login.aspx view actually exists (which it didn’t in the case I’m talking about, as I only found out at runtime). Below is my new test:
[Test]
public void the_login_view_should_be_returned()
{
AssertViewIsCorrectAndExists(result, "Login");
}
This assertion not only checks that the view names match, but also that the file exists on disc.
The solution is far from elegant, but it works, which is better than nothing!
Before I show you the codes, some prerequisite knowledge about my solution setup is required.
My folders are ALWAYS organised like this:
/src/Project.Web/
/src/Project.Domain/
/src/Project.Tests.Unit/
with these folder names matching the assembly names. This allows the following very fragile code to work:
protected void AssertViewIsCorrectAndExists(ViewResult result, string viewName)
{
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new TestingViewEngine());
Assert.AreEqual(viewName, result.ViewName, "View names do not match");
var controllerContext = Stub<ControllerContext>();
controllerContext.RouteData = new RouteData();
controllerContext.Controller = SubjectUnderTest;
var controllerName = typeof(TController).Name;
controllerContext.RouteData.Values.Add("controller", controllerName.Substring(0, controllerName.Length - "controller".Length));
var viewEngineResult = result.ViewEngineCollection.FindView(controllerContext, result.ViewName, result.MasterName);
Assert.IsNotNull(viewEngineResult.View, "View '" + result.ViewName + "' could not be found");
}
public class TestingViewEngine : WebFormViewEngine
{
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
// hack of death!!!!
var webProjectPath = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, Path.Combine("../../../", controllerContext.Controller.GetType().Assembly.GetName().Name)));
foreach(var location in this.ViewLocationFormats)
{
var virtualViewPath = string.Format(location, viewName, controllerContext.RouteData.Values["controller"]);
// crudely trim leading ~/
virtualViewPath = virtualViewPath.Substring(2);
var fullPath = Path.Combine(webProjectPath, virtualViewPath);
if (File.Exists(fullPath))
return new ViewEngineResult(MockRepository.GenerateStub<IView>(), this);
}
return new ViewEngineResult(this.ViewLocationFormats);
}
}
Crude I know, but I hope this helps someone!
Following on from Robert Pickerings F# introduction at Progressive.Net in London last week, I was inspired to try and do something with this powerful functional language.
As an exercise I though’t I’d port some old code I wrote in Haskell several years ago, a simple Caeser Cipher cracker.
A Caeser Cipher works by shifting each letter of the alphabet by n positions. A shift of 3 would encode “ABCD” as “DEFG”. Due to this simple linear transform (y = x + c), the Caeser Cipher is incredibly easy to crack with frequency analysis. By shifting the ciphertext by 1-25 positions and comparing the frequency of each letter in the resulting plaintext candidate to a table of English letter frequencies, it is possible to easily discover the original plain text (assuming there is sufficient data to make the expected freqency distributions).
Here’s the code!
Disclaimer: This is the first F# code I’ve ever written, so don’t count on it being remotely decent. Suggestions for improvements are more than welcome!
#light
let alphabet = ['A'..'Z']
let getpos x xs = List.find_index ((=) x) xs
let let2nat c = getpos c alphabet
let nat2let i = alphabet.[i]
let shift i a = nat2let ((let2nat a + i) % 26)
let encode i s = new string(Seq.map (fun c -> shift i c) s |> Seq.to_array)
let decode i = encode (26 - i)
let count c s = Seq.filter ((=) c) s |> Seq.length
let percent a b = (float a / float b) * 100.
let freqs ws = [for x in alphabet do
yield percent (count x ws) (Seq.length ws)]
let table = [8.2; 1.5; 2.8; 4.3; 12.7; 2.2; 2.0; 6.1; 7.0;
0.2; 0.8; 4.0; 2.4; 6.7; 7.5; 1.9; 0.1; 6.0;
6.3; 9.1; 2.8; 1.0; 2.4; 0.2; 2.0; 0.1]
let chisqr os es =
let chied = [for x, y in Seq.zip os es do
yield ((x - y) * (x - y)) / y]
List.sum chied
let crack ws =
let wws = [for x in [0..25] do
yield chisqr (freqs (decode x ws)) table]
let n = getpos (Seq.min wws) wws
decode n ws
let ciphertext = encode 5 "THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG"
let plaintext = crack ciphertext
System.Console.WriteLine(ciphertext)
System.Console.WriteLine(plaintext)
This produces:
YMJVZNHPGWTBSKTCOZRUJITAJWYMJQFEDITL
THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG
Ok this was an annoying one, If your TDD.Net runner keeps telling you “No tests run (No tests where found)” and you’ve run the “InstallTDNetRunner.bat” you can try the following:
Edit the InstallTDNetRunner.bat
and comment out the last 2 lines:
regedit MSpecTDNet.reg
del MSpecTDNet.reg
Run the bat file and a .reg should appear in the same folder. Edit this.
in there you should see: AssemblyPath”=”<some path>\\Machine.Specifications.TDNetRunner.dll”
Make sure this path is actually correct (it wasnt for me). Then save the .reg and run it.
Job done
Just a quick one, but it took me a while to figure this out. Hopefully this can help someone else out.
To get MSpec working with ReSharper you need to copy all the MSpec dlls into the resharper’s plugins folder, so you end up with:
ReSharper/bin/plugins/machine.specifications/<dlls here>
Make sure you delete whichever one of the ReSharperRunner dlls is not your ReSharper version!
Enjoy