Friday, June 6, 2008

ASP.NET MVC in legacy solutions (classic Web Forms)

ASP.NET MVC is new approach, when building web sites using ASP.NET. It’s still quite new and at this moment version ASP.NET MVC Preview 3 has been released. All examples in this article conform to this version.

While MVC framework is still evolving more and more people start using it even in production environment. Creating new application from scratch with ASP.NET MVC is explained in many places and won’t be covered here. The biggest challenge is to introduce new approach into existing solution and then migrate site day by day, page by page to MVC. Before describing required steps which must be taken to use classic Web Forms and MVC in parallel way some assumptions/limitations must be introduced.

Assumptions/limitations:

  • Pages using MVC controller cannot use classic Web Forms Master Page – new Master Page, which looks same as old one must be created and all changes must be synchronized in both files,
  • Classic controls which depends on post back data cannot be used – controls which does not used ViewState will work properly if tag <form runat="”server”"/> surrounds page content,
  • All links to new pages which has been rewritten to ASP.NET MVC must be updated – you may also consider using LegacyRouteHandler, which redirects user from old pages to new one.
  • It’s strongly recommended that, ale page content is rewritten to MVC – it means, you shouldn’t use classic controls together with MVC Components. Disadvantage is that it may lead to temporary duplicating functionality, but clever with refactoring code duplication is minimal.

1. Convert VS 2005 Web Project to VS 2008 Web Application

ASP.NET MVC may be used only with Web application so all solutions using Web Projects must be converted (both VS 2005 and VS 2008 projects). In details it described here, but in short:
  • Create a new Visual Studio 2008 Web application project in a new solution,
  • Add references to a Visual Studio 2008 Web application project,
  • Copy Web site project files to a Web application project,
  • Convert pages and classes to use partial classes in a Web application project,
  • Run the Web Application Project

2. Create routes definition

Routes definition defines which route handler and which controller will be invoked for specific URL. Goal of this section it to describe configuration which works for both Web Forms and MVC
  • Reference MVC assemblies: System.Web, System.Web.Abstractions, System.Web.Routing
  • Define routes in Application.Start event – notice adding “.mvc” appendix to route definition which must be handled by MVC framework. Since none of current pages/items uses .mvc extension (usually aspx, ashx) old request will be treated as old Web Forms requests.


3. Update web.config

You must add some new sections to web config to start using MVC framework. Steps below are necessary however some optional section has been omitted for clearance.
  • Add MVC assemblies to system.web\compilation\assemblies section

  • Add namespaces to pages\namespaces section

  • Add Http Handlers and Http Modules

  • If you plan use it with copy section system.webserver from default web.config for Visual Studio 2008

Saturday, April 19, 2008

Sharepoint 2007: Creating page from layout with “No parameterless constructor defined for this object” exception

Symptom

After creating page from layout “No parameterless constructor defined for this object” exception was thrown.



Description

I have created site definition using webtemp.xml. Inside site definition I have had few features activated and one of them created layouts for publishing template. Inside some I have added section for automatically adding default webparts using AllUsersWebPart element.

On development environment manually activating features worked perfect, but when I followed steps below:
• Create site based on custom site definition
• Create paged based on custom layout
I saw error like this:

No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandle& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean fillCache)
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at Microsoft.SharePoint.WebPartPages.SPWebPartSerializer.get_DefaultControl()
at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.Serialize(PersonalizationScope scope)
at Microsoft.SharePoint.WebPartPages.BinaryWebPartSerializer.get_Links()
at Microsoft.SharePoint.WebPartPages.SPWebPartManager.AddWebPartToStore(WebPart webPart, Int32 viewId, String viewGuid)
...

Semi-solution

I found that removing template from “Master page and layout gallery” and adding it manually again fixed that problem. Of course this solution may be acceptable in development environment, but cannot be used in production environment with a lot of templates.

Solution

After few hours of investigation I found that site definition didn’t register web parts as safe controls. It wasn’t easy to discover and description of error didn’t make it easier.
Now, you may ask why semi solution worked? After removing layout from gallery AllUsersWebPart section has been reseted and there were no default webparts on page.

Friday, April 4, 2008

6 steps to successful Continuous Integration

In early seventies, when computer aided projects become bigger and bigger, more independent companies were involved. After few months of development there was a special phase called integration. It was the hardest task to integrate all solutions and it wasn’t uncommon that project was successful until it suddenly fails due to integration hell.

