Click here to Skip to main content
Click here to Skip to main content

Getting the Job Done with XAF - Part 1

Tutorial on eXpressApp Framework (XAF)

Editorial Note

This article is in the Product Showcase section for our sponsors at CodeProject. These reviews are intended to provide you with information on products and services that we consider useful and of value to developers.

Introduction

What if it was really easy to develop a reasonable complex application, something along the lines of creating just a few classes and be done with it? This comes at a price, but then we all know that there is no such thing as a free lunch.

The good news is that the solution only contains 63 lines of code. Actually that's what I really want to tell you about, getting the job done with a minimal amount of work.

We are just going to create a number of Domain Object classes, no Windows Forms or ASP.NET coding, and still end up with functioning Windows Forms and ASP.NET applications.

XAFSmartBooking.png

XAF from DevExpress is a framework that allows us to create a wide range of applications with a minimum of development effort. Out of the box, it provides a lot of functionality commonly required during development of line of business (LOB) applications. XAF leverages DevExpress components for .NET, and XPO – their object relational mapping (ORM) solution.

XAFSmartBookingWeb.png

Requirements

You get XAF with DXperience Universal Subscription. There is also a free trial of the product.

Creating the Solution

A new XAF based solution is created in the usual way, using the Visual Studio New Project Dialog.

01-NewProject.png

By choosing the Applications Solution, we get a solution containing both a Windows Forms and a Web application. I think that’s a neat thing, and the initial solution looks like this:

02-SolutionAfterNewProject.png

At this point, we have to open the app.config for the Windows Forms project, XAFSmartBooking.Win and the Web.Config for the Web Application project XAFSmartBooking.Web. Uncomment the connection strings we want, then save and build the solution.

We now have a Windows Forms Application:

03-InitialWindowsForms.png

and a Web Application:

04-InitialWeb.png

It’s nice that user management is built in from the start, without a single line of code.

Creating Domain Objects

Since we are working on a booking application, we need something to book, a bookable object, if you want. Right click on the XAFSmartBooking.Module project and select Add -> New Item.

05-BookableAddNewItem.png

We create a new Domain Object called Bookable, this will be our abstract base class for bookable objects. Initially, I’d like to be able to book buildings, rooms and vehicles. So we just add the required types using the same procedure giving us a simple hierarchy structure.

06-BookableTypesClassDiagram.png

The Code

Bookable is our base domain object entity, and it's derived from BaseObject the predefined class that all XAF domain objects descends from. We define one string property “Name”, and give it a [Size(255)] attribute definition. The Size attribute is used to declare the size of the field in the underlying data storage.

public abstract class Bookable : BaseObject
    {
        private string name;

        public Bookable(Session session)
            : base(session)
        { }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        [Size(255)]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                SetPropertyValue<string>("Name", ref name, value);
            }
        }
    }</string>

Facility is the common base class for Building and Room. It also exposes a property of type PhoneNumber, one of many predefined classes from the XAF Business Class Library.

During construction, we create a new instance of the PhoneNumber class if our domain object is not in the loading state. A domain object is in a loading state if the entity already exists in the data storage, and the constructor is called during a load operation.

To facilitate saving of the phonenumber, as part of a save operation for a Facility object, we override the OnSave method, and save the phone number.

The [ExpandObjectMembers(ExpandObjectMembers.InDetailView)] attribute declaration forces expansion of the properties defined on the PhoneNumber for detail views of Facility objects.

public abstract class Facility : Bookable
    {
        private PhoneNumber phoneNumber;

        public Facility(Session session)
            : base(session)
        {
            if (!IsLoading)
            {
                phoneNumber = new PhoneNumber(session);
            }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        protected override void OnSaving()
        {
            phoneNumber.Save();
            base.OnSaving();
        }

        [ExpandObjectMembers(ExpandObjectMembers.InDetailView)]
        public PhoneNumber PhoneNumber
        {
            get
            {
                return phoneNumber;
            }
            set
            {
                SetPropertyValue<phonenumber>("PhoneNumber", 
                                      ref phoneNumber, value);
            }
        }
    }</phonenumber>

TypeBase will be used as a base class for classes used to discriminate between various types of buildings, room, and vehicles.

The [NonPersistent] attribute ensures that XAF, or rather XPO, does not create a table for this type. The Name property will be stored in the same table as the properties of direct descendants. [Indexed(Unique=true)] instructs XAF to create a unique index on the column used to store the property. The column will be unique for the descendant type, and not for instances of the TypeBase class.

    [NonPersistent]
    public abstract class TypeBase : BaseObject
    {
        private string name;

        public TypeBase(Session session)
            : base(session)
        { }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        [Size(255)]
        [Indexed(Unique=true)]
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                SetPropertyValue<string>("Name", ref name, value);
            }
        }
    }</string>

