Null !== Steve

Steve Gentile's Tech Blog – Thoughts and Musings

Archive for the month “March, 2008”

OCP Example

Agile Joe (Joe Ocampo) has a good post on the ‘Open Closed Principle’:

“The open closed principle is one of the oldest principles of Object Oriented Design. I won’t bore you with the history since you can find countless articles out on the net. But if you want a really comprehensive read please checkout Robert Martin’s excellent write up on the subject.

The open closed principle can be summoned up in the following statement.

open/closed principle states “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”;[1] that is, such an entity can allow its behavior to be modified without altering its source code.

Sounds easy enough but many developers seem to miss the mark on actually implementing this simple extensible approach. I don’t think it is a matter of skill set as much as I feel that they have never been taught how to approach applying OCP to class design.”

Read the full post here.


Partial page updates with jQuery and MS MVC

Just a quick and dirty, as I’m not going to go into all the details of neither jQuery nor MS MVC.  But I wanted to show a easy way to use jQuery to get ajax callbacks with MS MVC.

In my View I have a select tag as follows:

<%= Html.Select("selectList", ViewData.AirSummaryList, "PilotName", "ID") %> 
 

This is data that is bound to the list.  In the header of the View I have a call setup to make the ajax call:

$(document).ready(function(){
          $("#selectList").change(function(e){
               $("#selectList option:selected").each(function(){
                    var t = $(this).text()
                    $.post("/Home/AJAXTest", {
                        content: t
                    },function(txt){
                         $('#showResults').html(txt).show();
                    });


            });
          });
      });

The “/Home/AJAXTest” is a call to the HomeController and the AJAXTest action.  Content ‘t’ is the data being passed to the action:

public void AJAXTest(string content)
        {
            PassThroughData data = new PassThroughData();
            data.Name = content;
            RenderView("ViewUserControl1", data);
        }

I have created a new ‘MS MVC User Control’ and the data will be sent to this ‘control’ and rendered inside the ‘showResults’ div (see javascript above), as well as a structure to pass the data with (I prefer this route):

public partial class ViewUserControl1 : System.Web.Mvc.ViewUserControl<PassThroughData>
    {
    }

    public struct PassThroughData
    {
        public string Name{get;set;}
    }

With the ViewData being set to ‘PassThroughData’, inside the control’s view it’s easy to display the data:

Hello <%= ViewData.Name %>

I like this way of handling callbacks with MS MVC.  jQuery makes it fairly easy to use as well.

Note: you can use a ‘get’ as well :

 

$.get("/Home/AJAXTest", {
                        content: t
                    },function(txt){
                         $('#showResults').html(txt).show();
                    });

Also, just to show how your view could continue to use jQuery, inside the view that is loaded via the callback:

<script type="text/javascript">
$('#selectedPilot').click(function()
                        {
                           alert($(this).text());
                        });
</script>
<div id="selectedPilot"><i>You have selected</i> <b><%= ViewData.Name %></b></div>

Notes on running MS MVC on IIS 6 and migrating to MS MVC from Webforms

I took some steps to see how well MS MVC would coexist with Webforms on a hosted environment.  One of the things I really like about the new MS MVC is the ability to be run inside the same project/web application as webforms.  This will allow for a migration plan vs. just a complete total rewrite.

The first step was to add in the 3 assemblies required.  The assemblies in preview 2 were separated from the System.Web.Extensions, these assemblies are:

System.Web.Mvc (dependent on Routing)
System.Web.Routing (dependent on Abstractions)   <— note: this can be used outside of MS MVC
System.Web.Abstractions

Web.config updates:

Under ‘system.web’

<!-- MS MVC-->
      <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Routing"/>
        <add namespace="System.Linq"/>
        <add namespace="System.Collections.Generic"/>
      </namespaces>

Under ‘assemblies’

<!-- MS MVC -->
      <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

Under ‘httpModules’

  <!-- MS MVC -->
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

Under ‘system.webServer’

<!-- MS MVC -->
      <remove name="UrlRoutingModule"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      
<add name="MvcScriptMap" preCondition="classicMode,bitness32" verb="*" path="*.mvc" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll"/>
      <add name="MvcScriptMap64" preCondition="classicMode,bitness64" verb="*" path="*.mvc" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll"/>
      

