I have been working on a ASP.NET MVC application recently. This is my first real ASP.NET MVC application, previously I have only played with it. The transition from MonoRail is overall very smooth as they are so very similar, the only thing that I found painful was the WebForms view engine which feels clunky.

I like the MonoRail Brail engine because it allows for expressions in ${} syntax which severely decreases the usage of ugly <% %> tags that sometimes can make your templates hard to read. I was strongly considering using the ported Brail engine that exists in the MvcContrib project until I read Scott Hanselman's post about a view engine called Spark.

Simple example:

<ul>
  <li each='var product in products'>
    ${product.Name}
    <div class="product-detail" if="product.HasDetail">
      ///...
    </div>
  </li>  
</ul>

This is the view engine I have been looking for! I quickly downloaded the latest release, referenced the spark assembly from my MVC application and was testing it in a matter of minutes. After reading though the documentation I was able to convert all my WebForms views into spark views in just an hour (so far very small application with not many views).

This is how one WebForm view looked like:

<% foreach (var rev in ViewData["changesets"] as IEnumerable<Changeset>) { %>
  <div class="log-entry">
    <div class="log-entry-header">
      <a href="asd" class="rev-nr"><%= rev.Revision %></a>
      &nbsp;by&nbsp;
      <span class="rev-author"><%= rev.Author %></span>&nbsp;
      <span class="rev-date"><%= rev.Time %></span>&nbsp;
    </div>
    
    <div class="rev-message">
      <%= rev.Message %>
    </div>
    
    <ul class="rev-items">    <% 
      foreach (var item in rev.ChangeItems.Where(x => x.IsRelevant).Take(5)) { %>
      <li>
        <a href="asd"><%= item.Path %></a>
        <%     
        switch (item.Action)
        {
          case ChangeAction.Added:
            Response.Write("<em>added</em>");
            break;
          case ChangeAction.Deleted:
            Response.Write("<em>added</em>");
            break;
          case ChangeAction.Replaced:
            Response.Write("<em>replaced</em>");
            break;
          case ChangeAction.Modified:
        %>    
        (+<%=item.Diff.PlusLines%>, -<%=item.Diff.MinusLines%>)
        <%= Html.RouteLink("diff", "Diff", new { 
		reposName=rev.Repository.Name, 
		path=item.Path, 
		r1=item.Diff.FromRevision, 
		r2=item.Diff.ToRevision }) %>
        <%
          break;
        }
        %>
      </li>                            
      } %>                
    </ul>    
    <% if (rev.ChangeItems.Count > 5) { %>        
    <div class="rev-items-more">
      ... <%= rev.ChangeItems.Count %> more files in <a href="asd">changeset</a>
    </div>
    <% } %>
  </div>        
<% } %>    

This is not a very nice view, if I had kept WebForms I would have rewitten this, extracted some stuff to a helper method and maybe written a UserControl. But instead I rewrote it in Spark:

<div each="var set in changesets" class="log-entry">
  <div class="log-entry-header">
    <a href="asd" class="rev-nr">${set.Revision}</a>&nbsp;by&nbsp;                
    <span class="rev-author">${set.Author}</span>&nbsp;
    <span class="rev-date">${set.Time}</span>&nbsp;
  </div>
    
  <div class="rev-message">
    ${set.Message}
  </div>
    
  <ul class="rev-items">
    <li each="var item in set.ChangeItems.Where(x => x.IsRelevant).Take(5)">
      <a href="asd">${item.Path}</a>
      <em if="item.Action == ChangeAction.Added">added</em> 
      <em if="item.Action == ChangeAction.Deleted">deleted</em> 
      <em if="item.Action == ChangeAction.Replaced">replaced</em> 
      <if condition="item.Action == ChangeAction.Modified">
        (+${item.Diff.PlusLines}, -${item.Diff.MinusLines})                    
        ${Html.RouteLink("diff", "Diff", new { 
            reposName=set.Repository.Name, 
            path=item.Path, 
            r1=item.Diff.FromRevision, 
            r2=item.Diff.ToRevision })}
      </if>
    </li>
            
    <div class="rev-items-more" if="set.ChangeItems.Count > 5">
      ... ${set.ChangeItems.Count} more files in <a href="asd">changeset</a>
    </div>                
  </ul>                  
</div>

I find this a lot easier to read and understand than the html/<% %>/C# tag soup that is sometimes hard to avoid with WebForms. I also think a view engine like this make more sense, because Spark is a view engine tailor made for only one thing, to generate html!

So if this is your cup of tea when it comes to view engines, try it out.

The boo visual studio integration project on codeplex (BooLangStudio) has been progressing nicely. I have had some time to work on it and recently got debugging working:

image

I was also able to implement the project properties dialog where standard settings like AssemblyName, Default namespace and OutputPath can be set as well as some Boo specific, like turn on or off ducktyping mode or whitespace agnostic mode.

There has also been some big improvements to the intellisense support by James Gregory. Improvements has also been made to the syntax highlighting by Olson Jeffery. The fun thing about the new syntax highlighting code is that a large part of it is written in Boo! So we are actually at the point were we are using BooLangStudio to develop BooLangStudio :)

Justin Chase has also created an installer which is great as you can now install BooLangStudio in the standard registry hive along with all your other plugins and language services. I had some free time today, and decided to try to get code outlining to work, it was quite simple to get something to work, but it is a little buggy, they keep disappearing and reappearing.

image

With some luck we might see a release sometime before the summer is over :)