BuildingType is one of the three classes used to define discriminators for our Bookable descendants, the other two being RoomType and VehicleType.

[Association("Building-BuildingType", typeof(Building))] defines the one side of a one-to-many relationship between BuildingType and Building. The Buildings property returns the associated Building objects as a collection.

    [DefaultClassOptions]
    [NavigationItem("Facilities")]
    [ImageName("BO_Category")]
    public class BuildingType : TypeBase
    {
        public BuildingType(Session session)
            : base(session)
        {}
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        [Association("Building-BuildingType", typeof(Building))]
        public XPCollection<building> Buildings
        {
            get
            {
                return GetCollection<building>("Buildings");
            }
        }
    }</building></building>

Here is our Building class. It includes the many side of the one-to-many association with the BuildingType class, and it also uses another predefined class, Address from the XAF Business Class Library.

    [DefaultClassOptions]
    [NavigationItem("Facilities")]
    [ImageName("BO_Organization")]
    public class Building : Facility
    {
        private BuildingType type;
        private Address address;

        public Building(Session session)
            : base(session)
        {
            if (!IsLoading)
            {
                address = new Address(session);
            }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
        }

        protected override void OnSaving()
        {
            address.Save();
            base.OnSaving();
        }

        [Association("Building-BuildingType", typeof(BuildingType))]
        public BuildingType Type
        {
            get
            {
                return type;
            }
            set
            {
                SetPropertyValue<buildingtype>("Type", 
                                 ref type, value);
            }
        }

        [ExpandObjectMembers(ExpandObjectMembers.InDetailView)]
        public Address Address
        {
            get
            {
                return address;
            }
            set
            {
               SetPropertyValue<address>("Address", ref address, value);
            }
        }
    }

Concluding Remarks

It doesn’t get much easier than this. With just 63 lines of coding, we have created a solution that maintains its own data storage. XAF supports popular database management systems like Microsoft SQL Server, IBM DB2, Oracle RDBMS, and many more.

As an added bonus, we have both a Windows Forms application and an ASP.NET application.

The next part of the series will add support for booking, and it’s going to look nice too.

History

  • 12th of January 2011 - Initial posting
  • 14th of January 2011 - Added link to XAF at the top of the page

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Espen Harlinn
Architect Powel AS
Norway Norway
Chief Architect - Powel AS.
 
Specializing in integrated operations and high performance computing solutions.
 
I’ve been fooling around with computers since the early eighties, I’ve even done work on CP/M and MP/M.
 
Wrote my first “real” program on a BBC micro model B based on a series in a magazine at that time. It was fun and I got hooked on this thing called programming ...
 
A few Highlights:
  • High performance application server development
  • Model Driven Architecture and Code generators
  • Real-Time Distributed Solutions
  • C, C++, C#, Java, TSQL, PL/SQL, Delphi, ActionScript, Perl, Rexx
  • Microsoft SQL Server, Oracle RDBMS, IBM DB2, PostGreSQL
  • AMQP, Apache qpid, RabbitMQ, Microsoft Message Queuing, IBM WebSphereMQ, Oracle TuxidoMQ
  • Oracle WebLogic, IBM WebSphere
  • Corba, COM, DCE, WCF
  • AspenTech InfoPlus.21(IP21), OsiSoft PI
 
More information about what I do for a living can be found at: harlinn.com or LinkedIn
 
You can contact me at espen.harlinn@powel.no