Cure for this illness is Continuous Integration – everyone should integrate with rest not after months but continuously – each week, each day, each hour – as often as possible. This practice helps avoiding problems later. It’s so called “pay me now or pay me more later”.

To increase chance for project it should be integrated continuously. In the rest of article I will introduce 6 practices, which should be used to integrate continuously. Depending on the project and your attitude you can choose only some of described practices, but I strongly advice to fulfill preceding practices before using next one.


Establish vs. maintain cost for Continuous Integration

Chart above shows relationship between cost of initial phase and cost of work required to maintain.

1. Use source code repository

It’s first and required step to start using continuous integration. Initial cost is not so small because you need dedicated machine and backup policy for “heart of software company”. Also each developer must be aware of source control existence and install so on each machine. Consider using Svn, Cvs, Team System.

2. Introduce check-in policy

Check in policy may be introduced after establishing source code repository – quite easy to introduce but some effort is required to follow. Firstly it involves storing all necessary files in repository. Secondly, each developer should check-in as often as possible completed part of work. Frequently integration show problem early and either solution is easy or rollback is necessary for only small part of solution.

3. Automate build

Next step is to perform build automatically – no more than one action should be required to start it. If developer must do more things than he forgets about it or deliberately skips it to save time. Perfect solution is when after each commit build is automatically triggered. Cost of using it is very small after establishment so I strongly advice to use it in all projects.
Consider using Nant, Msbuild for scripting build process and CruiseControl.Net, Microsoft Team System or Team City as Continous integration server.

4. Create auto-deployable test environment

After each build new version of binaries should be automatically deployed to test server. It helps improving better integration with customer – after each fix customer may verify new version. Some work is necessary at the beginning but it’s really worth this effort in later phases of project.

5. Use code quality analysis

Using code analysis is very important in big project with many developers. It helps preserving coding conventions and constantly monitors code. If any time some suspicious code is committed warning should be generated. It differs from code reviews, because here approval or disapproval must be done automatically. Trigger for generating warning should be adjusted for each project or for whole company. Consider using NDepend, FxCop, Simian

6. Use unit test

Although I’m a big fan of XP and TDD I must admit that this is the most time consuming practice. At the beginning it requires reasonably small amount of effort, but when project goes on more and more time developers spend on writing, refactoring and verifying test cases. Only some companies can reach this level of maturity and can enjoy all advantages of continuous integration. Consider using NUnit, Team System Testing, TypeMock, RhinoMock, NMock and many others.

Tuesday, March 18, 2008

Encoding mailto in hyperlink against spam bots

Scanning pages for hyper link with mail
On almost each html tutorial you can find how to create link, which openes user's default mail application.


Don't do that
- after creating such page, your mailbox will contain almost only spam e-mails.

Solution 1 - creating dummy human readable address
You can paste on your page:


Yes - it's working, but do you really want place it on your company site. Imagine link on home page: "Contact our consultant - send sales_at_professional_REMOVE_IT_company.com" - actually it does not seems to be very professional.

Solution 2 - encode with javascript
Concept: Instead of creating


Create on output page with javascript encoded email - spam-bots does not parse javascript, so email will not be properly generated:


In browsers supporting javascirpt it will be displayed as earlier, because document.write is processed immediately after loading:

Steps:
  1. Import javascript decode64 function


  2. Create ASP.NET filter which finds all occurences of hyperlinks with mailto:


  3. Replace all occurrences with javascript which produces document.write in javascript


  4. Add configuration in web.config


Monday, March 17, 2008

Publishing Web Application with MsBuild



Visual Studio 2005 has features that can used to publish a website in a production server or a staging server.When you compile files using the Publish Web Site utility the source code is removed. The marked up code in the .aspx files can also be removed optionally. After compilation the .aspx pages point to the compiled versions. With this feature the source code of your pages are safe. Accessing your code by others is difficult. This is one of the features that are more useful for those who want their code to be safe.

Question is how to automate it?

1. Add target to .csproj file
Ensure your web application project contains :

2. Call hidden task _CopyWebApplication
Call task from msbuild:


3. Resolve references to other projects
Unfortunatelly task _CopyWebApplicaiton does not copy output from referenced project so you have to do it manually by calling ResolveReferences task