The next steps were done to the project structure:

Added a Controllers, Views, and Models folder

Updated the Global application (HttpApplication) to add routing:

protected void Session_Start(object sender, EventArgs e)
        {
            RegisterRoutes(RouteTable.Routes);
        }

public static void RegisterRoutes(RouteCollection routes)
        {
            // Note: Change the URL to "{controller}.mvc/{action}/{id}" to enable
            //       automatic support on IIS6 and IIS7 classic mode

see the note above:  when adding routes with IIS6 and II7 classic mode, you must include the .mvc (or any unique extension).  This is important.  Your host will also need to map .mvc to the ISAPI .net.  Although, as I hope to show, you can actually just use routing to get around this.

Here are some examples of my registered routes:

routes.Add(new Route("{controller}.mvc/{action}/{id}", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { action = "Index", id = "" }),
            });

            routes.Add(new Route("{controller}.mvc", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { action = "Index" }),
            });


            routes.Add(new Route("ViewMissionSummary.aspx", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { controller = "Mission", action = "ViewMissionSummary" }),
            });

Basically, the routing will let you intercept any call to a page and route it to a controller and action!  So in the above example for ‘ViewMissionSummary’, I took an existing page in Webforms and created a new controller, action and view.

Example controller:

namespace FSWeb.Controllers
{
    public class MissionController : FSController
    {
        public void ViewMissionSummary()
        {
            ICampaignDao campaignDao = DaoFactory.GetCampaignDao();
            TargetsDestroyed targets = campaignDao.GetCampaignData();

            IMissionDao missionDao = DaoFactory.GetMissionDao();
            MissionSummaryViewData summaryData = new MissionSummaryViewData();
            summaryData.MisSummary = missionDao.GetMissionSummariesForCurrentWeek();
            summaryData.CurrentCampaign = targets.CurrentCampaign;

            RenderView("ViewMissionSummary", summaryData);
        }
    }
}

To help with binding to the view I created a new ‘MissionSummaryViewData’ struct.  As you see above, the RenderView takes the name of the view and an object ‘viewData’.  The viewData is a way to attach a specific data structure type to a view

public struct MissionSummaryViewData
    {
        private List<MissionSummary> misSummary;
        private string currentCampaign;

        public List<MissionSummary> MisSummary
        {
            get { return misSummary; }
            set { misSummary = value; }
        }

        public string CurrentCampaign
        {
            get { return currentCampaign; }
            set { currentCampaign = value; }
        }
    }

On the view code behind I tell the ‘ViewMissionSummary’ view the data type I’m going to ‘attach’ to it, ie.

public partial class ViewMissionSummary : ViewPage<MissionSummaryViewData>
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ViewMissionSummaryRepeater.DataSource = ViewData.MisSummary;
            ViewMissionSummaryRepeater.DataBind();
        }

        public static string ConvertData(object inputString)
        {
            DateTime dt = new DateTime(Convert.ToInt64(inputString));
            return dt.ToShortDateString();
        }
    }

I don’t have to do this, I can just pass key pair values, ie. ViewData["MissionSummaryView"] = missionSummaryViewData and call ‘RenderView’.  However, making it typed allows me to use intellisense and have type checks in my view!

ie.

Missions Flown:  <%= ViewData.MisSummary.Count.ToString()%>

ViewData is a struct defined above that has a List<MissionSummary> , which has a ‘count’ – this is very nice feature of MS MVC!  You might have noticed above that I still have ‘databinding’ going on in MS MVC.  My solution uses Repeaters which are ‘MS MVC friendly’ and I was able to bind my list to the repeater.

Routing

Now that we have this in place, lets talk about how the routing will work.  Just deploying the current code above, I can access my new code via the following url:

http://www.forgottenskies.com/ForgottenWars/Mission.mvc/ViewMissionSummary

This corresponds to the route:

{controller}.mvc/{action}

In my code though, this ViewMissionSummary still has a ViewMissionSummary.aspx webform page.  I want to replace it with the above MVC code.  Instead of changing all my links in my solution to point to this new url (which isn’t very friendly!) I create a new route:

routes.Add(new Route("ViewMissionSummary.aspx", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new { controller = "Mission", action = "ViewMissionSummary" }),
            });

This tells IIS that when ViewMissionSummary.aspx is requested, forward it to the Mission controller and corresponding action!

If a user selects ‘Mission’ on the menu, it will load:

http://www.forgottenskies.com/ForgottenWars/ViewMissionSummary.aspx

Which is mapped to my specified action!

One question that comes up with this is how to use querystrings in this example.  (I’m not going to cover RESTful urls right now, as I’m assuming we’re in ‘migration mode’).

A couple of updates are required:

I update the action to take a parameter:

public void ViewMissionSummary(int? id)

I made this nullable for now, as when the page initially is loaded, it will load all the summaries if id is null.  I can pass the id via the querystring as follows:

ForgottenWars/ViewMissionSummary.aspx?id=12

Presto!

Ayende on “A maintainable environment – anti corruption as a way of life”

Ayende has a post that exemplifies principles that I see as extremely important to a good development environment.

Some key points:

    • Infrastructure Ignorance – If I have to deal with my infrastructure explicitly, then I need to have developers dealing with it on a regular basis. That doesn’t mesh well with the idea of moving all the complexity to the infrastructure.
    • Fizz Buzz concepts – the code that a developer should write should be simple and easy to follow.
    • Follow good design principals – the code written should naturally lean toward single responsibility principal, separation of concerns, etc
    • Easy to figure out – It should be simpler than the alternative for any non trivial scenario. Ideally, you can explain how to solve most scenarios using this approach in half an hour or less (ignoring the infrastructure part, which may be very complex).
    • No training wheels – one of the things that drives me crazy is having two ways to do things. One for the average developer, the second for the architect. This usually comes out of putting training wheels on the first approach that make it hard to deal with in more advance scenarios. I see this as a sign of contempt for the rest of the members of the team. If you expect the rest of the team to work in a certain way, make damn sure that this is a way that this is a way that you can live with.

“The code that a developer should write should be simple and easy to follow”

There is so much about this that needs to be expounded upon. I really think the Single Responsibility Principle(SRP) is vital to this concept. I’ve seen some pretty ugly looking code all over the place where I’m at right now. Very large functions that are procedural in nature. I’d personally rather have many classes than classes stuffed with tons of code. Also, too much code in asp.net code behind pages is a major ‘no-no’. For myself, I’ve had to do much refactoring to get code back into business/presenter classes and out of the code behind. (This is one reason I like the Monorail/MS MVC approach). I could go on and on about this one.

“Easy to figure out”

Whew, amen here. Here is my code smell for this one: When you have no code in the business layer and all it is a pass through. Why do I say this ? Typically this means all the logic is in the UI or in the data layer. This is why I’m a big fan of a domain driven design with clean POCO business objects. Separation of Concerns is important here. I know it’s always debatable in the MS developer world, but when I see datasets I cringe. I think datasets tend to make developers think just in terms of the data layer. They are confusing to see the domain picture. So for me ‘Easy to figure out’ == well defined domain model.

I should add, I think creating a rules engine (IRules) and/or validation objects that can be kept away from the actual entity objects is important. This allows me to see the domain without clutter of all the rules (ie. different sets of business rules for a each client – the entity would hold a collection of ‘IRule’ objects associated to it’s particular instance)

The struggle is working in environments where principles aren’t openly discussed. I think ‘best practices’ should be complemented with developers all speaking a common language of good OO principles. On some teams I really enjoyed working with, stressing these principles made us a successful team, it was a very growing experience to me as a developer.

Ayende on "A maintainable environment – anti corruption as a way of life"

Ayende has a post that exemplifies principles that I see as extremely important to a good development environment.

Some key points:

    • Infrastructure Ignorance – If I have to deal with my infrastructure explicitly, then I need to have developers dealing with it on a regular basis. That doesn’t mesh well with the idea of moving all the complexity to the infrastructure.
    • Fizz Buzz concepts – the code that a developer should write should be simple and easy to follow.
    • Follow good design principals – the code written should naturally lean toward single responsibility principal, separation of concerns, etc
    • Easy to figure out – It should be simpler than the alternative for any non trivial scenario. Ideally, you can explain how to solve most scenarios using this approach in half an hour or less (ignoring the infrastructure part, which may be very complex).
    • No training wheels – one of the things that drives me crazy is having two ways to do things. One for the average developer, the second for the architect. This usually comes out of putting training wheels on the first approach that make it hard to deal with in more advance scenarios. I see this as a sign of contempt for the rest of the members of the team. If you expect the rest of the team to work in a certain way, make damn sure that this is a way that this is a way that you can live with.

