Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Revisiting CodeBetter.Canvas

A month ago I released CodeBetter.Canvas, a simple application with equally simple goals:

  • Provide developers with a starting point for new ASP.NET MVC projects
  • Provide developers with a learning tool for oft-talked about tools/patterns

Instead of building a full-fledge application (like another blog engine, or shopping site), I wanted to build something as close to a blank canvas as possible – not only because it made the task more managable for me, but also because I thought it would be a better way to learn, and a more practical application for developers to use as a launching pad for their own real projects. While being an MVC application, the focus is more general: namely proper use of dependency injection, leveraging NHibernate/FluentNhibernate/Linq2Nhibernate, unit testing and mocking, and jQuery.

Yesterday I released an updated version of CodeBetter.Canvas to Google Code. You can check it out at http://code.google.com/p/codebettercanvas/. There are a number of new things in this release, including a revamped repository model, the introduction of a model binding framework (these end up doing a lot of heavy lifting), an improved validation framework, and ideas on how to do paged lists.

Enjoy.

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

14 Responses to Revisiting CodeBetter.Canvas

  1. What do you think of using OnAuthorization instead of OnActionExecuting? That way it will work with AuthorizeAttribute.

  2. Travis says:

    Any chance of you implementing this? http://www.codeplex.com/CommonServiceLocator

    It would make dropping in a different container (StructureMap) a lot easier.

  3. Colin Jack says:

    @Roberto @Karl
    My current solution, and this is very early days, is to copy the rules from the domain model to the view (or in our case REST contract) model. The way we’re doing it is essentially 3 steps:

    1) Take the information that specifies how to map from the view model to the domain model
    2) Ask the domain model for the list of rules its applying
    3) Use the outputs from 1 & 2 to work out how to apply the rules to the view model instead of the domain model, so basically your “mapping” the rules.

    The secret sauce is PostSharp, essentially you attribute your view model using something like this:

    [MapValidationRulesUsing(RuleProviderType = “Security.Domain.GroupRulesProvider, Security.Domain”)]
    public class GroupContract : IValidatableContract

    MapValidationRulesUsing is a PostSharp attribute and its responsible for running the three steps I’ve described then applying the rules to the view model. It does this by copying the rules over and mapping them, so maybe our StringNotEmptyRule was applied to Customer.Name.First in the domain and its copied to run on CustomerViewModel.FirstName. Its more difficult with attributes but I’m working on that.

    * Circular Dependency *
    However its far than perfect, notice that RuleProviderType is a string.

    Why?

    Well take the concrete example above, GroupContract is in a project called ServiceContract and GroupRulesProvider/Group are in a project called Service. The Service project references the ServiceContracts one, which is fine.

    However we now have a dependency from the ServiceContract to the Service project (obviously). How can we copy rules from a (domain) class in the Service project to a project in ServiceContract using PostSharp if ServiceContract needs to build before Service does?

    It would work fine if PostSharp ran after the entire solution had built, but it doesn’t. So if I clean the solution and build then when PostSharp tries to run on the ServiceContract project it will fall over because the Service project wouldn’t yet exist.

    My “solution” is to PostSharp run as a post build task on the Service project, telling it to run against ServiceContract. Not tried this yet but the author of P# has indicated it should work.

    I’m not sure if this is a hack too far yet….

  4. karl says:

    Roberto:
    I’ve struggled with that exact issue. I end up duplicating my validation attributes which is a huge NO-NO. Its one of the reasons I made the Credentials a component, so that you could use it as a ViewModel without dragging in the entire User Model.

    My only thought on this (so far) is to use a Fluent Validation framework (there’s at least 1 really good one for .NET) and use to properly manage duplicate validation rules.

    We’ll see…

  5. Oops.. plese disregard the last line of that comment! Apparently it needed some additional editing.

  6. @Karl,

    What I meant was, how would you deal with validation when you have a ViewModel pattern in place?

    Context:

    I assume that we can call your Credential, and User entities the Model, in most sample apps I have seen recently the Model’s don’t get pushed out to the View there is always a middle man the ViewModel that represents the specific data that your View needs. In the Canvas the attributes for validation are assigned to the model and I agree that this is the right place for them but if we follow the ViewModel pattern those attributes would not be accesible to the View.

    I assume that we can write a property in our ViewModel that would translate/expose the validation rules in the Model to the ViewModel.

    Regards,

    Roberto.-

    would reside in a model (Its definitely where they should be), but the UI sees a ViewModel that is a buddy object that is

  7. karl says:

    @Andre:
    I might write some documentation, but the code is meant to be bare enough to be understandable. I can see how some of the concepts might be very obscure depending on your experience. For example, the indirection introduced by a Dependency Injection framework might make some things seem awfully magical. And of course, if you aren’t at all familiar with NHibernate, all of that might be pretty strange.

    Was there something in particular I should focus for documentation/helping people get started?

    @Roberto:
    Not sure I’m following you. Isn’t that what I have? Attributes on domain models which generate javascript validation code?

  8. Hi Karl,

    Have you thought about working in an implementation of the ViewModel pattern into the Canvas. I would love to see a working example on how to handle mapping validations that are assigned as attributes to your model to a viewmodel for a specific controller.

    Regards,

    Roberto.-

  9. Andre Carrilho says:

    Hi Karl

    I managed to install TortoiseSVN, thanks for the tip. Is there any documentation on how to use your project or just to understand it? I’m working on a project that I want to put in MVC and I’m in need of some guidance and some good patterns that, I think, your project will provide.

    Thanks in advance

  10. karl says:

    Andre:
    Google code uses Subversion. You’ll need a subversion client. You can find a list at http://subversion.tigris.org/links.html#clients (most are free).

    Most people use TurtoiseSVN (free) – it integrates with the Windows Shell. If thats a bit too much for you, try one of the stand-alone client on that page. Once installed, you simply do a checkout from:
    http://codebettercanvas.googlecode.com/svn/trunk/

    This is a great opportunity to learn about Subversion for you!

  11. Andre Carrilho says:

    Hi

    I would like to see and use your project. I’ve never worked with google code so I could download your project to my computer?

    Thanks

  12. karl says:

    Gary:
    Validation has been moved to the binders, it feels better (largely because don’t mind feeding an IUserRepository into a binder as much as I do into a model). It also gives me that sense of trusting my code – once an entity is passed the user input boundary, the system doesn’t have to keep checking validity at each level. On the flip side, you get far worse re-use.

    All that to say that it isn’t being used. I should have taken it out. Or maybe have the base model binder check for it and call it – in the case where validation does make sense at the entity level.

  13. Gary Brunton says:

    Karl, I’ve just taken a few minutes to look at your project so please forgive me if I’m missing something but I don’t see how your using the IValidate interface. In your other example the User entity inherited directly from it but that is not the case here.

    I’m I missing something obvious?

  14. Karl – great idea in keeping it close to a blank canvas… I checked out the code and for me it does make it easier to learn the patterns you are espousing. Timely too… I’ve been looking for good repository examples using Fluent NH. Thanks.