Comments and Discussions

 
QuestionPart 2? Pinmemberbobfox15-Mar-11 8:15 
AnswerRe: Part 2? PinmemberEspen Harlinn15-Mar-11 8:39 
GeneralRe: Part 2? Pinmemberbobfox15-Mar-11 9:46 
GeneralRe: Part 2? PinmemberDennis Garavsky2-Oct-11 7:30 
GeneralOverride Question PinmemberBrady Kelly12-Feb-11 22:53 
GeneralRe: Override Question PinmemberEspen Harlinn14-Feb-11 8:13 
GeneralRe: Override Question PinmemberBrady Kelly14-Feb-11 8:19 
GeneralRe: Override Question PinmemberDennis Garavsky2-Oct-11 7:22 
GeneralMy vote of 5 PinmemberShahin Khorshidnia17-Jan-11 9:28 
GeneralRe: My vote of 5 PinmemberMarcus Kramer17-Jan-11 12:44 
GeneralRe: My vote of 5 PinmemberShahin Khorshidnia17-Jan-11 23:40 
GeneralRe: My vote of 5 PinmemberMarcus Kramer18-Jan-11 3:27 
GeneralRe: My vote of 5 PinmemberShahin Khorshidnia18-Jan-11 8:52 
GeneralRe: My vote of 5 PinmemberMarcus Kramer18-Jan-11 8:58 
GeneralRe: My vote of 5 PinmemberShahin Khorshidnia18-Jan-11 9:21 
GeneralRe: My vote of 5 PinmemberMarcus Kramer18-Jan-11 9:43 
GeneralRe: My vote of 5 PinmemberEspen Harlinn18-Jan-11 8:59 
GeneralMy vote of 5 PinmemberJF201515-Jan-11 4:32 
GeneralMy vote of 3 PinmembermarcoNS14-Jan-11 3:24 
GeneralMy vote of 3 Pinmembersam.hill13-Jan-11 5:55 
GeneralMy vote of 4 PinmvpRichard MacCutchan13-Jan-11 4:07 
GeneralRe: My vote of 4 PinmemberMarcus Kramer13-Jan-11 4:11 
GeneralRe: My vote of 4 PinmvpRichard MacCutchan13-Jan-11 4:15 
GeneralRe: My vote of 4 PinmemberEspen Harlinn13-Jan-11 4:36 
GeneralRe: My vote of 4 PinmemberMarcus Kramer13-Jan-11 4:58 
GeneralMy vote of 1 PinmemberMarcus Kramer12-Jan-11 12:31 
GeneralRe: My vote of 1 PinmemberEspen Harlinn12-Jan-11 21:12 
GeneralRe: My vote of 1 PinmemberMarcus Kramer13-Jan-11 4:05 
GeneralRe: My vote of 1 PinmemberEspen Harlinn13-Jan-11 4:34 
GeneralRe: My vote of 1 PinmemberMarcus Kramer13-Jan-11 4:48 
GeneralRe: My vote of 1 PinmemberEspen Harlinn13-Jan-11 5:00 
GeneralRe: My vote of 1 PinmemberMarcus Kramer13-Jan-11 8:17 
GeneralRe: My vote of 1 PinmemberEspen Harlinn13-Jan-11 8:27 
GeneralRe: My vote of 1 PinmvpRichard MacCutchan13-Jan-11 4:06 
GeneralRe: My vote of 1 PinmemberMarcus Kramer13-Jan-11 4:10 
GeneralRe: My vote of 1 PinmvpRichard MacCutchan13-Jan-11 4:18 
GeneralRe: My vote of 1 PinmemberMarcus Kramer13-Jan-11 4:53 
GeneralRe: My vote of 1 PinmvpRichard MacCutchan13-Jan-11 6:49 
No apology necessary, you have explained your position clearly.
I must get a clever new signature for 2011.

QuestionIsn´t this the same as Lightswitch, but paid? PinmemberKiller Bean12-Jan-11 12:21 
AnswerRe: Isn´t this the same as Lightswitch, but paid? PinmemberEspen Harlinn12-Jan-11 21:31 
AnswerRe: Isn´t this the same as Lightswitch, but paid? PinmemberDennis Garavsky27-Jan-11 11:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140709.1 | Last Updated 14 Jan 2011
Article Copyright 2011 by Espen Harlinn
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid