My DSL experience

Posted March 20, 2010 by Nieve
Categories: Fubu

Tags: ,

A couple of days ago my recent pull request for FubuMVC has been accepted- a feature I’ve been working on that allows registering through conventions the partial view that would be used for a certain partial model. This meant writing some DSL which was a first time for me.

In case anyone stumbles upon this entry and wants to find out more about what is DSL and how to do it properly, I will recommend you to head straight towards Jeremy D. Miller’s thorough article on the subject.

My target was simply to allow the developer to write

 types.For<MyPartialModel>().Use<MyPartialView>();

In order to do that I added the following:

  1. IPartialViewTypeRegistry
  2. IPartialViewTypeBindingExpression
  3. IPartialViewTypeRegistrationExpression

The registry would register each partial model type to its partial view type, the latter being a page (implementing IFubuPage). At first I had my registry containing also the For method which passed the partial model type and returned a binding expression which contains only the Use method so that the user could only tell the registry to use the view for the model (so that the Use method was ‘void’).

Afterwards I added the registration expression in order to hide the registry interface. The registration expression contains only the For<TPartialModel>() method.
Inside the FubuRegistry I added then the following method:

public void RegisterPartials(Action<IPartialViewTypeRegistrationExpression> registration)
 {
 var expression = new PartialViewTypeRegistrationExpression(_partialViewTypes);
 registration(expression);
}

That way, the IPartialViewTypeRegistry instance (the _partialViewTypes field) is completely hidden.

Advertisements

Redirecting in Fubu

Posted March 6, 2010 by Nieve
Categories: Fubu, MVC

Tags:

This is a very straight forward post, just a reminder of how do you redirect and transfer in FubuMVC.

Using the FubuDinner example, we have a registration page, and its GET action:

public RegisterModel Query(RegisterModel input)
 {
 input.PasswordLength = _settings.MinPasswordLength;
return input;
}

Now, in our POST method we’d like to log on the user and redirect to our Home page if the registration went ok (validated and persisted); however, if the registration wasn’t validated, we’d like to get back to our registration page, display the error messages and keep the data the user has entered.

This is how the POST method would look like than:

public FubuContinuation Command(RegisterForm input)
 {
 var errors = _validator.Validate(input);

 //TODO: need unique username validation

 if( input.Nerd.Password != input.ConfirmPassword )
 {
 errors.RegisterFailure("ConfirmPassword", "Confirm password must match password exactly.");
 }

 if( errors.IsValid())
 {
 _repository.Save(input.Nerd);
 _authContext.ThisUserHasBeenAuthenticated(input.Nerd.Username, false);
 return FubuContinuation.RedirectTo(new HomeModel());
 }

 return FubuContinuation.TransferTo(new RegisterModel { Errors = errors, Nerd = input.Nerd, ConfirmPassword = input.ConfirmPassword });
}

Simples!



FubuMVC Behaviours

Posted February 21, 2010 by Nieve
Categories: Fubu

Tags:

In an old post Mark Nijhof talked about the way Fubu can handle different concerns of your website. He explains that with Fubu we can add ‘behaviours’ in order to get certain data that needs to be displayed on certain pages in certain contexts; in other words different concerns could be treated in different places.

Suppose we want to display the list of the most recent posts of our blog. First, we should have an interface for all of our ViewModels that would have to render the recent posts list:

public interface IRecentPostsModelBase
 {
IList<Post> RecentPosts { get; set; }
}

and each view model that would need to display these posts would implement our interface.

 public class OutputBehaviour : BasicBehavior
 {
 private readonly IFubuRequest _request;
 private readonly IPostRepository _postRepository;

 public OutputBehaviour(IFubuRequest request) : base(PartialBehavior.Ignored)
 {
_request = request;
 }

 protected override DoNext performInvoke()
 {
IRecentPostsModel recentPostsModel = null;
foreach (IRecentPostsModel model in _request.Find<IRecentPostsModel>())
recentPostsModel = model;
if (recentPostsModel != null)
{
recentPostsModel.RecentPosts = _postRepository.GetRecentPosts();
_request.SetObject(recentPostsModel);
}
return base.performInvoke();
 }
}

Now, we are going to insert our behaviour directly after the OneInOneOutActionInvoker default fubu behaviour that sets the output view model in the current FubuRequest. That way, our behaviour will be able to add/inject the recent posts into the output model view after it has been initialised, after the controller action has been invoked, but before the view has been rendered and the output model has been used:

public class MyPolicy : IConfigurationAction
 {
 public void Configure(BehaviorGraph graph)
 {
graph.Behaviors.Where(c => c.ContainsCall(a=>a.OutputType().GetInterfaces().Contains(typeof(IRecentPostsModelBase))))
 .Each(InsertBehaviours);
 }

 private void InsertBehaviours(BehaviorChain c)
 {
Wrapper node = new Wrapper(typeof (OutputBehaviour));
c.Top.InsertDirectlyAfter(node);
node.InsertDirectlyAfter(new Wrapper(typeof(MyBehaviour)));
 }
}

Inside the Configure method we’re filtering the behaviours with an ActionCall having an output type implementing IRecentPostsModelBase. The graph.Behaviors property contains a behaviour per action (ie if you have only two pages with two corresponding actions, the Behaviors property would have two chains).

Last thing we need to do would be registering our behaviour in our FubuRegistry, like so:

Policies.Add(new MyPolicy());

FubuMVC – No Strings Attached II

Posted February 8, 2010 by Nieve
Categories: Fubu

