Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Getting the Job Done with XAF - Part 1

14 Jan 2011 1  
Tutorial on eXpressApp Framework (XAF)

This article is in the Product Showcase section for our sponsors at CodeProject. These articles 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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here