“The code that a developer should write should be simple and easy to follow”

There is so much about this that needs to be expounded upon. I really think the Single Responsibility Principle(SRP) is vital to this concept. I’ve seen some pretty ugly looking code all over the place where I’m at right now. Very large functions that are procedural in nature. I’d personally rather have many classes than classes stuffed with tons of code. Also, too much code in asp.net code behind pages is a major ‘no-no’. For myself, I’ve had to do much refactoring to get code back into business/presenter classes and out of the code behind. (This is one reason I like the Monorail/MS MVC approach). I could go on and on about this one.

“Easy to figure out”

Whew, amen here. Here is my code smell for this one: When you have no code in the business layer and all it is a pass through. Why do I say this ? Typically this means all the logic is in the UI or in the data layer. This is why I’m a big fan of a domain driven design with clean POCO business objects. Separation of Concerns is important here. I know it’s always debatable in the MS developer world, but when I see datasets I cringe. I think datasets tend to make developers think just in terms of the data layer. They are confusing to see the domain picture. So for me ‘Easy to figure out’ == well defined domain model.

I should add, I think creating a rules engine (IRules) and/or validation objects that can be kept away from the actual entity objects is important. This allows me to see the domain without clutter of all the rules (ie. different sets of business rules for a each client – the entity would hold a collection of ‘IRule’ objects associated to it’s particular instance)

The struggle is working in environments where principles aren’t openly discussed. I think ‘best practices’ should be complemented with developers all speaking a common language of good OO principles. On some teams I really enjoyed working with, stressing these principles made us a successful team, it was a very growing experience to me as a developer.

AOP Concept : MS MVC ActionFilterAttributes

David Hayden has an excellent post on ‘ActionFilterAttributes’ with MS MVC Preview 2.  I really like this feature since it allows for cross-cutting concerns across controller actions.

It’s very easy to implement a filter and they use attributes which makes it very easy to apply to a controller action.

I am looking forward to developing with MS MVC!

On a side note, Scott Guthrie has a link to the MS MVC Source code here

Validator Toolkit for ASP.NET MVC with jQuery Client Validation

Juergen Baeurle has written a good article over at CodeProject on a validation library for MS MVC for server side . It includes using the jQuery validator library for clients side as well.

A Few Design Pattern Links for C#

A few simple examples of some design patterns in C# :

Creating a generic command pattern in C#

Observer pattern using events and delegates

MS MVC Preview 2 Screencasts by Scott Hanselman

I just viewed 2 of Scott Hanselman’s 4 available screencasts, these are very infomation.  Be sure to check them out.

The use of the helpers is very nice, and I especially like the Binding ability he discusses in video 2 along with how to use the MVC user controls.

Very informative, and even if you haven’t touched the code, it gives a good glimpse into features of the new MS MVC.

Spring.NET and DI with WebForms

Typically with a tool like Castle Windsor you have to setup the container in the Global handlers. For instance:

