Tag Archives: ASP.NET MVC

Cuyahoga

Cuyahoga 2.0 Alpha released

Just a little post to let you know that I released the first Alpha of the next generation of the Cuyahoga CMS yesterday. For the people who don’t know Cuyahoga: it’s a .NET CMS that uses lots of Open Source components like NHibernate, Castle Windsor and Lucene.NET. Although not as polished as Umbraco or Dotnetnuke, I think it still shines when doing custom module and template development.

Development has been a long journey. Already back in 2006 we started development for the 2.0 version. In that time most of the work was done by Max Gaerber. He did a fantastic job in the design of the generic handling of content items.

Then somewhere in 2007 we started the new admin with Castle Monorail, did a spike with the first ASP.NET MVC, changed back to Monorail and finally changed to ASP.NET MVC again. The switch from ASP.NET WebForms to MVC for the site admin allowed us to do some pretty advanced AJAX stuff. The result is still a little rough around the edges, but it’s usable for experimental purposes.

Download it at http://sourceforge.net/projects/cuyahoga/files/.

O/R mapping

Entity Framework 4.0: a fresh start (with demo application)

Edited 2009-11-26: removed EF4 Feature CTP from demo package and added some code examples.

So, Entity Framework 1.0 pretty much sucks (compared to alternatives), but I’m glad to see that things have improved a lot in version 4.0 (we’ll call that EF4 from now). To see how the improvements work out, I did a quick spike that also gave me the opportunity to test some new ASP.NET MVC 2 features that I might blog about later.

What’s in it?

  • Entity Framework 4 with POCO entity objects and code-only configuration (no edmx);
  • Data access abstracted via repository interfaces;
  • ASP.NET 2 MVC for the UI;
  • Validation with Data Annotations;
  • Castle Windsor IoC container to wire the various components together;

EF4 POCO

In EF4, it’s now possible to use entity classes that don’t have to inherit from EntityObject. This allows for better testability and separation of concerns. This is how an entity looks in the demo:

public class Course
{
    public virtual int Id { get; set; }

    [Required(ErrorMessage="Course title is required")]
    public virtual string Title { get; set; }

    [Required(ErrorMessage = "Price is required")]
    [DataType(DataType.Currency)]
    [Range(10.00, double.MaxValue, ErrorMessage="The minimum price is {1}")]
    public virtual decimal Price { get; set; }

    public virtual ISet<Schedule> Schedules { get; set; }

    public Course()
    {
        this.Schedules = new HashSet<Schedule>();
    }
}

Note that all properties are marked virtual. This allows EF4 to do some magic with run-time proxy generation to allow lazy loading and change notification.

Also note that we can now easily add validation attributes (in this case from Sytem.ComponentModel.DataAnnotations). We don’t have to use those dreadful ‘buddy classes’ anymore to hold the meta-data.

Code-only configuration

EF4 now allows model-first design from the VS 2010 designer, but it can still get awkward with a lot of entities. Fortunately, the EF4 Feature CTP makes it possible to do everything in code.

So you now just create your POCO entity and add a mapping class that replaces the edmx designer:

public class CourseMapping : EntityConfiguration<Course>
{
    public CourseMapping()
    {
        HasKey(c => c.Id);
        Property(c => c.Id).IsIdentity();
        MapSingleType(c => new
        {
            courseid = c.Id,
            title = c.Title,
            price = c.Price
        }).ToTable("course");
        Property(c => c.Price).HasStoreType("money").HasPrecision(19, 4);
    }
}

Looks remarkably similar to Fluent NHibernate, doesn’t it? ;)

I’m not sure if this is the most optimal way to define the mapping, but it works. In the demo, there is a class CoursesContextBuilder that wraps the ContextBuilder from the EF4 Feature CTP where the mappings are added. It also serves as a factory for new ObjectContext instances () :

public class CoursesContextBuilder
{
    private ContextBuilder<ObjectContext> _builder;
    private string _defaultConnectionString;

    public CoursesContextBuilder(string defaultConnectionString)
    {
        this._defaultConnectionString = defaultConnectionString;
        this._builder = new ContextBuilder<ObjectContext>();
        ConfigureMappings();
    }

    private void ConfigureMappings()
    {
        _builder.Configurations.Add(new TeacherMapping());
        _builder.Configurations.Add(new CourseMapping());
        _builder.Configurations.Add(new ScheduleMapping());
    }

    public ObjectContext GetContext()
    {
        return GetContext(_defaultConnectionString);
    }

    public ObjectContext GetContext(string connectionString)
    {
        var context = _builder.Create(GetConnection(connectionString));
        context.ContextOptions.LazyLoadingEnabled = true;
        return context;
    }

    private DbConnection GetConnection(string connectionString)
    {
        // Hardcoded to SqlConnection for this demo.
        return new SqlConnection(connectionString);
    }
}

That’s all we need to get EF4 working. In theory, we can now do everything with the POCO classes and the ObjectContext that comes from the CoursesContextBuilder, but of course if we would use it this way, we are directly tied to EF again and there goes away our testability.

Repository implementation

To make sure our application code isn’t tied to EF directly, data access goes through Repository interfaces. In the demo app you can find a generic IRepository<T> interface that is implemented by an EfRepository<T> class. The EfRepository implementation uses the EF ObjectContext to perform queries and so on. Note that we added an extra IContextManager interface that the EfRepository depends on. The IContextManager is responsible for managing the lifetime of the ObjectContext that is obtained from the ContextBuilder. This way, the repository implementations don’t have to worry about creating and disposing ObjectContext instances. It’s just always always available.All specific Repository interfaces inherit from IRepository<T> and the specific implementations inherit from EfRepository<T>.

public interface ICourseRepository : IRepository<Course>
{
    void DeleteCourseWithSchedule(Course course);
    Ef4Poco.Domain.Course GetCourseWithSchedulesAndTeachers(int courseId);
    void RemoveScheduleFromCourse(Schedule schedule, Course course);
}
/// <summary>
/// Course-specific repository.
/// </summary>
public class CourseRepository : EfRepository<Course>, ICourseRepository
{
    public CourseRepository(IContextManager contextManager)
        : base(contextManager)
    { }

    public Course GetCourseWithSchedulesAndTeachers(int courseId)
    {
        // Wouldn't it be nice to have strong-typed includes?
        var query = from c in ObjectSet.Include("Schedules").Include("Schedules.Teacher")
                    where c.Id == courseId
                    select c;
        return query.Single();
    }

    public void RemoveScheduleFromCourse(Schedule schedule, Course course)
    {
        course.Schedules.Remove(schedule);
        CurrentObjectContext.DeleteObject(schedule);
        CurrentObjectContext.SaveChanges();
    }

    public void DeleteCourseWithSchedule(Course course)
    {
        // Howto configure cascade delete via code? This is a little cumbersome.
        var schedules = new List<Schedule>(course.Schedules);
        foreach (var schedule in schedules)
        {
            CurrentObjectContext.DeleteObject(schedule);
        }
        CurrentObjectContext.DeleteObject(course);
        CurrentObjectContext.SaveChanges();
    }
}

Consuming the data access interfaces

Now we have our data access interfaces in place, it’s time for consuming. This is plain simple. Below is an example of how a controller in the ASP.NET MVC app in the demo uses the interfaces:

public class TeachersController : Controller
{
    private ITeacherRepository _teacherRepository;

    public TeachersController(ITeacherRepository teacherRepository)
    {
        _teacherRepository = teacherRepository;
    }

    public ActionResult Index()
    {
        var teachers = _teacherRepository.Find().OrderBy(t => t.Name);
        return View(teachers);
    }

    [...snip other methods]
}

The demo app

You can download the demo to see what’s possible. It’s by no means a best practices example. Just a spike to test out various new technologies.

To run the demo, you’ll need Visual Studio 2010 Beta 2, the latest EF4 Feature CTP and SQL Server (Express).

Both, the web and the test project have a connection string in the config file that defaults to the .\SQLEXPRESS instance. Change that if you want to use a different instance. The database name doesn’t matter because a new database will be created the first time you run the application. Note that the reference to the EF4 feature CTP (Microsoft.Data.Entity.CTP.dll) points to C:\Program Files (x86)\Microsoft ADO.NET Entity Framework Feature CTP2\Binaries. On 32 bit machines, you’ll probably have to change that to C:\Program Files\…

Some observations

  • Entity Framework 4.0 is much, much better than version 1.0, especially for a model-first approach;
  • It’s not on par yet with NHibernate feature-wise (for example, I really miss cascade settings). Given the choice, I’d still opt for NHibernate, but it’s not a bad product anymore and I’d prefer it over LINQ to SQL at this time.
ASP.NET MVC Web development

Considering ASP.NET MVC UI controls? Learn HTML and Javascript!

Warning: highly subjective content ahead.

In the recent weeks we’ve seen several control vendors come up with toolkits that target ASP.NET MVC. Personally, I don’t see anything that might make me starting to consider picking one of these toolkits to speed up development. Why on earth would I prefer a wrapper around jQuery UI or shoehorning existing WebForms controls in MVC views?

The beauty of ASP.NET MVC is that it embraces the web as it is and this automatically involves HTML, CSS and Javascript. Don’t be afraid for that. The combination can be so powerful! Why aren’t there any large component vendors for PHP, Rails, Django etc? Isn’t it probably possible that these components are not required to do proper web development?

The control vendors seem to be targeting people who come from a Windows background that don’t want to learn HTML and Javascript, but from my experiences I can say that those people should really stick to WebForms.

ASP.NET MVC

ASP.NET WebForms and MVC together in one project

This post briefly describes a solution to mix ASP.NET WebForms and MVC in one project. You can download a sample project that might be more useful than my ramblings. Download the sample here, unzip, open with VS 2008 SP1 and hit F5.

There are lots of ‘legacy’ ASP.NET WebForms applications out there in the wild. What if you want to create new functionality or rebuild an existing part with ASP.NET MVC, but you can’t (or won’t) create a separate new project?