Update: Publishing Websites with cascade dependency (2009.02.03)

It's quite common that you have project structure like on image below. Web site on top of Business Logic Layer, which is on top of Data Access Layer.

Unfortunately, solution posted above does not solve second degree references (references of references) and therefore. When project is built with code above only first degree are propery copied to output directory.


In order to configure all degree references to be copied you have to specify both
  • WebProjectOutputDir - where website will be published
  • OutDir - where all assemblies should be placed (bin folder>

In MsBuild script you can use snippet as below:

<MSBuild Projects="WebApplication\WebApplication.csproj"

Properties="Configuration=Release;WebProjectOutputDir=..\build\Release\Web\;OutDir= ..\builda\Release\Web\bin\"

Targets="ResolveReferences;_CopyWebApplication" />


Thanks to Maciej Grzyb for solution http://maciek79.secondbrain.com

Friday, February 29, 2008

Configuring Cruise Control .Net with MsBuild and email notification

Best scenario should
  • Easy to maintain - no extra developer effort should be required
  • Easy to extend - time to time it happens that custom action must be performed during build process
  • Build failure results should be accessible - via mail and on dashbord to decrease time spent looking for error
Possible build scenarions
There are few build scenarios, that could be used with CCNET:
  • Visual studio batch mode
  • Nant compilation
  • MsBuild compilation
I'm going to go fast through first two, and later focus on most suitable ble for me sollution - using msbuild.

Using Visual Studio batch mode
The easiest and fastest to establish way to compile projects is usage of Visual Stuido command line
Adventages:
  • Easy to establish
  • No developer effort required after enviroment configuration
Disadventages:
  • Error report is generated only on local disk, so it's hard for developer to check why it does not compile in build enviroment
  • Standard mail contains only changed files listing
Standard DevEnv configurationMail for devenv task

Using Nant
Nant is another common tool used for building solution, by for me it's biggest disatventage is so uge, that it discards it.
Adventages:
  • Very extensible with plenty of custom task available
  • Tested in Java enviroment
  • Possible to include results in mail
Disadventages:
  • Each developer has to update build script after adding
    • project
    • file to project (it's possible to include **/*.cs but what about *.xml files or not included files)
  • Not so easy to configure first time
For me, forcing developer to update build script is both unsecure and errorprone. In big build enviroments only build master should be resposible for build process. Also it's not obligatory for every developer (like CSS front side developer) to have knowledge about Nant syntax. Mistakes made in build script will fail build process what we should avoid like fire.

Using MsBuild
For me it's most suitable solution and I would strongly recomend it for teams which have quite common build scenarios. In case of some sofisticated build process extension is also possible.
Adventages:
  • Possible to include build results in mail
  • Extensible
  • Easy to maintain - no extra developer effort is required
Disadventages:
  • Takes some time to configure
MsBuild configuration
Follow the instructions from ThoughtWorks blog. They have introduced improved MsBuild logger.
  1. Copy Rodemeyer.MsBuildToCCnet.dll to your \CruiseControl.NET\server folder
  2. Copy msbuild2ccnet.xsl to your \CruiseControl.NET\webdashboard\xsl and \CruiseControl.NET\servrt\xsl folder
  3. Copy cruisecontrol.css to your \CruiseControl.NET\webdashboard folder
    • If you have modified the dashboards stylesheet, just copy the section-project, section-error, section-warning, error and warning style.
  4. In your ccnet.config file locate the task. Change the node to
    c:\Program Files\CruiseControl.NET\ server\Rodemeyer.MsBuildToCCNet.dll

    I highly suggest that you set the verbosity level to quiet or minimal to avoid excessive large log files!

    /v:quiet /noconlog /p:Configuration=Debug
  5. In your dashboard.config file locate the section. Remove the compile-msbuild.xsl and msbuild.xsl if present. Theses transformations are not compatible with the MsBuildToCCNet logger. Add the msbuild2ccnet.xsl transformation instead.
           xsl\header.xsl
    xsl\msbuild2ccnet.xsl
    xsl\modifications.xsl
    [...]
  6. Modify \CruiseControl.NET\server\ccnet.exe.config and \CruiseControl.NET\server\ccservice.exe.config add following lines to add mail sending functionality
  7. Configure project

Sample project configuration
Mail for MsBuild task
Webdashboard output