public class GlobalApplication : HttpApplication, IContainerAccessor
    {
        private static IWindsorContainer container;

        /// <summary>
        /// Provides a globally available access to the <see cref="IWindsorContainer" /> instance.
        /// </summary>
        public static IWindsorContainer WindsorContainer
        {
            get { return container; }
        }

        #region IContainerAccessor

        public IWindsorContainer Container
        {
            get { return container; }
        }

        #endregion

        public void Application_OnStart()
        {
            container = new WindsorContainer(new XmlInterpreter());
        }


Then on any corresponding page, you can retrieve the container, for example, I tend to create a basepage and access the factory, something like this:

public abstract class BasePage : Page
    {
        /// <summary>
        /// Exposes accessor for the <see cref="IDaoFactory" /> used by all pages.
        /// </summary>
        public IDaoFactory DaoFactory
        {
            get { return GlobalApplication.WindsorContainer.Resolve<IDaoFactory>(); }
        }


This pulls from the config to get the IDaoFactory, ie.

<components>
    <component id="primaryDaoFactory"
               type="FSData.DaoFactory, FSData"
               service="FSData.IDaoFactory, FSData">
      <parameters>
        <connectionString>#{connString}</connectionString>
      </parameters>
    </component>
  </components>

Inside the page, I would then use that factory:

IMissionDao dao = DaoFactory.GetMissionDao();

With Spring.NET’s Spring.Web this is all diverted into the configuration with no code required:

First, you setup the correct context – notice I’ve commented out the default context to instead using the webcontext:

<sectionGroup name="spring">
            <!--<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>-->
      <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
            <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
        </sectionGroup>

A description of this can be found in the Spring.NET help:

"The instantiation and configuration of the Spring.NET IoC container by the Spring.Web infrastructure is wholly transparent to application developers, who will typically never have to explicitly instatiate and configure an IoC container manually (by for example using the new operator in C#). In order to effect the transparent bootstrapping of the IoC container, the Spring.Web infrastructure requires the insertion of the following configuration snippet into each and every Spring.Web-enabled web application’s root Web.config file"

Next, you add the HttpHandler:

<httpHandlers>
      <add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
        </httpHandlers>


and HttpModule:

<httpModules>
      <add name="SpringModule" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
    </httpModules>

(Both of these are in the web.config)

Once these are setup once, you don’t have to worry about it again.

Now we need to actually use our DaoFactory in our page:

<spring>
        <context>
            <resource uri="config://spring/objects"/>
        </context>
        <objects xmlns="http://www.springframework.net">
            <description>An  example that demonstrates simple IoC features.</description>

      <object type="Default.aspx">
        <property name="DaoFactory" ref="primaryDaoFactory"/>
      </object>

      <object  name="primaryDaoFactory"
               type="FSData.DaoFactory, FSData">
        <constructor-arg name="connectionString" value="server=.SQLEXPRESS;database=dbFW;Integrated Security=true"/>
      </object>

        </objects>
    </spring>


This shows that the Default.aspx page has a dependency on ‘DaoFactory’ that will be injected into the page. I setup a property on the page:

public partial class _Default : System.Web.UI.Page
    {
        private IDaoFactory daoFactory;

        public IDaoFactory DaoFactory
        {
            set { daoFactory = value; }
            get { return daoFactory; }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            IAircraftDao acDao = daoFactory.GetAircraftDao();
            List<Aircrafts> ac = acDao.SelectAllAircraft();
        }
    }

* Update:

If you notice, I did have to add the ‘object type=Default.aspx’ above.  Well, let’s say you had a ton of pages and didn’t want to add every page in order to inject this daoFactory.  An alternative is to use a basepage class that inherits from Spring.Web.UI.Page with the following:

        private IDaoFactory daoFactory;
        public IDaoFactory DaoFactory
        {
            get
            {
                //return this.ApplicationContext.ConfigureObject(this, typeof(IDaoFactory).FullName);
                return daoFactory;
            }
        }

        protected override void OnInit(EventArgs e)
        {
            daoFactory = (IDaoFactory)this.ApplicationContext.GetObject("primaryDaoFactory");
            base.OnInit(e);
        }

Since i want the DaoFactory to be a singleton and it’s scope to be the application, I updated the config as well:

<object  name="primaryDaoFactory"
           type="FSData.DaoFactory, FSData" scope="application" singleton="true">
    <constructor-arg name="connectionString" value="server=.\SQLEXPRESS;database=dbFW;Integrated Security=true"/>

This allows me to inject the DaoFactory into every page that uses the base class (granted I’ve probably not want this code in my code behind but that is another topic…)

So there you have it – the daoFactory is injected into the page, and is accessible. I find this to be a better approach than Castle Windsor once you get through the configuration aspects. Both however, are very powerful, so if anything, this shows an alternative way of handling DI in webforms.

Side note: Curious about Spring.NET with MS MVC ? Here is an approach one programmer has used…

also http://fredrik.nsquared2.com/ViewPost.aspx?PostID=465

Post Navigation

Follow

Get every new post delivered to your Inbox.