The simple solution is to add the default MVC folders (Content, Controlllers, Scripts, Views etc.) to the root of the web project, add references to the MVC binaries, modify web.config and add the MVC GUID to the ProjectTypeGuids in the project file. A major drawback however is that it pollutes the root of your carefully structured application. This post will show you how you can logically separate the new MVC pieces from the existing WebForms app in a single project.

Isolate the MVC bits

webforms-mvc-solution  A simple requirement: I want that all my MVC folders reside in the folder /MyMvcApp and I also want that all urls of the MVC app start with /mymvcapp. No interference with my old WebForms app please.

Area’s

About a year ago, Phil Haacked showed a concept called area’s to partition an ASP.NET MVC application. After that, Steve Sanderson came up with an improved version of the concept.

Although designed to partition an MVC application, area’s are also useful when we want to isolate our MVC application from our existing WebForms app. The solution from Steve Sanderson almost completely fits our needs, follow the link for more technical details. The only thing I removed was the usage of an Areas subfolder in the project where all the individual MVC sub-applications. Simply didn’t need the extra subfolder and url of the MVC app is closer to the physical structure.

So, I implemented area’s with a specific AreaViewEngine that can lookup views based on the area name and added the extension to the RouteCollection class to add area information when mapping routes. This is how Global.asax.cs looks:

protected void Application_Start(object sender, EventArgs e)

{

    ViewEngines.Engines.Clear();

    ViewEngines.Engines.Add(new AreaViewEngine());

 

    // Routes

    RegisterRoutes(RouteTable.Routes);

}

 

public static void RegisterRoutes(RouteCollection routes)

{

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

 

    routes.CreateArea("mymvcapp", "WebFormsMVCDemo.MyMvcApp.Controllers",

        routes.MapRoute("mymvcapp-defaultroute", "mymvcapp/{controller}/{action}/{id}", new { action = "Index", controller = "Home", id = "" })

    );

}

With the ViewEngine and routes in place, we’re able to run the MVC app from the url /mymvcapp. To make sure the WebForms url’s still work, we just have to add some ignore statements in Global.asax.cs (in our case, exclude .aspx and .ashx from routing):

public static void RegisterRoutes(RouteCollection routes)

{

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.IgnoreRoute("{*allaspx}", new { allaspx = @".*\.aspx(/.*)?" });

    routes.IgnoreRoute("{*allashx}", new { allashx = @".*\.ashx(/.*)?" });

    routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

 

    routes.CreateArea("mymvcapp", "WebFormsMVCDemo.MyMvcApp.Controllers",

        routes.MapRoute("mymvcapp-defaultroute", "mymvcapp/{controller}/{action}/{id}", new { action = "Index", controller = "Home", id = "" })

    );

}

One caveat: when performing the request for /mymvcapp without controller name (and action), the Default.aspx that comes with the MVC projects was loaded, but area’s seem so cause a problem with the default one. Instead of rewriting the url from ‘default.aspx’ to ‘/’, I had to rewrite to url to ‘Home/Index’:

public partial class _Default : Page

{

    public void Page_Load(object sender, System.EventArgs e)

    {

        string pathToRewriteTo = Request.Path.ToLowerInvariant().Replace("default.aspx", "Home/Index");

        HttpContext.Current.RewritePath(pathToRewriteTo, false);

        IHttpHandler httpHandler = new MvcHttpHandler();

        httpHandler.ProcessRequest(HttpContext.Current);

    }

}

I’m under the impression that I’m missing something very simple, but couldn’t get my fingers behind it, so if you know it, please comment.

 

That’s it. I created a sample project with both WebForms and an MVC app in a subfolder. You can download it here.

ASP.NET MVC Web development

ASP.NET MVC bridging the gap with PHP development?

Grand_Canyon6 For a long time, there has been a distinct separation between ASP.NET and PHP developers. The platforms have been so fundamentally different and also have the surrounding cultures. Generally speaking, ASP.NET developers consider the PHP guys script kiddies with no real understanding of ‘real’ software development and the PHP guys saw ASP.NET developers as some M$ infected bunch of people that have no clue of web standards, clean HTML or how to build a proper web app at all.

But times have changed. Both platforms are moving. PHP now has a whole bunch of application frameworks (Zend, CakePHP etc.) that encourage good application design and also since PHP 5, the programming language has improved a lot. On the other hand, with the release of ASP.NET MVC, it has become much more easy to render clean HTML and we can finally leverage all the cool client-side toolkits that are out there without having to work around the quirks of Web Forms

So, with this movement, we see that both platforms grow towards each other. More and more developers come to have a look over the fence to see what’s happening at the neighbours place.bridge-gap

Two concrete examples:

  • I’m consulting a little at a PHP shop that is moving towards .NET. They found Visual Studio and C# very cool, but the Web Forms issues regarding clean HTML etc. made it an absolute no-go. ASP.NET MVC is what made them switch.
  • Just watched the ASP.NET MVC Mix 09 presentation of Rob Conery (Microsoft) and he showed lots of things that were clearly inspired by how PHP apps like WordPress work.
    I like this movement! As a .NET developer, I find it very refreshing and inspiring to mix and mingle with ‘the other side’. There is a lot we can learn from each other to make better web applications.