It seems like some design bureaus are just hellbent on making it difficult for developers to realise their designs via html/css. I am currently trying to convert some design images into usable html/css, and in one case I had to make a box with rounded corners, all borders had a shaded shadow, the inner content had a gradient background and the box was required to handle dynamic width. The only thing that makes this tricky is that the borders and corners needs a shaded shadow and the fact that the box is required to support dynamic width.

After some experimentation I ended up with this html:

<div class="shadebox-wrapper">
  <div class="shadebox-wrapper2">
    <div class="shadebox-wrapper3">
      <div class="shadebox">                        
        <div class="shadebox-header">
          <b class="shadebox-tlc"></b>
          <b class="shadebox-trc"></b>        
        </div>            
        
        <h2>Hello</h2>
  
        <div class="shadebox-inner">
          Lorem uipsad asd asd asd as
          asdassdasd asd asd
          dasdaasd  asd asd
          asdasdsd dsd 
        </div>
    
        <div class="shadebox-footer">
          <b class="shadebox-blc"></b>
          <b class="shadebox-brc"></b>    
        </div>
      </div>
    </div>
  </div>
</div>

As you can see there is a lot of noise html that is only there to have elements to use in the css. For example the div wrappers are for the gradient background and the left, right and top borders. The corners are handled by absolute positioned "b" elements (absolute relative to the container). Although a lot of html I was actually quite pleased I managed to get it done in a short time and that it looked good in Firefox and IE7. Here is how it looked:

image

The shaded border shadow is quite subtle and can be hard to see on some monitors. Initially I wanted to use a JQuery Corner plugin because it gets you so much cleaner html but there is no one (that I know of) that supports the kind of shadows I needed. However it is very easy to manipulate html with jquery so I though I would give it a try and see how I could dynamically insert all the div wrappers and other needed elements.

This is the html I was aiming for:

<div class="shadebox">
  <h2>Hello</h2>            

  <div class="shadebox-inner">
    Lorem uipsad asd asd asd as
    asdassdasd asd asd
    dasdaasd  asd asd
    asdasdsd dsd 
  </div>        
</div>

And this is the javascript code that makes it possible:

<script type="text/javascript">
            
  $(document).ready(function() {
    $('.shadebox').wrap(
      "<div class='shadebox-wrapper'>" +
      "<div class='shadebox-wrapper2'>" +
      "<div class='shadebox-wrapper3'>" +
      "</div></div></div>");
      
    $('.shadebox').prepend("<div class='shadebox-header'><b class='shadebox-tlc'></b><b class='shadebox-trc'></b></div>");
    $('.shadebox').append("<div class='shadebox-footer'><b class='shadebox-blc'></b><b class='shadebox-brc'></b></div>");
  });              

</script>

This is by no means an optimal solution, I am not that fond of concatenating strings to generate html via javascript, but the html I have to write and maintain in template views is drastically reduced, easier to read and maintain. One downside is of course that it will not look correct if javascript is turned off, and some might not like the magic :)

Here is the CSS:

.shadebox { background: url(../_images/shadebox/shadebox-bb.gif) repeat-x bottom; }
.shadebox h2 { padding-left: 10px; color: #004684; margin: 0px;}
.shadebox-header { height: 10px; position: relative; }                
.shadebox-footer { height: 10px; position: relative; }                    

.shadebox-header { background: url(../_images/shadebox/shadebox-top.gif) repeat-x top; }            
.shadebox-wrapper { background: url(../_images/shadebox/shadebox-background.gif) repeat-x 0px 10px;}
.shadebox-wrapper2 { background: url(../_images/shadebox/shadebox-lb.gif) repeat-y left; }            
.shadebox-wrapper3 { background: url(../_images/shadebox/shadebox-rb.gif) repeat-y right; }                        
.shadebox-inner { padding: 10px; }
.shadebox-header b, .shadebox-footer b { position: absolute; width: 10px; height: 10px; }

.shadebox-tlc { left:  0px; top: 0px; background: url(../_images/shadebox/shadebox-tlc.gif) no-repeat; }            
.shadebox-trc { right: 0px; top: 0px; background: url(../_images/shadebox/shadebox-trc.gif) no-repeat; }
.shadebox-blc { left:  0px; top: 0px; background: url(../_images/shadebox/shadebox-blc.gif) no-repeat; }                        
.shadebox-brc { right: 0px; top: 0px; background: url(../_images/shadebox/shadebox-brc.gif) no-repeat; }

I think using javascript like this is is a pretty decent solution to work around the current shortcomings of html/css. But It can, as so much else, probably be overused :)

NHibernate 2.0 beta1 was release a couple of days ago, so I thought it was time to go through some more new stuff that has been added since version 1.2.  I found a new useful helper class named CritieraTransformer which can be used to clone ICritiera queries. This is very useful if you want to perform multiple queries with small variations (in the where clause for example). It also has a useful function that adds a row count projection to a query.

Example:

var customersCritiera = session.CreateCritiera(typeof(Customer));
var totalCustomersCritiera =  CriteriaTransformer.TransformToRowCount(customersCritiera);

var inGroupCriteria = 
  CriteriaTransformer.Clone(customersCritiera)
    .Add(Expression.Eq("Group", group));

var goldenInGroupCritiera = 
  CriteriaTransformer.Clone(inGroupCriteria)
    Add(Expression.Eq("IsGold", true);                          
                
IList results = session.CreateMultiCriteria()  
     .Add(inGroupCriteria)
     .Add(goldenInGroupCritiera)
     .Add(totalCustomersCritiera)
     .List();

IList inGroupCustomers = (IList)results[0];
IList customers = (IList)results[1];
IList counts = (IList)results[2];
int count = (int)counts[0]; 

The multi criteria feature allows you peform multiple database queries in a single database call, the downside is that the IMultiCritiera interface does not support generic lists.