Learn NHibernate with The Summer of NHibernate

Summer of NHibernate Screencast Series

“a series of successive screencast sessions that cover the complete use and implementation of NHibernate”

Advertisements

ASP.NET MVC and Silverlight

I’m not going to dwelve too deep into Silverlight, as I’m just learning it  šŸ™‚  But one of the things I wanted to try out was using the Silverlight WebClient capability to call a Controller action (vs. a web service, etc…).  I’m treating Silverlight as a UI presentation layer – and letting my Controller/Actions be the glue to my existing service layer/data layer.

I used Scott Guthrie’s blog post as a guide to using the WebClient capability:

http://weblogs.asp.net/scottgu/pages/silverlight-tutorial-part-3-using-networking-to-retrieve-data-and-populate-a-datagrid.aspx

A few steps:

The Action – using XmlResult

I wanted the data returned from the Action to be xml.  Luckily, the MVCContrib includes a ‘XmlResult’ (ActionResult).  If you download the source you can see what it is doing.  A brief description: “…Action result that serializes the specified object into XML and outputs it to the response stream.”  Just want I want

Here is a quick example of the action I’m using:

public XmlResult XmlSquadronStats(string SquadId)
        {
            IPilotStatsDao pilotStatsDao = DaoFactory.GetPilotStatsDao();
            var stats = pilotStatsDao.GetAllPilotSummariesBySquad(SquadId);
            return new XmlResult(stats);
        }

 

Silverlight

With Silverlight, you cannot add a ‘non-Silverlight assembly’  – so in the above, I’ll be returning a List<PilotStats> – but I can’t just include the ‘PilotStat’ class in my domain object in silverlight.  That isn’t a bad thing however, as it will help me layer my Silverlight application.  So my first step is to create a new class, which I call PilotStat (see that above article by Scott Gu, I’m just taking that same concept and applying it here).

public class PilotStat
    {
        public string PilotName{get;set;}
        public int Missions{get;set;}
        public int Flights{get;set;}
        public int Kills{get;set;}
        public int Deaths{get;set;}
        public int Landed{get;set;}
        public int GroundTargets{get;set;}
        public int Crashes{get;set;}
        public int Bailed{get;set;}
        public int Captured{get;set;}
        public int ShotDown{get;set;}
        public int TanksDestroyed{get;set;}
        public int ShipsDestroyed{get;set;}
        public int Points{get;set;}
    }

Next, I want to work with my Page.xaml – to keep it simple, I want to use a querystring to pass to the page to determine which ‘squadrons’ data I want to load in the view.  This is the part of Silverlight I do like – it’s interaction with the underlying page.  So first I want to validate there is a querystring key/pair being used:

if (!System.Windows.Browser.HtmlPage.Document.QueryString.ContainsKey("SquadId"))
            {
                Status.Text = "Please provide SquadId";
            }

Next, I’m adding some code to make it easy to deploy later (this is really simple example!)

else
            {
                string squadId = System.Windows.Browser.HtmlPage.Document.QueryString["SquadId"];
                try
                {
                    Uri uri = Application.Current.Host.Source;
                    string host = uri.Host;

                    string statsUrl = string.Format("http://{0}/ForgottenWars/Squadron.mvc/XmlSquadronStats?SquadId={1}", host, squadId);
                    Status.Text = statsUrl;
                    WebClient client = new WebClient();
                    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
                    client.DownloadStringAsync(new Uri(statsUrl));
                }
                catch (Exception ex)
                {
                    Status.Text += ex.Message;
                }
            }

Lastly, I want to display these results in the Datagrid:

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            DisplayStats(e.Result);
        }

        void DisplayStats(string xmlContent)
        {
            XDocument xmlStats = XDocument.Parse(xmlContent);
            var stats = from stat in xmlStats.Descendants("GetAllPilotSummariesBySquadResult")
                        select new PilotStat
                        {
                            PilotName = (string)stat.Element("PilotName"),
                            Missions = (int)stat.Element("Missions")
                        };
            PilotStatsGrid.ItemsSource = stats;
        }

I’m happy to report that this works well  šŸ™‚  I developed it on my Vista laptop with IIS 7 and was able to easily deploy the clientbin to my hosted IIS 6 server.

Although not rocket science here, I like the idea of being able to resuse my existing mvc architecture and adding this Silverlight UI on top of it. 

Feel free to send me any feedback on this approach!

MvcContrib – Grid – a diamond in the rough

The MvcContrib is a community driven code repository for asp.net mvc.  I’m quite impressed and hope to see more cool stuff.  The source code is available on codeplex. (check out the additional documentation here)

A couple of items from the contrib that I’m looking into:

1. UI – Grid

2. Pagination

There is some easy to read documentation on the grid as well as how it works with paging.

As you may know from reading my blog, I’m a big fan of jQuery with the asp.net mvc architecture.

The MvcContrib plays well with my jQuery table.

For example, adding sortable headers:

I use a common class for my ‘tablesorter’ jQuery implementation.

Let’s take an example from the hobby gaming website:

 

<% Html.Grid<FSData.TerritoryCaptured>(
    ViewData.Model.TerritoryCaptured.AsPagination(Int32.Parse(ViewData["page"].ToString()), 2),
    new Hash(empty => "No data available", id=>"terr1", @class=>"tablesorter",  style => "width:600px"),
    column => {
        column.For(p => p.TerritoryName, "Territory");
        column.For(p => p.CapturedBy).Formatted("Captured By: {0}");
        column.For(p => p.DateCaptured.Value.ToShortDateString(), "Date").CellCondition(p => p.DateCaptured.HasValue);
        column.For("Custom Column").Do( p => {%>
            <td>a custom column</td>
        <%});
    }
    );

     %>

In the above markup, I’ve tried to use some of the features in the documentation link above.  Keep in mind, all of this supports intellisense as you build the grid!  A few notes:  I use the @ with @id and @class – those just make sure it’s written literally (there is a conflict with keyword ‘class’ of course!)

Using the jQuery tablesorter, I’ve marked this with the class ‘tablesorter’.  (It’s easy to apply styles the grid – as it outputs a table)

In my javascript, simply add the $(“#terr1”).tablesorter(); and you have tablesorting!  You can leave out the ‘id=>”terr1″‘ and use $(“.tablesorter”).tablesorter(); (instead – this will apply the tablesorter to any class marked with ‘tablesorter’ using the jQuery css selector logic).

Sorting can be done on the server, for example:

<% Html.Grid<Person>( "people", column => { column.For(p => p.Id).Heading(() => { %> <th><a href="/People/List?orderby=id">Id</a></th> %>}); column.For(p => p.Name); column.For(p => p.Gender); column.For(p => p.RoleId); } ); %>

jQuery has a pagination ‘addin’ to the tablesorter that I use, however it’s client side only. 

I look at it this way: if I want client side functionality with my tables – it’s easy to use jQuery to achieve this.  However, in situations where I want server side paging or sorting, this grid provides a good start on providing that functionality.

I also think this grid will cut back on the amount of html I will write and yet still have absolute control on what is generates!  šŸ™‚