Using the Spark View Engine with Delphi Prism

by John 8/31/2010 4:44:00 AM

I have been investigating the Spark View Engine as an alternative to the default webforms view engine inside ASP.Net MVC 2.0.

As it says on the Spark website "Spark is a view engine for Asp.Net Mvc and Castle Project MonoRail frameworks. The idea is to allow the html to dominate the flow and the code to fit seamlessly. "

While exploring the syntax and features, really liking what I saw, I decided to fork the source code available here and add support for Delphi Prism.

My fork is available on GitHub here, this is a Visual Studio 2008 solution with my additions. I also have an example project. While the modifications are in C#, the example is a Visual Studio 2010 Delphi Prism project using ASP.Net MVC 2. The views, files with the extension .spark contain Delphi Prism code. The example also contains release versions of my fork, so it isn't necessary to download the C# solution.

An example is shown below

 

<use namespace="System.Web.Mvc.Html"/>
<use namespace="OxygeneMVCApplication.Models" />
<viewdata model="OxygeneMVCApplication.Models.EmployeeViewModel"/>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>

    <table>
        <tr each="someEmployee in ViewData.Model.Employees">
            <td>${someEmployee.Firstname}</td>
            <td>${someEmployee.Lastname}</td>
            <td>${someEmployee.Age.ToString}</td>
           
        </tr>
    </table>

</body>
</html>

The code above creates a table with a number of employee records, the example is also available on my website here.

As a small example this is way more elegant than the equivalent markup using the default aspx view engine.

 

Taking a more indepth look at the sample project, there a a couple of things that should be pointed out.

 

1) At the top of the web.config I have configured spark to use Oxygene as the default language.

 

<configuration>
    <configSections>
    <section name="spark" type="Spark.Configuration.SparkSectionHandler, Spark"/>
    </configSections>

  <spark>
    <compilation debug="true" defaultLanguage="Oxygene">
      <assemblies>
        <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </assemblies>
    </compilation>

  </spark>

 

2) Spark has a rather nice pre-compilation feature which can be used to remove the need to deploy the Oxygene compiler to wherever your website is hosted. My website is hosted at DiscountASP.Net and since the Oxygene compiler hasn't been installed, I have been developing my aspx pages with the language set to C#. Using precompilation I can now develop the views using Oxygene and deploy the views precompiled as an assembly to the bin directly. This is actually how I have been able to deploy the example on my website.

The actual compilation is performed at build time using PostBuildStep.pas, views are compiled into an assembly called Precompiled.dll. This assembly is loaded at runtime. If you take a look at Global.asax.pas there is a method which makes a call to the Spark View Engine passing in an assembly reference.

method Global_Asax.LoadPrecompiledViews(engines: ViewEngineCollection);
begin
  var factory: SparkViewFactory := engines.OfType<SparkViewFactory>().First();
  factory.Engine.LoadBatchCompilation(&Assembly.Load('Precompiled'))
end;

 

The spark views in the example project exercise a number of features. At the moment I'm still exploring and fixing things as I go. I'm in the process of converting an mvc application I'm developing to Spark, things seems to be going well so I have decided to release the source I have available at the moment.

A word of warning, if you want to compile the example you will need to very latest version of the Oxygene compiler found in Delphi Prism XE.

Any feedback welcome is welcome..

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Delphi Prism | Spark | aspnetmvc

Domain Object Validation with AOP

by John 6/4/2010 7:23:00 PM

A common requirement when developing applications is the ability to validate domain objects and display the subsequent validation errors on the user interface.

One method of implementing this is through the use of the IDataErrorInfo interface. This interface expects the class to implement two properties, Error and Item

 

Shown below is a class with 2 properties upon which I would like to perform validation 

 

ClassE = public class (IDataErrorInfo)

     { Methods }
    public constructor;


     { Properties }
    public property AnotherStringProperty: String;
    public property StringProperty: String;

 

    public property Error: String;
    public property Item[columnName: String]: String read get_Item;
 

end;

 Shown below is the implementation of the get_item method

 

method ClassE.get_Item(columnName: String): String;
begin
    var str: String;
    if ((String.Compare('AnotherStringProperty', columnName) = 0) and (not String.IsNullOrEmpty(self.AnotherStringProperty) and iif((self.AnotherStringProperty.Length > 5), (self.AnotherStringProperty.Length >= 10), true))) then
        str := 'AnotherStringProperty must fall between 5 and 10';
    if ((String.Compare('StringProperty', columnName) = 0) and (not String.IsNullOrEmpty(self.StringProperty) and (self.StringProperty.Length >= 10))) then
        str := 'StringProperty must be less than 10';
    begin
        result := str;
        exit
    end
