#.think.in
learn.create.enjoy

Azure Table Storage in IronPython

February 20, 2009 14:14 by tarn

My goal was to write a bit of scaffolding to make using the storage service fun and easy from in IronPython. The Windows Azure SDK comes with a library in the samples which does the low level work interfacing with the API and provides some nice classes to work with. There are methods to generate table schemas by reflecting on model classes and another sample implements all the standard .NET providers.

I was hoping to write all the scaffolding and the model classes in IronPython but, in the first of a series of set backs, I found the development storage server behaves differently than the cloud. For some reason you need to create tables on the development storage server using a command line tool, passing your model assemblies as arguments. Apparently this will be fixed soon, but trying to stay focused I decided I'd have to write my models in C# for now.

Once I had an assembly with some models I could use the DevTableGen.exe command line tool that comes with the Azure SDK to create tables on my development storage server.

I don't think there are currently any good tools for visualizing and editing data, but I'm sure by the time its released it will integrate into Server Explorer and Query Analyzer (or perhaps it'll just be a Firefox plug-in). I've seen a presentation where HTTP requests are hand coded to retrieve data, but I wasn't up for that and tried importing the sample library into an IronPython console. I got enough working to convince me everything was going to work out, I just needed find out how to use extension methods in IronPython...

Much to my surprise and disappointment, consuming extension methods in IronPython is still difficult. There does appear to be a way to bind the extension methods, but I haven't seen an example binding all the Linq extension methods. This is a problem as it means Linq expression trees can't be easily built in IronPython. Passing expression trees as queries is ideal as the cloud can do the filtering, sorting and only return the data you want.   

I decided to put this problem on ice and write helpers in C# that returned a List<T> of all the rows. This won't work well with lots of data, but it will work find on small tables.

I wrapped the required credentials to connect to the service in an Account class, mainly so I could hard code the development credentials which are always the same.

public class Account
{
    public Uri EndPoint { get; set; }
    public String AccountName { get; set; }
    public String SharedKey { get; set; }

    public Account()
    {
        // development server defaults
        EndPoint = new Uri("http://127.0.0.1:10002/");
        AccountName = "devstoreaccount1";
        SharedKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==";
    }
}

I later I will try creating Models on the DLR, but for now I created them in a separate assembly using C#.

namespace DataModels
{
    public class PostDataModel : TableStorageEntity
    {
        public PostDataModel(string partitionKey, string rowKey)
            : base(partitionKey, rowKey)
        {
        }

        public PostDataModel()
            : base()
        {
            PartitionKey = Guid.NewGuid().ToString();
            RowKey = String.Empty;
        }


        public string Name
        {
            get;
            set;
        }

        public string Content
        {
            get;
            set;
        }

    }
}

A context is required that derives from TableStorageDataServiceContext, the field names in the context are used for table names and the type of the field describes the table row. The DataServiceContext works a bit like the LinqToSql data context keeping track of all the objects it returns.

namespace DataModels
{
    public class DataServiceContext : TableStorageDataServiceContext
    {
        public DataServiceContext(StorageAccountInfo accountInfo)
            : base(accountInfo)
        {
        }
        
        public IQueryable<PostDataModel> PostTable
        {
            get
            {
                return this.CreateQuery<PostDataModel>("PostTable");
            }
        }

        public IQueryable<PostDataModel> CommentTable
        {
            get
            {
                return this.CreateQuery<PostDataModel>("CommentTable");
            }
        }
    }
}

I wrote a generic model class to hide all the details and provide a simple wrapper to access create, read and select operations on a table. There's a couple of tests in the solution that demonstrate how this work, but basically you just need a custom context (V), a model (T) and table name. The generic model can then be used to insert, select and delete from the table.   

public class Model<T, V>
    where V : TableStorageDataServiceContext
{
    private V _context;
    public StorageAccountInfo AccountInfo { get; set; }
    public TableStorage TableStorage { get; set; }
    public string TableName { get; set; }

    public Model(Account account, string tableName)
    {
        TableName = tableName;
         AccountInfo = new StorageAccountInfo(account.EndPoint, null, account.AccountName, account.SharedKey);
         TableStorage = TableStorage.Create(AccountInfo);
         _context = Activator.CreateInstance(typeof(V), new object[] { AccountInfo } ) as V;  
    }

    public List<T> Select()
    {
        MethodInfo field = _context.GetType().GetMethods().Where(f => f.Name == "get_" + TableName).FirstOrDefault();
        if (field == null) return null; // field doesn't exist
        IQueryable<T> fieldValue = (field.Invoke(_context, null) as DataServiceQuery<T>);
        var results = from c in fieldValue select c;
        TableStorageDataServiceQuery<T> query = new TableStorageDataServiceQuery<T>(results as DataServiceQuery<T>);
        IEnumerable<T> queryResults = query.ExecuteAllWithRetries();
        return queryResults.ToList();
    }

    public void Insert(object item)
    {
        _context.AddObject(TableName, item);
        _context.SaveChanges();
    }

    public void Delete(object item)
    {
        // AttachTo is not required if the item was created by the context
        _context.DeleteObject(item);
        _context.SaveChanges();
    }
}

We've done all the C# code, now lets see how it can all be tied together in an IronPython console.

IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> # import everything we need
>>>
>>> import clr
>>> clr.AddReference("DataModels.dll")
>>> clr.AddReference("DataHelper.dll")
>>> clr.AddReference("StorageClient.dll")
>>> from DataModels import *
>>> from DataHelper import *
>>> from Microsoft.Samples.ServiceHosting.StorageClient import *
>>>
>>> # create a generic model, using the default account (development server)
>>>
>>> model = Model[PostDataModel, DataServiceContext](Account(), "PostTable")
>>>
>>> # now we can add some data rows
>>>
>>> for i in range(5):
...    post = PostDataModel()
...    post.Name = "Post Name " + str(i)
...    post.Content = "Some content for post" + str(i)
...    model.Insert(post)
...
>>>
>>> # we can now read them back
>>>
>>> for post in model.Select():
...    print "Name", post.Name
...
Name Post Name 3
Name Post Name 1
Name Post Name 2
Name Post Name 0
Name Post Name 4
>>>
>>> # delete them all
>>>
>>> for post in model.Select():
...    model.Delete(post)
...
>>>
>>> # and finally ensure they have all been removed
>>>
>>> for post in model.Select():
...    print "Name", post.Name
...
>>>
>>>

 

I'm pretty excited with how it all worked out, despite the setbacks. In future posts hopefully I'll have a go creating tables in the cloud with models and context created on the DLR. I will also try and resolve using Linq Extension Methods in IronPython which are essential to building complex queries to be executed in the cloud. I'm also writing a very simple Azure MVC weblog app which I'll hopefully finish soon.  

The project can be downloaded here and I've also uploaded just the compiled DataHelper assembly.

 

I found these links useful writing this post:

Windows Azure Essential Links

Walkthrough: Simple Table Storage

Creating Azure Tables From Script


Desktop Racer

December 16, 2008 12:10 by tarn

I've finally got around to publicly hosting my DevSta entry - Desktop Racer. Turns out it was pretty easy, I was just too burnt out by it to want to do anything with it till now.

Play Desktop Racer Now

Looking at it now, I'm a little disappointed I didn't just go a little bit further and add a two player mode as I think it would  have actually made it fun to play. But honestly after the sixth day of the competition I was so over it I didn't care.

I would like to add the two player mode and some performance improvements to make it a bit more fun to play, but I seriously doubt I'll ever get round to doing it. I'm already half way into an ASP.NET MVC weblog project and I've also suddenly become really interested in learning Python.

I'm going to upload the source as well for anyone who is interested, but I warn you its probably not a great example Silverlight application as I was just learning what was a beta technology at the time. As the competition was only 200 hours I didn't spend much time pondering what would be the best way to implement it, I pretty much just got in and started coding. Some logic is nicely packaged but some classes just ended up getting way to large and unwieldy. I've since seen some good demos and blogs on patterns to help separate out the presentation and logic.

There are some cool-ish parts in the code; I like how the level and all the level elements are defined in XAML so you can visualize the level at design time in Visual Studios. I also kind of like how the all the level elements the car can collide with implement an interface that has its geometric information.  This allowed my to simplify the collision logic to two type of geometric primitive and basically calculate and collision with all the level elements in a single loop.


Tags: , ,
Categories: Demos
Comments (0)

SharpWeblog - Iteration 1

November 29, 2008 16:28 by tarn

I've finished all the initial requirements so I'll briefly describe how its going.

The Data Layer

The data layer interface has methods to find, create, update and delete stateless model objects. The data layer is implemented with Linq to Sql. As the interface uses model data objects, the data layer implements the repository pattern by mediating these objects with the Linq to Sql classes.

This is nice as it means the rest of the application doesn't have a dependency on the data layer implementation. This is good as I don't want to have to deal with Linq to Sql classes through-out the entire application. There are tests verifying what I would consider a more sane object model is correctly implemented by the data layer.

I personally don't think Linq to Sql should be considered as an ORM for most web applications; It has no built in way of modeling many to many relationships and it's much more difficult to use than most other ORM I've worked with. I'm looking forward to trying the new Entities Framework, and hope they have finally made a legitimate ORM.

Routing

I'm a big fan of both being able to write routing logic and routing logic tests so easily. I highly recommend writing tests verifying your routes. I briefly discussed how this is done in my previous post about testing this project. The requested route is tested against all the routes in sequence until a match it found. This means its very easy to add a route that inadvertently catches a route that was supposed to be mapped by another route further down the sequence.

I think TDD is really important here as the routing can quickly get quite complicated. Adding unit tests verifying specified routes are mapped to the correct controller and actions will protect your routes. It's also generally a quicker development cycle writing some route tests and then writing the route logic than writing the route logic and testing it in the browser.   

If you insist on testing your routes in the browser or just want to see how specific are mapped in action, Phil Haack has a neat little route tester tool that renders the route test information in the browser for any URL on your site you enter.

Views

So far there has been no work done on the UI and the views are all pretty basic. I'm using C# with strongly type ViewPages, but I would like to consider using a dynamic language later in the project.

I'm a huge fan of the templated ActionLink helper method, I included the ASP.NET MVC Futures assembly without hesitation when I realised it wasn't included in the Beta.

<%=Html.ActionLink<HomeController>(m => m.Category(category),category) %>

 

I'm a little more nervously on the fence with regard to the RenderAction method which allows you to call an action on the controller from within a view to render a control. I can see the why its there; It provides a lot of flexibility for making controls that can be responsible for getting there own data and can be used by any view. This also means these user control controller actions can be tested separately. On the other hand it appears to be way to get around the MVC pattern where in many cases the controller itself could call off to get the additional information and pass it down to view.

<%Html.RenderAction<HomeController> 
(m => m.PostDetail(ViewData.Model.SelectedPost));%>

 

If I could call a view from within another view and pass it a model from the data already in the calling view I would be a lot more comfortable with it (You probably can do that, I haven't worked it out yet). That way there would be a nice way to call controls with model data without calling methods on the controller from the view.

EDIT: As soon as I tabbed to Visual Studio after posting this I noticed the login control from the template renders a user control using RenderPartial from the view. The user control inherits from ViewUserControl and can be templated. An overloaded RenderPartial method allows you to pass model data to the view. I've fallen to the lets get on with coding side of the fence.

<% Html.RenderPartial("LoginUserControl"); %>

 

Membership and Roles

It wasn't in my initial requirements, but the MVC VS2008 Beta template comes with some login in and registration pages using the default SQL Server Membership provider. I am looking to leverage all the technologies I can to build this site, so I decided I would use the default provider, if I could use it and keep the code very testable.

In the default template a database is generated with the membership and roles tables and stored procedures used by the default membership provider already created. As I already had a database, I used a tool called aspnet_regsql to add the tables and procedures to my database. The tool is part of the .NET framework and can also be used to generate scripts and works with SQL Server Express.

I had mixed emotions when I found this in the controller from the template. I liked that they had thought about testing the controller (no tests are actually included).

// This constructor is not used by the MVC framework but is instead provided for ease
// of unit testing this type. See the comments at the end of this file for more
// information.

public AccountController(IFormsAuthentication formsAuth, MembershipProvider provider)
{
    FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
    Provider = provider ?? Membership.Provider;
}

.. 

// The FormsAuthentication type is sealed and contains static members, so it is difficult to
// unit test code that calls its members. The interface and helper class below demonstrate
// how to create an abstract wrapper around such a type in order to make the AccountController
// code unit testable.

..

 

That great! Its a pattern I use in the project to avoid dependencies and improve testability, the only problem is I don't think they've gone far enough. I'm going to take it further and create a wrapper around Provider so I can mock it and not have a dependency on System.Web in my controller unit tests. 

EDIT: After writing this post I found I could reference System.Web in my tests and not have a development web server fire up when the tests run. I was a little surprised by this, and now I'm not sure what does fire up the development web server. I'll post an update on this when I understand it more clearly.   


Tags: ,
Categories:
Comments (0)

SharpWeblog - Testing

November 24, 2008 15:54 by tarn

I'm right into the coding for this project at the moment, but the iteration one requirements are all complete so its probably a good time to write some posts and reflect on what has been implemented so far.

As specified this project is use TDD for development. There has been a lot of work put into ASP.NET MVC to make it a most testable framework. I would like to discuss how various parts of this project have been tested.

I am using Microsoft Unit Test Framework and MOQ for testing this project. I had never used MOQ before, but I love it. For those that don't know about MOQ its another mock testing framework, the thing I love about it is it uses C# 3.5 so you can do a lot with lambda expressions.

Controllers

In the controller tests a real controller is created with a mocked IWeblogRepository interface. This means the controller can be tested independent of an IWeblogRepository implementation. 

[TestInitialize]
public void Setup()
{
    _mockRepository = new Mock<IWeblogRepository>();
    _controller = new HomeController(_mockRepository.Object);
}

Testing controllers is really testing two things, firstly that the controller renders the correct view and secondly it sends the right data to that view. The tests shown here validate the "Post" action on the HomeController.

In this test the mock repository is setup to return a post when GetPost("Test-Post-1") is called on it. When we call the controller with these parameters we expect it to make the specified request to the mock repository. This test ensure that when a post is found that "Post" view is rendered.  

The sharp eyes will notice that I'm not using the date parameters to find the post from the repository. That functionality has not been implemented in this iteration.

[TestMethod]
public void Post_FindsPost_RendersPostView()
{
    _mockRepository.Expect(m => m.GetPost(It.Is<string>(i => i == "Test-Post-1")))
                   .Returns(new PostModel());        
    ViewResult result = _controller.Post(8,8,8,"Test-Post-1") as ViewResult;
    Assert.AreEqual("Post", result.ViewName);
}

 

We can also test the correct data is being sent to the view. I personally like to separate these two tests, this may not be a universal opinion, but I think its best to keep unit tests short and I think these tests are clearly testing different expectations.

[TestMethod]
public void Post_FindsPost_ReturnPostViewData()
{
    _mockRepository.Expect(m => m.GetPost(It.Is<string>(i => i == "Test-Post-1")))
                   .Returns(new PostModel() {
                                                Title = "Test Post 1",
                                                Content = "Test Post Content 1"
                                            });        

    ViewResult result = _controller.Post(8, 8, 8, "Test-Post-1") as ViewResult;
    PostViewData data = result.ViewData.Model as PostViewData;
    Assert.IsNotNull(data);
    Assert.AreEqual("Test Post 1", data.SelectedPost.Title);
    Assert.AreEqual("Test Post Content 1", data.SelectedPost.Content);
}

 

Two additional test were added to test other expectation of the "Post" controller action. These test that the "Index" view is rendered when the action is called with invalid parameters or can't find the post. This functionality may change to display an error message or alternate posts when the request is invalid in later iterations.

[TestMethod]
public void Post_PostNotFound_RendersIndexView()
{
    _mockRepository.Expect(m => m.GetPost(It.Is<string>(i => i == "Test-Post-1")))
                   .Returns<PostModel>(null);
    ViewResult result = _controller.Post(8, 8, 8, "Non-Existing-Post") as ViewResult;
    Assert.AreEqual("Index", result.ViewName);
}

[TestMethod]
public void Post_InvalidRequest_RendersIndexView()
{
    ViewResult result = _controller.Post(null,null,null,null) as ViewResult;
    Assert.AreEqual("Index", result.ViewName);
}

 

Routes

Testing routes is testing Http Requests are correctly mapped to the appropriate controller actions with the appropriate parameters. The below is testing "~/Post/2008/10/20/Test-Post" request will call the HomeController with the Post action and will also correctly populate the parameters.

[TestMethod]
public void PostRoute_TestSuccessfullRoute()
{
    var routes = new RouteCollection();
    var context = new Mock<HttpContextBase>();

    context.ExpectGet(m => m.Request.AppRelativeCurrentExecutionFilePath)
           .Returns("~/Post/2008/10/20/Test-Post");

    SharpWeblogRouting.RegisterRoutes(routes);
    var routeData = routes.GetRouteData(context.Object);

    Assert.AreEqual("Home", routeData.Values["controller"]);
    Assert.AreEqual("Post", routeData.Values["action"]);
    Assert.AreEqual("20", routeData.Values["day"]);
    Assert.AreEqual("10", routeData.Values["month"]);
    Assert.AreEqual("2008", routeData.Values["year"]);
    Assert.AreEqual("Test-Post", routeData.Values["name"]);
}

 

I can write a more route tests to test other requests when I have features saying what should happen.

Data Layer

While I think its great we can "fake out" the IWeblogRepository to avoid using an actual implementation while testing other areas of the system, I strongly believe implementations of the IWeblogRepository should also be tested, separately.

The IWeblogRepository interface basically has methods to save, load, update and delete model objects in a data storage. In this case it is storing the data in a SQL Express 2005 database using LINQ to SQL.

NOTE: The model classes are just data objects that have no information about the data context or data state. This does result in some inefficiencies updating the database, but the design was chosen as it clearly separates the implementation of the data layer from the rest of the system.

Anyway here are some typical tests, no mocking required here.

NOTE: I think these tests should be written against an interface with our implementation injected in. This would mean the same tests could be applied to other IWeblogRepository implementations.

[TestMethod]
public void PostCRUD()
{
    // Create
    PostModel post = CreateTestPost();
    _repository.SavePost(post);
    
    // Read
    PostModel findPost = _repository.GetPost(post.Id);
    Assert.IsNotNull(findPost);
    ValidatePosts(post, findPost);

    // Update
    findPost.Content = "Updated Content";
    findPost.Title = "Update Content";
    _repository.SavePost(findPost);

    // Read Update
    PostModel findUpdatedPost = _repository.GetPost(post.Id);
    Assert.IsNotNull(findUpdatedPost);

    // Delete
    _repository.DeletePost(findUpdatedPost);
    PostModel findDeletedPost = _repository.GetPost(post.Id);
    Assert.IsNull(findDeletedPost);
}

 

While I generally like small tests, I think an objects CRUD tests are best tied up in one test because otherwise you end up testing "create" four times to setup for each of the other tests. I would also generally implement the entire CRUD of an object even if it wasn't all required just so as CRUD tests can be performed and each operation can be tested.

I have many more tests for the data layer but they are all pretty standard, so no point discussing them further here.

MetaWeblog

The MetaWeblog API has also been (partly, so far) implemented for this project. I will discuss the implementation further in another post but for now we'll talk about testing it.

The MetaWeblog is implemented in two clearly separate components. One part processes the XML-RPC request and invokes methods on a IMetaWeblog interface and returns XML-RPC responses to Http Response. The other is an implementation of the IMetaWeblog, both can be tested separately.

Testing the IMetaWeblog implementation is pretty straight forward. As the IMetaWeblog implementation uses the repository through the IWeblogRepository interface we can mock the repository and test the expected calls are made against the interface.

NOTE: Sharp eyes will notice I'm not validating the user name and password. This isn't yet implemented.

[TestMethod]
public void NewPost_InvokesSaveMethod()
{
    MWAPost post = TestHelper.CreateTestMWAPost();
    Mock<IWeblogRepository> repository = new Mock<IWeblogRepository>();
    SharpMetaWeblogAPI model = new SharpMetaWeblogAPI(repository.Object);
    model.NewPost("100", "TestUser", "TestPassword", post, false);
    repository.Verify(m => m.SavePost(It.Is<PostModel>(p => ComparePosts(p, post))));
}

We can also test the return values of the IMetaWeblog methods with a known responses from the IWeblogRepository mock.

[TestMethod]
public void GetPost_ReturnsRequestedPost()
{
    Guid id = Guid.NewGuid();

    PostModel post = new PostModel()
    {
         Title = "Test Title",
    };
    Mock<IWeblogRepository> repository = new Mock<IWeblogRepository>();
    repository.Expect<PostModel>(m => m.GetPost(id)).Returns(post);
    SharpMetaWeblogAPI metaWeblog = new SharpMetaWeblogAPI(repository.Object);
    MWAPost findPost = metaWeblog.GetPost(id.ToString(), "none", "none");

    Assert.AreEqual(post.Id.ToString(), findPost.postID);
    Assert.AreEqual(post.Title, findPost.title);
}

 

Being able to unit test the MetaWeblogFramework is cool, but I may have taken unit testing too far here, but I'll let you decide.

The MetaWeblogFramework had to be implemented against HttpContextBase, with an actual context object passed into the ProcessRequest method. An instance of IMetaWeblogAPI is injected into the constructor to allow the framework to call the interface methods on a real object after processing the request, kind of like a call back or an event. 

The structure of most of tests I have written so far is to mock a HttpContextBase request and send it to a real instance of MetaWeblogFramework which has been constructed with a mock IMetaWeblog API.

This way I can verify that with known HTTP requests and payloads the expected methods on the IMetaWeblog interface are called. The test below creates an XmlRpcRequest object which the HttpContextBase mock will return when the MetaWeblogFramework ProcessRequest method requests the HttpContext.Request.InputStream. The test expects the IMetaWeblogAPI.NewPost(..) method to be called with known parameters.

 

[TestClass]
public class MetaWeblogFrameworkTest
{
    Mock<HttpContextBase> context;
    Mock<IMetaWeblogAPI> api;
    Byte[] _output;

    [TestInitialize]
    public void Setup()
    {
        context = new Mock<HttpContextBase>();
        api = new Mock<IMetaWeblogAPI>();

        _output = new Byte[1000];
        context.ExpectGet(m => m.Response.ContentType).Returns("text/xml");
        context.ExpectGet(m => m.Response.OutputStream).Returns(new MemoryStream(_output));
    }

    [TestMethod]
    public void ProcessRequest_MockRequestNewPost_InvokesNewPostMethod()
    {
        MWAPost sentPost = TestHelper.CreateTestMWAPost();
        XmlRpcRequest mockRequest = new XmlRpcRequest()
        {
            MethodName = "metaWeblog.newPost",
            Params = new List<Param>()
            {
                new StringParam("TestBlogId"),
                new StringParam("TestUserName"),
                new StringParam("TestPassword"),
                new PostParam(sentPost),
                new StringParam("False"),
            }
        };
        context.ExpectGet(m => m.Request.InputStream).Returns(mockRequest.CreateStream());
        MetaWeblogFramework framework = new MetaWeblogFramework(api.Object);

        framework.ProcessRequest(context.Object);
        
        api.Verify(m => m.NewPost("TestBlogId", "TestUserName", "TestPassword", It.Is<MWAPost>(a=>sentPost.Match(a)) , true));
    }
 
    ..

}

 

Testing the MetaWeblogFramework was a little difficult, and I had to create a whole range of additional objects and methods to perform the tests. I might re-visit the MetaWeblogFramework implementation later in the project and re-write it to be more testable.

Conclusion

Well I managed to test a whole range of components in this ASP.NET MVC project, but my overall coverage is still pretty low (32% over the entire project). I'll keep you updated with how testing is going though-out the project and I'll try to get those coverage stats up by the drop of the first iteration this week.

 

image


Tags: , , , ,
Categories:
Comments (1)

SharpWeblog Project

November 21, 2008 14:47 by tarn

Introduction

I've just started a small project building a simple weblog site using ASP.NET MVC. I know there are heaps of blog sites out there but I thought it would be a good project to get familiar with ASP.NET MVC, JQuery and Silverlight 2.

I don't like writing about projects I'm going to build, but I'm hoping I can get a couple of the guys from work involved to share the learning and the work. I'm also going to hassle a few graphic designers I know and try to get little free consulting and maybe even some design work.

It will be used it to drive this blog instead of BlogEngine.NET which we are currently using.

To keep things simple the project will use the database schema and parts of the Metaweblog API implementation from the BlogEngine.NET project. LINQ to SQL will be used to quickly get some ORM mappings to the database schema. It will also use the standard ASP.NET Membership and Roles providers for SQL Server. Some Silverlight 2 will be added for some cool menus and navigational controls.

Tools, Technologies and Methodologies

The project will use TDD, Agile methodologies and identify design patterns where appropriate.

For now the code will be hosted on our internal Subversion server, but I would like to move it CodePlex eventually. I will move it sooner if anyone else is interested in checking out the code or contributing to the project. I would like to use a build machine, but I'm not sure if there is support for this at CodePlex, but we'll find out.

The project will be developed with .NET 3.5 SP1 and ASP.NET MVC Beta. The Microsoft Unit Test framework will initially be used for unit testing but a Mock Testing framework may be introduced later.

The project should be able to be run and debugged using the Visual Studios internal development web server and SQL Server Express, basically by pressing F5 after checking out the code.

Initial Requirements

In agile fashion the project will start with some initial requirements, additional requirements can be added as the project evolves.

  • A default or index page showing recent posts in reverse chronological order
  • A post page, using the same URI routing as BlogEngine.NET
  • A Metaweblog API implementation to support Windows Livewriter for publishing and managing content on the weblog

So that's it for now, hopefully we can knock this first iteration together pretty quickly.

Tasks

I don't want to get to far into fine grained tasks as I don't have to estimate the project time or cost, but I do want to cover the basic tasks as it does give an indication of what I expect will need to be done for this phase.

  • Create the database
  • Create the LINQ to SQL classes
  • Create a Data Layer and a Data Layer Interface
  • Write some Data Layer Tests
  • Create a Model (tests?)
  • Create a Controller
  • Write some Controller Tests
  • Setup some routes
  • Create the index view
  • Create the post view
  • Implement the Metaweblog API

Lets Rock'n'Roll

Hopefully I'll be posting the learning from phase one and the goals of phase two next week.


Tags: ,
Categories:
Comments (4)

Command Line Arguments

October 21, 2008 11:28 by tarn

I still write heaps of little console applications to do all sorts of things. Most of the console applications I write are tools for tasks like deployment, manipulating data and processing images. Usually they are for my own use, if I find one really useful I might pass it on to the rest of our development team or publish it on this blog. 

For these little tools, I prefer using console applications over windows application as I feel they are more useful. Even though its easier to use a tool that has a little GUI, its not more useful if you ever want to automate it.

Ideally I would prefer to write assemblies and use them from Powershell as it would provide the greatest usage flexibility. But it also requires competence scripting with Powershell. I was very excited about Windows Powershell when it was released, but a year on, I still haven't made it the integral part of my development toolset I thought it would be. This is an area I want to improve on, but this post is about command line arguments.

Generally these little non production, internal applications are quite light weight and fit for purpose. I find I often write simple logging and command line processing that is also fit for purpose. This is fine, its usually very simple, quick to write and works. The problem is that I write this same functionality over and over again for each little application.

I was toying with the idea of writing a generic command line parsing class. I figured I could use reflection on a settings class decorated with attributes describing the specific command line syntax. I figured I could even generate the help text using reflection too. While this seemed like a great idea, I am aware of time I've previously spent (wasted?) re-writing code where a perfectly good open source solution is available.

So I did a search and found a couple of existing command line solutions. Not surprisingly, given they were both written in .NET 2.0+, they both used reflection and attributes. I ended up using the Command Line Parser Library from CodePlex. I'm not sure if it does everything, but it does everything I need for 99% of the console applications I write that require command line processing.  

Anyway here is all the code from my test application:

public class Options
{
    [Option("r", "run", HelpText = "Run the export", Required = true)] 
    public bool Run;

    [Option("n", "Name", HelpText = "Use a specific name")]
    public string Name = String.Empty;

    [HelpOption(HelpText = "Dispaly this help screen.")]
    public string GetUsage()
    {
        HelpText help = new HelpText(new HeadingInfo("Hello World Example", "1.0.0"));
        help.Copyright = new CopyrightInfo("sharpthinking", 2008);
        help.AddPreOptionsLine("Usage: Hello --run");
        help.AddOptions(this);
        return help;
    }
}
class Program
{
    static void Main(string[] args)
    {
        Options options = new Options();
        if (Parser.ParseArguments(args, options, Console.Error))
        {
            string name = string.IsNullOrEmpty(options.Name) ? "World" : options.Name;
            Console.WriteLine("Hello {0}!", name);
        }
    }
}

And we get the expected usage from the command line

image

Now I have to make sure I bundle the console applications with an external assembly, but it does make using command line arguments easy.  


Tags:
Categories: Reviews
Comments (0)