Tags:

In my last post I was talking about how stringless fubuMVC is and how it simplifies our work.

One of the points I was still struggling with was how to add a convention to add a certain route pattern; in other words, I was trying to figure out what was the Fubu equivalent to ASP.NET MVC’s

routes.MapRoute(
 "Default", // Route name
 "{controller}/{action}/{id}", // URL with parameters
 new {controller = "Home", action = "Index", id = ""} // Parameter defaults
);

Well, it seems that this is way more simple than I thought.

The first thing you have to do is write an interface for all your models with an Id property, something along the lines of:

public interface IIdentifiable
 {
 int Id { get; set; }
 }

Now, for each and every InputModel you wish to have the Id in the url as shown above (controller/action/Id), you’ll need to implement your IIdentifiable and then in your FubuRegistry class, you add the following:

Routes.
IgnoreControllerNamespaceEntirely().
ForInputTypesOf<IIdentifiable>(x => x.RouteInputFor(model => model.Id));

And that’s it!! Magic, isn’t it?

What I personally love about it is the fact that a) no strings, yet again, but more importantly- b) you don’t have to struggle with the much less intuitive api of ASP.NET MVC that forces you to write the more specific routes before the more general ones. Fubu api is by far more user friendly!

FubuMVC Routing – No Strings Attached

Posted February 6, 2010 by Nieve
Categories: Fubu, MVC

Tags:

Recently I’ve stumbled upon FubuMVC, and thought I should have a go at it, see what can you do with it, and more importantly see how other implementations of the MVC pattern work. After following the HelloWorld in Fubu steps, I felt I really like what I see, and thought I should try and pick it up, blogging on it on my way… If everything would work out nicely, I’m hoping to write my own site with Fubu, and share with others my experience with it 🙂

So the first thing I wanted to have a look at was the way they map (or register) their routes in Fubu, the way we in MVC do

routes.MapRoute(
 "Default", // Route name
 "{controller}/{action}/{id}", // URL with parameters
 new {controller = "Home", action = "Index", id = ""} // Parameter defaults
);

And lo and behold, Jeremy Miller has posted about the subject. Now, I really like the fact that you can simply have a [RouteInput] attribute on your InputModel property, and that’s all it takes to tell the URL to end with “/{Id}”; that way, if you have the IputModel and the controller action

public class ProductsInputModel
 {
 [RouteInput]
 public int Page { get; set; }

 public ProductsInputModel(int page)
 {
 Page = page;
}
}

public class ProductsController
{

public ProductsViewModel List(ProductsInputModel model)
 {
//use model.Page to get your products list of page number X
}

}

then the url /products/List/4 will get you to the 4th page of your products list.

This, by the way, could be also achieved with the QueryString attribute, which as its name suggests, would put this data in your url as a query string like so: /products/List?Page=4

However, using attributes should come only after the convention (that is for exceptional occasions), and that’s something I still need to figure out. Doh’!

Now, what Jeremy was saying in his post (in a nutshell), is that the Fubu equivalent to ASP.NET MVC

Html.ActionLink("ActionName", "ControllerName", routeObjects)

uses no strings whatsoever, but simply uses the conventions. If we use an input model per action, we simply call

UrlRegistry.UrlFor(new ProductsInputModel(4)); 

How cool is that?? Working with ASP.NET MVC I can definitely say that this approach could have made a HUGE difference. One of the things I dread the most is renaming an action name or a controller.

Get your entity rather than the proxy

Posted February 2, 2010 by Nieve
Categories: nhibernate

Tags:

A small problem we’ve encountered today- this is truly basics, but you can never know, this might serve me or someone at some point. One of my colleagues was trying to figure out why was his UserRepository.Get(id) method was returning him a proxy rather than a proper User. He was trying to determine what sort of user is it after getting it to know what should he display, and since a proxy was returned, none of the conditions were met (we have other sub-user classes and tables derived from the User class).
It turned out that he was calling during the same lifespan of his session another method that gets another entity which references his User (say Demand.User) and since by default NH gets us a proxy, the session returned to him what it had in his cache.
What we did was quite simply add the method DemandRepository.GetDemandWithUser(id), eagerly fetching the User property, which looks in NHibernate.Linq (old version- 1.1 as far as I remember) like that:

 return Session<Demand>().Expand("User").SingleOrDefault(d=>d.id == demandId);

Why do they need celebrity developers? (Us vs. Them)

Posted February 2, 2010 by Nieve
Categories: ALT.NET

Tags:

A week ago or so Roy Osherove has posted about celebrity developers and why do we need them. While generally speaking I more than agree with him, there’s just one point I thought I should add – I thought it could shed some light on the subject if the argument was coming from someone who needs celebrity developers rather than being one… I’m definitely in a position to say that the more well known developers blogs did and still do have a great impact on my day to day work/professional life. I can say that it was the blogs of Ayende and Udi that really got my curiosity going to discover as much as I can about the OSS community, the ALT.NET one and more generally speaking how to better myself as a developer, how to be on the look constantly for other ways to do things, especially ways to write a better, more efficient code. Beginning my career in a very small company where no practices were being followed and OOP was something no one knew about (and that was only 4 years ago), these blogs were a very important source of educational information, that at the time I couldn’t get anywhere else, especially working in an area where the .NET community is far from being well developed. So to conclude, since I can still consider myself in many aspects a ‘junior developer’, I can definitely say that celebrity developers are capable of at least encouraging younger ones to become more curious and passionate about what they do, if not teach them how to be a better developer.