end;

In this method I have specific validation 

1) AnotherStringProperty must be between 5 and 10 characters

2) StringProperty must be longer than 9 characters.

 

It gets pretty tedious having to implement this and there are usually alot of common validation requirements that can be shared across domain objects. For example

1) String lengths

2) Numbers falling between specific ranges

 

In this blog post I will be presenting a solution to this problem using the AOP framework called Cirrus in Delphi Prism.

 

Consider an Employee object as shown below

 

  Employee=public class

  private
    method ValidateBirthDate:Boolean;

  public

    property Id:Integer;
    property Firstname:String;
    property Lastname:String;
    property BirthDate:DateTime;

    property Salary:Decimal;

    property SomeNumber:Int32;

    method IsSalaryValid():Boolean;

  end;
 

It has some basic validation requirements

 

1) An Id is required

2) The firstname and lastnames must be set

3) The date of birth must be valid

4) The BirthDate must be valid. I treated this as "complex", so the class has a method to validate this

 

Shown below is how I decorate the class with aspects using my validation framework to meet the validation requirements listed above.

  [aspect:Prism.StandardAspects.Validation.Aspects.Validation]
  Employee=public class

  private
    method ValidateBirthDate:Boolean;

  public

    [aspect:Prism.StandardAspects.Validation.Aspects.NumericHasValue('An Id is Required')]
    property Id:Integer;
    [aspect:Prism.StandardAspects.Validation.Aspects.StringNullOrEmpty()]
    property Firstname:String;
    [aspect:Prism.StandardAspects.Validation.Aspects.StringNullOrEmpty('You must fill in the employees lastname')]
    property Lastname:String;
    [aspect:Prism.StandardAspects.Validation.Aspects.ValidationMethodForProperty('ValidateBirthDate','The date of birth must be valid')]
    property BirthDate:DateTime;

    property Salary:Decimal;

    [aspect:Prism.StandardAspects.Validation.Aspects.ValidationMethod('We are not paying this employee')]
    method IsSalaryValid():Boolean;

  end;
 

Each validation aspect takes parameters to display messages in the user interface if the property fails validation. If there are requirements not met by the supplied aspects you can implement your own methods.

In the code above the method validateBirthDate is used to validate the BirthDate property. 

At compile time the IDataErrorInfo interface is implemented on the domain object. An IsValid method is also exposed and can be used in non user interface code.

The IDataErrorInfo interface is suppported in WPF, Silverlight 4 and ASP.Net MVC. Domain objects can be bound to the user interface elements, validation can be supported

and validation errors can be displayed to the user while they are editing. Shown below are screen shots of when validation has failed in each environment.

The source code for the aspects and examples can be found at the RemObjects code repository 

This is an open source project that contains a number of aspects developed using the Cirrus AOP framework for Delphi Prism.

Show below is the Solution open in Visual Studio 2010. A word of warning you will need Delphi Prism 2011 to build the solution

 

 

 

I would like to highlight several projects in the Solution. Its split between implementation and examples.

Prism.StandardAspects.Validation
base framework added to projects consuming the validation aspects
Prism.StandardAspects.Validation.Silverlight  As above but for Silverlight
Prism.StandardAspects.ValidationAspects The Aspects
   
ValidationDomain
 A domain object using validation
ValidationDomain.Tests  NUnit tests for the framework
IDataErrorInfoWindowsApplication
 A WPF application showing the domain object bound to the UI
ValidationMVCApplication
 An ASP.Net MVC application showing editing and displaying of domain objects
ValidationSilverlightApplication
 A Silverlight 4 application, with the domain object bound to the UI
   

A combination of the NUnit tests and examples should give a good starting point.

Feedback is welcome either through the comments or email.

Cheers

John

Currently rated 3.0 by 2 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Delphi Prism | Cirrus | Silverlight | AOP | aspnetmvc | WPF

Powered by BlogEngine.NET 1.3.0.0
Theme by Mads Kristensen

About the author

Name of author John Moshakis
I'm a software developer living in Toronto..

E-mail me Send mail

Calendar

<<  August 2016  >>
MoTuWeThFrSaSu
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar

Pages

    Recent posts

    Recent comments

    Authors

    Tags

    Don't show

      Disclaimer

      The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

      © Copyright 2016

      Sign in