Design patterns in Microsoft.NET. Part 2

Introduction

As a solutions architect, we have to deal with several design patterns in order to design our solution. Design patterns are a way to conceptualize a reusable solution to commonly occurring problem in a given context in software design. Design pattern is today a way to communicate architectural ideas and decisions through a common language. In this series of articles, I will explain the essential design patterns (by the Gang of Four) with real-world code examples. In this second article, I want to talk about behavioral design patterns.

Talking about the design patterns

Behavioral design patterns

Chain of Responsibility design pattern: It consists of a source of command objects and a series of processing objects and it’s a way of communicating between objects. Each processing object contains a set of logic that describes the types of command objects that it can handle, and how to pass off those that it cannot to the next processing object in the chain. A mechanism also exists for adding new processing objects to the end of this chain.

You can use this design pattern when you have more than one object that may handle a request, you have a scenario that you need to pass a request to one of several objects without specifying the receiver and you have handlers of a request that should be specified dynamically.

The UML diagram for this design pattern is shown in the Figure 1.

01

Figure 1

And an example of this design pattern is found in the Listing 1.

public abstract class Handler

{

public int RequestLimit { get; private set; }

public Handler NextHandler { get; private set; }

 

public abstract void HandleRequest(int request);

 

public Handler(Handler handler, int requestLimit)

{

NextHandler = handler;

RequestLimit = requestLimit;

}

}

 

public class Worker : Handler

{

public Worker(Handler handler)

: base(handler, 10000)

{}

 

public override void HandleRequest(int request)

{

if (request < RequestLimit)

{

Console.WriteLine(“{0} handled a {1} request”, GetType().Name, request);

}

else

{

if (NextHandler != null)

{

NextHandler.HandleRequest(request);

}

}

}

}

 

public class Manager : Handler

{

public Manager(Handler handler)

: base(handler, 20000)

{}

 

public override void HandleRequest(int request)

{

if (request < RequestLimit)

{

Console.WriteLine(“{0} handled a {1} request”,GetType().Name, request);

}

else

{

if (NextHandler != null)

{

NextHandler.HandleRequest(request);

}

}

}

}

 

public class SeniorManager : Handler

{

public SeniorManager(Handler handler)

: base(handler, 50000)

{}

 

public override void HandleRequest(int request)

{

if (request < RequestLimit)

{

Console.WriteLine(“{0} handled a {1} request”,GetType().Name, request);

}

else

{

if (NextHandler != null)

{

NextHandler.HandleRequest(request);

}

}

}

}

 

class Program

{

static void Main(string[] args)

{

SeniorManager seniorManager = new SeniorManager(null);

Manager manager = new Manager(seniorManager);

Worker worker = new Worker(manager);

 

// Run requests along the chain

worker.HandleRequest(5000);

worker.HandleRequest(15000);

worker.HandleRequest(35000);

Console.WriteLine();

manager.HandleRequest(5000);

manager.HandleRequest(15000);

manager.HandleRequest(35000);

Console.WriteLine();

seniorManager.HandleRequest(5000);

seniorManager.HandleRequest(15000);

seniorManager.HandleRequest(35000);

// Wait for user

 

Console.Read();

}

}

Listing 1

Command design pattern: It encapsulates a request as an object, and it’s mainly used to represent and encapsulate all the information needed to call a method at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

Three terms always associated with the command pattern are client, invoker and receiver. The client instantiates the command object and provides the information required to call the method at a later time. The invoker decides when the method should be called. The receiver is an instance of the class that contains the method’s code.

The UML diagram for this design pattern is shown in the Figure 2.

02

Figure 2

And the example for this design pattern is shown in the Listing 2.

public interface Command

{

void Execute();

}

 

public class Light

{

public Light() { }

 

public void TurnOn()

{

System.Console.WriteLine(“The light is on”);

}

 

public void TurnOff()

{

System.Console.WriteLine(“The light is off”);

}

}

 

public class FlipUpCommand : Command

{

private Light _objLight;

 

public FlipUpCommand(Light light)

{

this._objLight = light;

}

 

public void Execute()

{

this._objLight.TurnOn();

}

}

 

public class FlipDownCommand : Command

{

private Light _objLight;

 

public FlipDownCommand(Light light)

{

this._objLight = light;

}

 

public void Execute()

{

this._objLight.TurnOff();

}

}

 

public class Switch : Command

{

private Command _objFlipUpCommand;

private Command _objFlipDownCommand;

 

private bool _bIsUp;

public bool IsUp

{

get

{

return this._bIsUp;

}

set

{

this._bIsUp = value;

}

}

 

public Switch()

{

Light objLamp = new Light();

 

this._objFlipUpCommand = new FlipUpCommand(objLamp);

this._objFlipDownCommand = new FlipDownCommand(objLamp);

}

 

public void Execute()

{

if (this._bIsUp)

{

this._objFlipUpCommand.Execute();

}

else

{

this._objFlipDownCommand.Execute();

}

}

}

 

public class PressSwitch {

 

public static void Main(String[] args)

{

Switch objSwitch = new Switch();

objSwitch.Execute();

}

}

Listing 2

Iterator design pattern: It provides a way to sequentially access aggregate objects without exposing the structure of the aggregate.

For example, a tree, linked list, hash table, and an array all need to be iterated with the methods search, sort, and next. Rather than having 12 different methods to manage (one implementation for each of the previous three methods in each structure), using the iterator pattern yields just seven: one for each class using the iterator to obtain the iterator and one for each of the three methods. Therefore, to run the search method on the array, you would call array.search(), which hides the call to array.iterator.search().

The pattern is widely used in C# and in the .NET framework we have the IEnumerator and IEnumerable interfaces to help us to implement iterators for aggregates. When you implement your own aggregate object you should implement these interfaces to expose a way to traverse your aggregate.

You use this when you need a uniform interface to traverse different aggregate structures, you have various ways to traverse an aggregate structure and you don’t want to expose the aggregate object’s internal representation.

The UML diagram for this design pattern is shown in the Listing 2.

03

Figure 3

And an example code in C# of this design pattern is shown in the Listing 3.

public class AggregateItem

{

public string Data { get; set; }

public AggregateItem(string data)

{

this.Data = data;

}

}

 

interface Aggregate

{

Iterator GetIterator();

}

 

class AggregateImpl : Aggregate

{

private readonly List<AggregateItem> _aggregate;

public int Count

{

get

{

return _aggregate.Count;

}

}

 

public AggregateItem this[int index]

{

get

{

return _aggregate[index];

}

set

{

_aggregate[index] = value;

}

}

 

public AggregateImpl()

{

_aggregate = new List<AggregateItem>();

}

 

public Iterator GetIterator()

{

return new IteratorImpl(this);

}

}

 

interface Iterator

{

object First();

object Next();

bool IsDone();

object Current();

}

 

class IteratorImpl : Iterator

{

private readonly AggregateImpl _aggregate;

private int _nCurrentIndex;

 

public object First()

{

return _aggregate[0];

}

 

public object Next()

{

object result = null;

if (_nCurrentIndex < _aggregate.Count – 1)

{

result = _aggregate[_nCurrentIndex];

_nCurrentIndex++;

}

return result;

}

 

public bool IsDone()

{

return _nCurrentIndex >= _aggregate.Count;

}

 

public object Current()

{

return _aggregate[_nCurrentIndex];

}

 

public IteratorImpl(AggregateImpl aggregate)

{

_nCurrentIndex = 0;

_aggregate = aggregate;

}

}

Listing 3

Mediator design pattern: – It encapsulates the interaction between a set of objects. The pattern helps to lose couple the object by keeping them from referring each other. You use this design pattern when the behavior is distributed between some objects can be grouped or customized, object reuse is difficult because it communicates with other objects, and objects in the system communicate in well-defined but complex ways.

The UML diagram for this design pattern is shown in the Figure 4.

04

Figure 4

And an example of this design pattern is shown in the Listing 4.

public interface Mediator

{

void Send(string message, Colleague colleague);

}

 

public class ConcreteMediator : Mediator

{

public List<ConcreteColleague> Colleagues { get; private set; }

public ConcreteMediator()

{

Colleagues = new List<ConcreteColleague>();

}

 

public void Send(string message, Colleague colleague)

{

foreach (Colleague currentColleague in Colleagues)

{

if (!currentColleague.Equals(colleague))

{

currentColleague.Recieve(message);

}

}

}

}

 

public abstract class Colleague

{

protected Mediator _mediator;

 

public Colleague(Mediator mediator)

{

_mediator = mediator;

}

public abstract void Send(string message);

public abstract void Recieve(string message);

}

 

public class ConcreteColleague : Colleague

{

public int ID { get; set; }

 

public ConcreteColleague(Mediator mediator, int id)

: base(mediator)

{

ID = id;

}

public override void Send(string message)

{

_mediator.Send(message, this);

}

public override void Recieve(string message)

{

Console.WriteLine(“{0} recieved the message: {1}”,ID, message);

}

}

 

class Program

{

static void Main(string[] args)

{

ConcreteMediator mediator = new ConcreteMediator();

ConcreteColleague colleague1 = new ConcreteColleague(mediator, 1);

ConcreteColleague colleague2 = new ConcreteColleague(mediator, 2);

mediator.Colleagues.Add(colleague1);

mediator.Colleagues.Add(colleague2);

colleague1.Send(“Hello from colleague 1”);

colleague2.Send(“Hello from colleague 2”);

Console.Read();

}

}

Listing 4

Memento design pattern: It helps to save the object internal state in an external place enabling us to restore the state later when needed. The memento pattern doesn’t violate encapsulation of the internal state. The pattern is rarely used but it’s very helpful in scientific computing or in computer games.

It’s mainly used when you need to save object’s state and use the saved state later in order to restore the saved state and you don’t want to expose the internal state of your object (see Figure 5).

05

Figure 5

An example code for this pattern is shown in the Listing 5.

public class Originator<T>

{

public T State { get; set; }

public Memento<T> SaveMemento()

{

return (new Memento<T>(State));

}

public void RestoreMemento(Memento<T> memento)

{

State = memento.State;

}

}

 

public class Memento<T>

{

public T State { get; private set; }

public Memento(T state)

{

State = state;

}

}

 

public class Caretaker<T>

{

public Memento<T> Memento { get; set; }

}

 

class Program

{

static void Main(string[] args)

{

Originator<string> org = new Originator<string>();

org.State = “Old State”;

Caretaker<string> caretaker = new Caretaker<string>();

caretaker.Memento = org.SaveMemento();

Console.WriteLine(“This is the old state: {0}”, org.State);

org.State = “New state”;

Console.WriteLine(“This is the new state: {0}”, org.State);

org.RestoreMemento(caretaker.Memento);

Console.WriteLine(“Old state was restored: {0}”, org.State);

Console.Read();

}

}

Listing 5

Observer design pattern: It is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.

You mainly use this pattern when you have a publisher/subscriber model, objects need to be notified of a change in another objects, and you need that the object that notify its state change would not know about its subscribers.

The UML diagram for this design pattern is shown in the Figure 6.

06

Figure 6

An example code for this design pattern is shown in the Listing 6.

public abstract class Subject

{

private List<IObserver> _observers;

 

public Subject()

{

_observers = new List<IObserver>();

}

 

public void Attach(IObserver observer)

{

_observers.Add(observer);

}

 

public void Detach(IObserver observer)

{

_observers.Remove(observer);

}

 

public void Notify()

{

foreach (IObserver observer in _observers)

{

observer.Update();

}

}

}

 

public class ConcreteSubject<T> : Subject

{

public T SubjectState { get; set; }

}

 

public interface IObserver

{

void Update();

}

 

public class ConcreteObserver<T> : IObserver

{

private T _observerState;

public ConcreteObserver(ConcreteSubject<T> subject)

{

Subject = subject;

}

 

public void Update()

{

_observerState = Subject.SubjectState;

Console.WriteLine(“The new state of the observer:{0}”, _observerState.ToString());

}

}

 

class Program

{

static void Main(string[] args)

{

ConcreteSubject<string> subject = new ConcreteSubject<string>();

subject.Attach(new ConcreteObserver<string>(subject));

subject.Attach(new ConcreteObserver<string>(subject));

subject.SubjectState = “Hello World”;

subject.Notify();

System.Console.Read();

}

}

Listing 6

Strategy design pattern: It allows you to use multiple algorithms interchangeably.  One reason you might use a Strategy design pattern is to simplify an overly complex algorithm. Sometimes, as an algorithm evolves to handle more and more situations, it can become very complex and difficult to maintain. Breaking these complex algorithms down into smaller more manageable algorithms might make your code more readable and more easily maintained.

The UML diagram for this pattern is shown in the Figure 7.

07

Figure 7

An example code for this design pattern is shown in the Listing 7.

using System;

 

namespace Wikipedia.Patterns.Strategy

{

class MainApp

{

static void Main()

{

Context anObject;

 

// Three contexts following different strategies

anObject = new Context(new ConcreteStrategyA());

anObject.Execute();

 

anObject.UpdateContext(new ConcreteStrategyB());

anObject.Execute();

 

anObject.UpdateContext(new ConcreteStrategyC());

anObject.Execute();

}

}

 

interface IStrategy

{

void Execute();

}

 

class ConcreteStrategyA : IStrategy

{

public void Execute()

{

Console.WriteLine(“Called ConcreteStrategyA.Execute()”);

}

}

 

class ConcreteStrategyB : IStrategy

{

public void Execute()

{

Console.WriteLine(“Called ConcreteStrategyB.Execute()”);

}

}

 

class ConcreteStrategyC : IStrategy

{

public void Execute()

{

Console.WriteLine(“Called ConcreteStrategyC.Execute()”);

}

}

 

class Context

{

IStrategy strategy;

 

public Context(IStrategy strategy)

{

this.strategy = strategy;

}

 

public void UpdateContext(IStrategy strategy)

{

this.strategy = strategy;

}

 

public void Execute()

{

strategy.Execute();

}

}

}

Listing 7

Conclusion

In this article, I’ve explained the essential design patterns (by the Gang of Four) with UML diagrams and real-world code examples.

 

Advertisements

Introduction

As a solutions architect, we have to deal with several design patterns in order to design our solution. Design patterns are a way to conceptualize a reusable solution to commonly occurring problem in a given context in software design. Design pattern is today a way to communicate architectural ideas and decisions through a common language. In this series of articles, I will explain the essential design patterns (by the Gang of Four) with real-world code examples. In this first article, I want to talk about creational and structural design patterns.

Talking about the design patterns

In order to explain the essential design patterns, I want to organize the design patterns the same way as the Gang of Four did as creational, structural and behavioral.

Creational design patterns

Factory design pattern: The factory design pattern is used to create instances of classes without specifying the exact class. The essence is: “Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses”. It’s mainly used for the creation of objects regarding to the configuration files or user input.

The UML representation is shown in the Figure 1.

Figure 1

An example in C# is shown in the Listing 1.

public interface ISession

{

void Initiate();

}

public class DatabaseSession : ISession

{

void Initiate()

{ }

}

public class MessageQueueSession : ISession

{

void Initiate()

{ }

}

public class SessionFactory

{

public static ISession GetSession(string session)

{

ISession objResult = null;

switch(session)

{

case “database”:

objResult = new DatabaseSession();

case “mqueue”:

objResult = new MessageQueueSession();

}

return objResult;

}

}

Listing 1

Abstract Factory: It provides a way to encapsulate a group of individual factories that have a common theme. In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interfaces to create the concrete objects that are part of the theme. It’s a factory of factory, so we need to create another layer to the example in the Listing 1.

Flyweight pattern: It’s used to maximize the sharing of objects resulting in reduced memory consumption, for example, you have large amount of small objects that share common information reducing the storage of the objects. It’s an extension of the factory design pattern.

The UML diagram is shown in the Figure 2.

Figure 2

Let’s see an implementation in C# (see Listing 2).

public enum eNumbers

{

One,

Two,

Three,

// .. and so on with every number

}

public class NumbersFactory

{

private Dictionary<eNumbers, Number> _numbers = new Dictionary<eNumbers, Number>();

public Number GetNumber(eNumbers number)

{

if (!_numbers.ContainsKey(number))

{

switch (number)

{

case (eNumbers.One):

{

_numbers.Add(number, new One());

break;

}

case (eNumbers.Two):

{

_numbers.Add(number, new Two());

break;

}

case (eNumbers.Three):

{

_numbers.Add(number, new Three());

break;

}

default:

{

break;

}

}

}

return _numbers[number];

}

}

public abstract class Number

{

protected int _number;

protected string _numberName;

protected int _numberSize;

public abstract void WriteNumber(int numberSize);

}

public class One : Number

{

public One()

{

this._number = 1;

this._numberName = “One”;

}

public override void WriteNumber(int numberSize)

{

this._numberSize = numberSize;

Console.WriteLine(string.Format(“{0} is size {1}”,_numberName, _numberSize));

}

}

public class Two : Number

{

public Two()

{

this._number = 2;

this._numberName = “Two”;

}

public override void WriteNumber(int numberSize)

{

this._numberSize = numberSize;

Console.WriteLine(string.Format(“{0} is size {1}”,_numberName, _numberSize));

}

}

public class Three : Number

{

public Three()

{

this._number = 3;

this._numberName = “Three”;

}

public override void WriteNumber(int numberSize)

{

this._numberSize = numberSize;

Console.WriteLine(string.Format(“{0} is size {1}”, _numberName, _numberSize));

}

}

Listing 2

Singleton design pattern: It’s used to insure that only a single instance of a given object can exist. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.

The UML diagram is shown in Figure 3.

Figure 3

And the example in C# is shown in the Listing 3.

public sealed class Singleton

{

private static readonly Singleton _instance = new Singleton();

private Singleton() { }

public static Singleton Instance

{

get

{

return _instance;

}

}

}

Listing 3

Builder design pattern: It separates the construction of a complex object from its representation so that the same construction process can create different representations. This pattern is not commonly used. It’s like the abstract factory with the difference that the builder is concerned about how the objects are created and the abstract factory is concerned about what objects are created.

Let’s see the UML diagram for this pattern (see Figure 4).

Figure 4

Let’s see an implementation using C# (see Listing 4).

class Pizza

{

public string Dough { get; set; }

public string Sauce { get; set; }

public string Topping { get; set; }

}

abstract class PizzaBuilder

{

public Pizza pizza { get; protected set; }

public void CreatePizza()

{

pizza = new Pizza();

}

public abstract void BuildDough();

public abstract void BuildSauce();

public abstract void BuildTopping();

}

class HawaiianPizzaBuilder : PizzaBuilder

{

public override void  BuildDough()

{

pizza.Dough = “Cross”;

}

public override void BuildSauce()

{

pizza.Sauce = “Mild”;

}

public override void BuildTopping()

{

pizza.Topping = “Ham+Pineapple”;

}

}

class SpicyPizzaBuilder : PizzaBuilder

{

public override void BuildDough()

{

pizza.Dough = “Pan Baked”;

}

public override void BuildSauce()

{

pizza.Sauce = “Hot”;

}

public override void BuildTopping()

{

pizza.Topping = “Pepperoni+Salami”;

}

}

class Cook

{

public PizzaBuilder PizzaBuilder { get; set; }

public Pizza Pizza { get { return PizzaBuilder.pizza; } }

public void MakePizza()

{

PizzaBuilder.CreatePizza();

PizzaBuilder.BuildDough();

PizzaBuilder.BuildSauce();

PizzaBuilder.BuildTopping();

}

}

static void Main(string[] args)

{

Cook cook = new Cook();

cook.PizzaBuilder = new SpicyPizzaBuilder();

cook.MakePizza();

cook.PizzaBuilder = new HawaiianPizzaBuilder();

cook.MakePizza();

}

Listing 4

Lazy initialization: The idea is to delay the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed (see Listing 5).

using System;

using System.Collections;

using System.Collections.Generic;

public class Fruit

{

private string _typeName;

private static Dictionary<string, Fruit> _typesDictionary = new Dictionary<string, Fruit>();

private Fruit(String typeName)

{

this._typeName = typeName;

}

public static Fruit GetFruitByTypeName(string type)

{

Fruit fruit;

if (!_typesDictionary.ContainsKey(type))

{

// Lazy initialization

fruit = new Fruit(type);

_typesDictionary.Add(type, fruit);

}

else

fruit = _typesDictionary[type];

return fruit;

}

public static void ShowAll()

{

if (_typesDictionary.Count > 0)

{

Console.WriteLine(“Number of instances made = {0}”, _typesDictionary.Count);

foreach (KeyValuePair<string, Fruit> kvp in _typesDictionary)

{

Console.WriteLine(kvp.Key);

}

Console.WriteLine();

}

}

}

class Program

{

static void Main(string[] args)

{

Fruit.GetFruitByTypeName(“Banana”);

Fruit.ShowAll();

Fruit.GetFruitByTypeName(“Apple”);

Fruit.ShowAll();

// returns pre-existing instance from first

// time Fruit with “Banana” was created

Fruit.GetFruitByTypeName(“Banana”);

Fruit.ShowAll();

Console.ReadLine();

}

}

Listing 5

Object pool design pattern: It’s a set of initialized objects that are kept ready to use, rather than allocated and destroyed on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished with an object, it returns it to the pool, rather than destroying it. It is a specific type of factory object. It’s mainly used in situations where the cost of initializing a class instance is high, the rate of instantiation of a class is high, and the number of instances in use at any one time is low, such as database connections, socket connections, threads and large graphic objects like fonts or bitmaps.

When writing an object pool, the programmer has to be careful to make sure the state of the objects returned to the pool is reset back to a sensible state for the next use of the object. If this is not observed, the object will often be in some state that was unexpected by the client program and may cause the client program to fail. The pool is responsible for resetting the objects, not the clients.

Structural design patterns

Adapter design pattern: It converts the interface of a class into another interface clients expect. Adapter lets the classes work together that couldn’t otherwise because of incompatible interfaces, by providing its interface to clients while using the original interface.

Let’s see the UML diagram for this pattern (see Listing 5).

Figure 5

The implementation of the design pattern is shown in the Listing 6.

public interface IClient

{

void DoWork();

}

public interface IAdaptor

{

void MethodA();

}

public interface IAdaptee

{

void MethodB();

}

public class Adaptee : IIAdaptee

{

public void MethodB()

{ }

}

public class Adaptor : IAdaptor

{

private Adaptee _objAdaptee;

public Adaptor(Adaptee objAdaptee)

{

this._objAdaptee = objAdaptee;

}

public void MethodA()

{

this._objAdaptee.MethodB();

}

}

public class Client : IClient

{

private IAdaptor _objAdaptor;

public Client(IAdaptor objAdaptor)

{

this._objAdaptor = objAdaptor;

}

public void DoWork()

{

this._objAdaptor.MethodA();

}

}

Listing 6

Bridge design pattern: It decouples an abstraction from its implementation so that the two can vary independently. In other words we make a bridge between the abstraction and its implementation and therefore we won’t have a binding between the two.

Let’s see UML diagram for this design pattern (see Figure 6).

Figure 6

Let’s see an implementation of this design pattern (see Listing 7).

public class Abstraction

{

private Bridge _bridge;

public Abstraction(Bridge bridge)

{

_bridge = bridge;

}

public void Operation()

{

Console.Write(“Using”);

_bridge.OperationImplementation();

}

}

public interface Bridge

{

void OperationImplementation();

}

public class BridgeImplementationA : Bridge

{

public void OperationImplementation()

{

Console.Write(“BridgeImplementationA”);

}

}

public class BridgeImplementationB : Bridge

{

public void OperationImplementation()

{

Console.Write(“BridgeImplementationB”);

}

}

Listing 7

Composite design pattern:  The main idea is to compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

The UML diagram for this design pattern is shown in the Figure 7.

Figure 7

Now let’s see the code example in C# (see Listing 8).

using System;

using System.Collections.Generic;

namespace Composite

{

class Program

{

interface IGraphic

{

void Print();

}

class CompositeGraphic : IGraphic

{

private List<IGraphic> child = new List<IGraphic>();

public CompositeGraphic(IEnumerable<IGraphic> collection)

{

child.AddRange(collection);

}

public void Print()

{

foreach(IGraphic g in child)

{

g.Print();

}

}

}

class Ellipse : IGraphic

{

public void Print()

{

Console.WriteLine(“Ellipse”);

}

}

static void Main(string[] args)

{

new CompositeGraphic(new IGraphic[]

{

new CompositeGraphic(new IGraphic[]

{

new Ellipse(),

new Ellipse(),

new Ellipse()

}),

new CompositeGraphic(new IGraphic[]

{

new Ellipse()

})

}).Print();

}

}

}

Listing 8

Decorator design pattern: It allows an objects behavior to be altered at runtime.This change in behavior is accomplished by wrapping an object with a new object.  This new wrapper object is the Decorator. The Decorator object will implement the same interface as the object being wrapped.  Because the decorated object uses the same interface as an undecorated object, other parts of your system do not need to be aware of whether or not one or more decorations are in use. The decorator (wrapper) can now alter the behavior of the object being wrapped by either completely replacing various methods or by altering the behavior of the methods of the object being decorated.

This is very important to implement cross-functional features (aspect-oriented programming) in your applications such as logging, security, transactions, etc. It can be also used to express context-specify aspects to plain objects without changing their implementation (see Listing 9).

public interface IReport

{

void Print();

}

public class Report : IReport

{

public void IReport.Print()

{

HttpContext.Current.Response.Write(“This is the report body.”);

}

}

public class ReportHeaderDecorator : IReport

{

private IReport _innerReport;

public ReportHeaderDecorator(IReport innerReport)

{

_innerReport = innerReport;

}

public void IReport.Print()

{

HttpContext.Current.Response.Write(“<h3>This is the report header</h3>”);

HttpContext.Current.Response.Write(“<hr />”);

_innerReport.Print();

}

}

public class ReportFooterDecorator : IReport

{

private IReport _innerReport;

public ReportFooterDecorator(IReport innerReport)

{

_innerReport = innerReport;

}

public void IReport.Print()

{

_innerReport.Print();

HttpContext.Current.Response.Write(“<hr />”);

HttpContext.Current.Response.Write(“<h6>This is the report footer.</h6>”);

}

}

IReport myReport;

myReport = new Report();

myReport = new ReportHeaderDecorator(myReport);

myReport = new ReportFooterDecorator(myReport);

myReport.Print();

Listing 9

Facade design pattern: It’s mainly used to provide a simpler interface into a more complicated series of complicated interfaces and or sub systems (see Figure 8).

Figure 8

Another UML diagram is shown in the Figure 9.

Figure 9

And an implementation is shown in the Listing 10.

using System;

namespace Facade

{

class Computer

{

class CPU

{

public void Freeze() { }

public void Jump(long addr) { }

public void Execute() { }

}

class Memory

{

public void Load(long position, byte[] data) { }

}

class HardDrive

{

public byte[] Read(long lba, int size) { return null; }

}

CPU cpu = new CPU();

Memory memory = new Memory();

HardDrive hardDrive = new HardDrive();

void StartComputer()

{

cpu.Freeze();

memory.Load(0x22, hardDrive.Read(0x66, 0x99));

cpu.Jump(0x44);

cpu.Execute();

}

static void Main(string[] args)

{

Computer facade = new Computer();

facade.StartComputer();

}

}

}

Listing 10

Proxy design pattern: It provides a Placeholder for another object to control access to it. A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate.

The UML diagram for this design pattern is shown in the Listing 10.

Figure 10

An implementation of this design pattern is shown in the Listing 11.

using System;

namespace Proxy

{

class Program

{

interface IImage

{

void Display();

}

class RealImage : IImage

{

public RealImage(string fileName)

{

FileName = fileName;

LoadFromFile();

}

private void LoadFromFile()

{

Console.WriteLine(“Loading ” + FileName);

}

public String FileName { get; private set; }

public void Display()

{

Console.WriteLine(“Displaying ” + FileName);

}

}

class ProxyImage : IImage

{

public ProxyImage(string fileName)

{

FileName = fileName;

}

public String FileName { get; private set; }

private IImage image;

public void Display()

{

if (image == null)

image = new RealImage(FileName);

image.Display();

}

}

static void Main(string[] args)

{

IImage image = new ProxyImage(“HiRes_Image”);

}

}

}

Listing 11

Conclusion

In this article, I’ve explained the essential design patterns (by the Gang of Four) with UML diagrams and real-world code examples.

Writing persistent layers using DLinq and Hibernate

By: John Charles (Juan Carlos) Olamendy Turruellas

Introduction

In this article, I will illustrate the principles, techniques and tools to develop applications using Linq to SQL and Hibernate technologies. As we know, ADO.NET is the standard data access library in Microsoft.NET and Linq to SQL is an extension to .NET languages to add native support for accessing and updating data by using traditional object operations following the object-oriented paradigm. Hibernate is a technology that enables the developer to manage (access and update) relational data in Java platform by defining persistent entities and mapping them to relational database tables by executing object operations.

ORM State of the art

Developing software is a complicated task and most significant development projects involve a relational database where CRUD operations are the corner stone of the solution. There are a lot of monolithic applications where the data access code and the data presentation are in one place. This is very difficult to develop and maintain, because the developer must understand how to write SQL code.

Then a new approach and several technologies supporting it come up. Object-relational mapping (ORM) is an approach to automatically connect the domain model of your application to a relational database system by using metadata as the descriptor of the object and data.

ORM solves the object-relational impendence mismatch problem (tabular data versus domain model) by replacing direct persistence related to the database access with high level object operations.

It’s very important to remark that there are many benefits to using ORM other than data access techniques, as shown:

  • ORM automatically mapping the object model to the back-end relational data using metadata. This simplifies the development and maintenance effort.
  • It requires a few lines of code to implement the data management logic by creating dynamic queries.
  • ORM technologies provide transparent caching objects, thus improving the overall performance of the system.

Getting started with Hibernate the examples

In order to illustrate the ORM concepts using Hibernate technology, we’re going to connect to a PostgreSQL database and create a table to persist the state of the Department business entity (see Listing 1).

CREATE TABLE department(

deptno integer NOT NULL,

deptname character varying(255),

“location” character varying(255),

CONSTRAINT department_pkey PRIMARY KEY (deptno)

)

WITH (OIDS=FALSE);

ALTER TABLE department OWNER TO john;

Listing 1

For the Hibernate code examples, we’re going to create a standalone console application in Java using NetBeans 6.5.

First step is to add a project using NetBeans 6.5 (see Figure 1).

Figure 1

Then set a name and the location for the project (see Figure 2).

Figure 2

In order to support Hibernate in the project, we need to add the Hibernate library to the project. Open the Projects windows and right-click on the Libraries node of the project and select “Add Library” option from the context menu. Then browse to the Hibernate library in the “Add Library” dialog box (see Figure 3).

Figure 3

The implementation strategy for this example is by following the top-down approach. That is, we’re going to configure the underlying Hibernate files for the connection to the back-end database system in this case the PostgreSQL database where the department table resides, then we’re going to generate the business entities’ classes and their underlying mapping using the NetBeans tools, as well as an utility class for doing common operations in Hibernate such as configuration loading and session creation.

Now let’s create the Hibernate configuration file using the wizards in NetBeans. The Hibernate configuration file (hibernate.cfg.xml) contains information about the database connection, resource mappings and other connections properties. This file is used by the Configuration class’ instances when to invoke the configure method to load this information for Hibernate to use.

Select the File | New File menu option. In the “New File” wizard, go to the Hibernate categories and select the “Hibernate Configuration File” in the “File Types” pane, and click on Next button (see Figure 4).

Figure 4

In the next page, leave it as shown in Figure 5 and click on the Next button.

Figure 5

In the “Select a Data Source” page, select a register data source to the department table in the PostgreSQL database and click on the Finish button.

The IDE creates the configuration file at the root of the context classpath of the application (in the Files window, WEB-INF/classes). In the Projects window the file is located in the <default package> source package. The configuration file contains information about a single database. If you plan to connect to multiple databases, you can create multiple configuration files in the project, one for each database servers, but by default the helper utility class will use the hibernate.cfg.xml file located in the root location.

If you expand the Libraries node in the Projects window you can see that the IDE added the required Hibernate JAR files and the PostgreSQL connector JAR (see Figure 6).

Figure 6

To use this Hibernate configuration we can create a helper class that handles startup and that accesses Hibernate’s SessionFactory class to obtain a Session object. The instances of this class call configure method, which loads the hibernate.cfg.xml configuration file from the classpath and then builds the SessionFactory to obtain the Session object.

Select the File | New File menu option. In the “New File” wizard, go to the Hibernate categories and select the “HibernateUtil.java” in the “File Types” pane, and click on Next button (see Figure 7).

Figure 7

In the “Name and Location” page, let’s enter the values as shown in the Figure 8.

Figure 8

For the examples, I’m going to use the POJO Department.java class definition. The “Hibernate Mapping Files and POJOs from a Database” wizard generates files based on the department table in the back-end database. When you use the wizard you select all the tables for which you want POJOs and mapping files and the IDE then generates the files for you based on the database tables and adds the mapping entries to hibernate.cfg.xml configuration file.

Select the File | New File menu option. In the “New File” wizard, go to the Hibernate categories and select the “Hibernate Mapping Files and POJOs from a Database” in the “File Types” pane, and click on Next button (see Figure 9).

Figure 9

In the “Name and Location” page, leave the data as shown in the Figure 10.

Figure 10

Add from the Available Table panel to Selected Table panel, the tables to be mapped to business entities  and click on the Next button(see Figure 11).

Figure 11

In the “Generation of Code” page, leave the data as shown in the Figure 12 and click on the Finish button.

Figure 12

Mapping classes to database tables can be accomplished through XML configuration file or using Java annotation. The most common used configuration file in Hibernate is the XML configuration file, and from this file Hibernate can generate skeletal source code for the persistence classes. The one-to-many and many-to-many relationships are also generated.

Let’s see the generated mapping (see Listing 2) and business entities (see Listing 3) for our example.

<?xml version=”1.0″?><!DOCTYPE hibernate-mapping PUBLIC “-//Hibernate/Hibernate Mapping DTD 3.0//EN”

http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd”&gt;

<!– Generated Jul 3, 2009 2:49:24 PM by Hibernate Tools 3.2.1.GA –>

<hibernate-mapping>

<class name=”hibernatetestjavaapp.Department” table=”department” schema=”human_resources”>

<id name=”deptno” type=”int”>

<column name=”deptno” />

<generator />

</id>

<property name=”deptname” type=”string”>

<column name=”deptname” length=”50″ not-null=”true” />

</property>

<property name=”location” type=”string”>

<column name=”location” length=”50″ />

</property>

</class>

</hibernate-mapping>

Listing 2

package hibernatetestjavaapp;// Generated Jul 3, 2009 2:49:18 PM by Hibernate Tools 3.2.1.GA

/**

* Department generated by hbm2java

*/

public class Department  implements java.io.Serializable {

private int deptno;

private String deptname;

private String location;

public Department() {

}

public Department(int deptno, String deptname) {

this.deptno = deptno;

this.deptname = deptname;

}

public Department(int deptno, String deptname, String location) {

this.deptno = deptno;

this.deptname = deptname;

this.location = location;

}

public int getDeptno() {

return this.deptno;

}

public void setDeptno(int deptno) {

this.deptno = deptno;

}

public String getDeptname() {

return this.deptname;

}

public void setDeptname(String deptname) {

this.deptname = deptname;

}

public String getLocation() {

return this.location;

}

public void setLocation(String location) {

this.location = location;

}

}

Listing 3

Now we’re ready to manage the department data using Hibernate from the main application. We’re going to follow a template for the creation of the queries (see Listing 4).

/** To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args)

{

SessionFactory factory = HibernateUtil.getSessionFactory();

Session session = factory.openSession();

try

{

session.getTransaction().begin();

//Here comes the Hibernate code to manage the data

session.getTransaction().commit();

}

catch (Throwable e)

{

if (session.getTransaction().isActive())

{

session.getTransaction().rollback();

}

System.out.println(e.getMessage());

}

session.close();

}

}

Listing 4

As you can see the HibernateUtil class invokes the getSessionFactory to create a new session factory and from this point, a new session is created. The SessionFactory is a heavyweight object, and there would be normally a single instance in the application. The Session has amount in common with JDBC Connection object, because in order to manipulate an object in a database system, we need to open a session first and then execute the underlying operations. The Session instances also manage caching functionality, lazy loading of objects, and watching for changes of the associated objects. The Transaction instances in Hibernate have the same responsibilities than their counterpart JDBC transactions. It’s required Hibernate operations to be enclosed in transactions.

Now let’s start to manipulate the department data using Session object in order to illustrate how to create, update, read and delete (CRUD) operations.

The create operation is implemented very simple. Just create an instance of the Department class and invoke the save method of the Session instance (see Listing 5). Creating an instance of a class does not automatically persist the object in the database. You need to explicitly save the object with a valid Hibernate session by using the active session’s save method.

If you are not able to determine the state of the object, then the active session’s saveOrUpdate method is used. In this case, Hibernate uses the identifier of the object to determine whether insert a new row or update an existing one.

/** To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args)

{

SessionFactory factory = HibernateUtil.getSessionFactory();

Session session = factory.openSession();

try

{

session.getTransaction().begin();

//Here comes the Hibernate code to manage the data

Department objDepartment = new Department();

objDepartment.setDeptno(120);

objDepartment.setDeptname(“Human Resources”);

objDepartment.setLocation(“Philadelphia”);

session.save(objDepartment);

session.getTransaction().commit();

}

catch (Throwable e)

{

if (session.getTransaction().isActive())

{

session.getTransaction().rollback();

}

System.out.println(e.getMessage());

}

session.close();

}

}

Listing 5

In order to retrieve a department object from the database, we need to use HQL. HQL is conceptually similar to SQL with the exception that the names in the query refers to the names used in the mapping files. Let’s supposed we want to get the last created entity, so we need to create a HQL query where the identifier of this entity (in this case, the department number) is equal to a value.

In our example, we need to create a Query object (similar in functionality to PreparedStatement in JDBC), populate the parameter of the query with the appropriate value and display the result. We use the uniqueResult method because it is guaranteed to throw an exception if somehow the query identifies more than one department (see Listing 6).

There is another method to get data from the underlying database system using the active session’s load and get methods. These methods are straightforward taking as arguments the class type of the object to load and its identifier. The load method also takes a lock mode as argument to specify whether Hibernate should look into the cache for the object, and which database lock model to follow.

/** To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args)

{

SessionFactory factory = HibernateUtil.getSessionFactory();

Session session = factory.openSession();

try

{

session.getTransaction().begin();

//Here comes the Hibernate code to manage the data

Query objQuery = session.createQuery(“from Department where deptno=:deptno”);

objQuery.setInteger(“deptno”,120);

Department objDepartment = (Department)objQuery.uniqueResult();

System.out.println(“Department data. Name=”+objDepartment.getDeptname()+”, Location=”+objDepartment.getLocation());

session.getTransaction().commit();

}

catch (Throwable e)

{

if (session.getTransaction().isActive())

{

session.getTransaction().rollback();

}

System.out.println(e.getMessage());

}

session.close();

}

}

Listing 6

In the same way, we can create a query to get a list of departments which are located in New York by using the follow query “Query objQuery = session.createQuery(“from Department where location=:location”)” and the complete code is shown in the Listing 7.

/** To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args)

{

SessionFactory factory = HibernateUtil.getSessionFactory();

Session session = factory.openSession();

try

{

session.getTransaction().begin();

//Here comes the Hibernate code to manage the data

Query objQuery = session.createQuery(“from Department where location=:location”);

objQuery.setString(“location”,”New York”);

List<Department> arrDepartment = (List<Department>)objQuery.list();

for(Department objDepartment:arrDepartment)

{

System.out.println(“Department data. Name=”+objDepartment.getDeptname()+”, Location=”+objDepartment.getLocation());

}

session.getTransaction().commit();

}

catch (Throwable e)

{

if (session.getTransaction().isActive())

{

session.getTransaction().rollback();

}

System.out.println(e.getMessage());

}

session.close();

}

}

Listing 7

Now let’s suppose we want to update the data of a department entity (see Listing 8).

/** To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args)

{

SessionFactory factory = HibernateUtil.getSessionFactory();

Session session = factory.openSession();

try

{

session.getTransaction().begin();

//Here comes the Hibernate code to manage the data

Query objQuery = session.createQuery(“from Department where deptno=:deptno”);

objQuery.setInteger(“deptno”, 120);

Department objDepartment = (Department)objQuery.uniqueResult();

objDepartment.setLocation(“Detroit”);

session.getTransaction().commit();

}

catch (Throwable e)

{

if (session.getTransaction().isActive())

{

session.getTransaction().rollback();

}

System.out.println(e.getMessage());

}

session.close();

}

}

Listing 8

And finally to complete the CRUD operations, let’s explain how to delete this department entity (see Listing 9).

/** To change this template, choose Tools | Templates

* and open the template in the editor.

*/

package hibernatetestjavaapp;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

/**

*

* @author root

*/

public class Main {

/**

* @param args the command line arguments

*/

public static void main(String[] args)

{

SessionFactory factory = HibernateUtil.getSessionFactory();

Session session = factory.openSession();

try

{

session.getTransaction().begin();

//Here comes the Hibernate code to manage the data

Query objQuery = session.createQuery(“from Department where deptno=:deptno”);

objQuery.setInteger(“deptno”, 120);

Department objDepartment = (Department)objQuery.uniqueResult();

session.delete(objDepartment);

session.getTransaction().commit();

}

catch (Throwable e)

{

if (session.getTransaction().isActive())

{

session.getTransaction().rollback();

}

System.out.println(e.getMessage());

}

session.close();

}

}

Listing 9

It’s remarkable to say that the examples in the previous listings are based on persistent objects associated to an active connection. But in Hibernate, there the concept Detach objects which are objects with a representation (using mapping) in the databases, but changes to their states are not reflected in the database because they are not connected to the database. A detached object can be created by closing a session that it was associated with, or by evicting it from the session with a call to the active session’s evict method. In order to persist the changes of their states, the application must re-attach it to a valid Hibernate session by calling the load, refresh, merge, update and save methods on the new session with a reference to the detached object.

Paging in Hibernate is also straightforward. There are two methods on the Query interface for implementing paging, setFirstResult and setMaxResult methods. The setFirstResult method takes an integer that represents the first row in the result set starting with 0. The setMaxResults method specifies how many rows must be retrieved by the operation (see Listing 10).

Query qryDepartments = session.createQuery(“from Department”);qryDepartments.setFirstResult(1);

qryDepartments.setMaxResults(10);

Listing 10

In order to sort your query results, you will need to use the sort by clause. You can order the result by either ascending (asc) or descending (desc) (see Listing 11).

Query objQuery = session.createQuery(“from Department d where d.location=:location order by d.deptno desc”);

Listing 11

Hibernate also supports join operations. The operations supported by Hibernate are inner join, cross join, left outer join, right outer join, and full outer join.

Batch updates on Hibernate are very straightforward by using the executeUpdate method for executing SQL statements. This method returns an integer value that contains the number of rows affected by the operation. Let’s supposed that we want to raise 10% the salary to employees using a batch update, then we execute the following code (see Listing 12).

Query qryRaiseSalary = session.createQuery(“update Employee set salary=salary*1.1”);int nRowCount = qryRaiseSalary.executeUpdate();

Listing 12

Getting started with Linq to SQL the examples

In order to illustrate the ORM concepts using Linq to SQL technology, we’re going to create a console project in Microsoft Visual Studio.NET 2008. As the back-end database, we’re going to use the AdventureWorks database shipped with Microsoft SQL Server 2005/2008 as well as the Production.Product. We’re going to explain the operations on the data source using Linq to SQL similar as we do in the Hibernate cases.

Next step is to add a “Linq to SQL” artifact to the project by selecting the Project | Add New Item menu option (see Figure 13).

Figure 13

Modeling the business entities

After that, the Object Relational (O/R) designer is launched which enables to model the classes that represent the underlying data model and the methods for each stored procedure in the back-end database system. It will also create a strongly typed DataContext class (the ProductionDataContext class).

Unlike the DataSet/TableAdapter approach, when we’re defining the entity classes in the designer, we don’t have to specify the SQL queries; instead we have to focus on defining the entity classes and the mapping of these classes to the underlying data model. SQL to Linq framework will generate the appropriate SQL statements at runtime when you interact and use the business entities.

In order to create the business entities, the easy way is to open a database connection in the Server Explorer windows, select the tables and views you want to model and map from it, and drag and drop them onto the designer surface.

In this case, drag and drop the Production.Product table on the designer surface (see Figure 14). After that you can see the Product business entity.

Figure 14

Let’s see a part of the generated Product class mapping back to the Production.Product table on the data source by exposing properties that represent the fields and the relationships (see Listing 13).

      [Table(Name=”Production.Product”)]public partial class Product : INotifyPropertyChanging, INotifyPropertyChanged

{

private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

private int _ProductID;

private string _Name;

private string _ProductNumber;

private bool _MakeFlag;

private bool _FinishedGoodsFlag;

private string _Color;

private short _SafetyStockLevel;

private short _ReorderPoint;

private decimal _StandardCost;

private decimal _ListPrice;

private string _Size;

private string _SizeUnitMeasureCode;

private string _WeightUnitMeasureCode;

private System.Nullable<decimal> _Weight;

private int _DaysToManufacture;

private string _ProductLine;

private string _Class;

private string _Style;

private System.Nullable<int> _ProductSubcategoryID;

private System.Nullable<int> _ProductModelID;

private System.DateTime _SellStartDate;

private System.Nullable<System.DateTime> _SellEndDate;

private System.Nullable<System.DateTime> _DiscontinuedDate;

private System.Guid _rowguid;

private System.DateTime _ModifiedDate;

#region Extensibility Method Definitions

partial void OnLoaded();

partial void OnValidate(System.Data.Linq.ChangeAction action);

partial void OnCreated();

partial void OnProductIDChanging(int value);

partial void OnProductIDChanged();

partial void OnNameChanging(string value);

partial void OnNameChanged();

partial void OnProductNumberChanging(string value);

partial void OnProductNumberChanged();

partial void OnMakeFlagChanging(bool value);

partial void OnMakeFlagChanged();

partial void OnFinishedGoodsFlagChanging(bool value);

partial void OnFinishedGoodsFlagChanged();

partial void OnColorChanging(string value);

partial void OnColorChanged();

partial void OnSafetyStockLevelChanging(short value);

partial void OnSafetyStockLevelChanged();

partial void OnReorderPointChanging(short value);

partial void OnReorderPointChanged();

partial void OnStandardCostChanging(decimal value);

partial void OnStandardCostChanged();

partial void OnListPriceChanging(decimal value);

partial void OnListPriceChanged();

partial void OnSizeChanging(string value);

partial void OnSizeChanged();

partial void OnSizeUnitMeasureCodeChanging(string value);

partial void OnSizeUnitMeasureCodeChanged();

partial void OnWeightUnitMeasureCodeChanging(string value);

partial void OnWeightUnitMeasureCodeChanged();

partial void OnWeightChanging(System.Nullable<decimal> value);

partial void OnWeightChanged();

partial void OnDaysToManufactureChanging(int value);

partial void OnDaysToManufactureChanged();

partial void OnProductLineChanging(string value);

partial void OnProductLineChanged();

partial void OnClassChanging(string value);

partial void OnClassChanged();

partial void OnStyleChanging(string value);

partial void OnStyleChanged();

partial void OnProductSubcategoryIDChanging(System.Nullable<int> value);

partial void OnProductSubcategoryIDChanged();

partial void OnProductModelIDChanging(System.Nullable<int> value);

partial void OnProductModelIDChanged();

partial void OnSellStartDateChanging(System.DateTime value);

partial void OnSellStartDateChanged();

partial void OnSellEndDateChanging(System.Nullable<System.DateTime> value);

partial void OnSellEndDateChanged();

partial void OnDiscontinuedDateChanging(System.Nullable<System.DateTime> value);

partial void OnDiscontinuedDateChanged();

partial void OnrowguidChanging(System.Guid value);

partial void OnrowguidChanged();

partial void OnModifiedDateChanging(System.DateTime value);

partial void OnModifiedDateChanged();

#endregion

public Product()

{

OnCreated();

}

[Column(Storage=”_ProductID”, AutoSync=AutoSync.OnInsert, DbType=”Int NOT NULL IDENTITY”, IsPrimaryKey=true, IsDbGenerated=true)]

public int ProductID

{

get

{

return this._ProductID;

}

set

{

if ((this._ProductID != value))

{

this.OnProductIDChanging(value);

this.SendPropertyChanging();

this._ProductID = value;

this.SendPropertyChanged(“ProductID”);

this.OnProductIDChanged();

}

}

}

[Column(Storage=”_Name”, DbType=”NVarChar(50) NOT NULL”, CanBeNull=false)]

public string Name

{

get

{

return this._Name;

}

set

{

if ((this._Name != value))

{

this.OnNameChanging(value);

this.SendPropertyChanging();

this._Name = value;

this.SendPropertyChanged(“Name”);

this.OnNameChanged();

}

}

}

……

Listing 13

You see that the Product class is decorated with the Table attribute pointing to the underlying database table. As well as this class inherits from INotifyPropertyChanging and INotifyPropertyChanged interfaces which are used by the DataContext based class to track when data is dirty or need to be refreshed. Then every attribute of the Product class is decorated by the Column attribute. The Column attribute establishes the primary key, if it’s a surrogate key (auto-generated), as well as the data type and underlying information such as nullability and other constraint checks.

The other important class is the DataContext based class which is the core channel used to communicate with the data source. It contains the properties and methods for interacting with the database tables added on the designer (see Listing 14). This class is decorated with the System.Data.Linq.DatabaseAttributte attribute to establish which database to connect on the SQL server.

      [System.Data.Linq.Mapping.DatabaseAttribute(Name=”AdventureWorks”)]public partial class ProductionDataContext : System.Data.Linq.DataContext

{

private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();

#region Extensibility Method Definitions

partial void OnCreated();

partial void InsertProduct(Product instance);

partial void UpdateProduct(Product instance);

partial void DeleteProduct(Product instance);

#endregion

public ProductionDataContext() :

base(global::LinqToSqlTestConsApp.Properties.Settings.Default.AdventureWorksConnectionString, mappingSource)

{

OnCreated();

}

public ProductionDataContext(string connection) :

base(connection, mappingSource)

{

OnCreated();

}

public ProductionDataContext(System.Data.IDbConnection connection) :

base(connection, mappingSource)

{

OnCreated();

}

public ProductionDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource) :

base(connection, mappingSource)

{

OnCreated();

}

public ProductionDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource) :

base(connection, mappingSource)

{

OnCreated();

}

public System.Data.Linq.Table<Product> Products

{

get

{

return this.GetTable<Product>();

}

}

}

Listing 14

The final aspect is the DBML file which contains the connection string, the provider information and the metadata mappings to the Production.Product table (see Listing 15).

<?xml version=”1.0″ encoding=”utf-8″?><Database Name=”AdventureWorks” xmlns=”http://schemas.microsoft.com/linqtosql/dbml/2007″&gt;

<Connection Mode=”AppSettings” ConnectionString=”Data Source=remote_server;Initial Catalog=AdventureWorks;Integrated Security=True” SettingsObjectName=”LinqToSqlTestConsApp.Properties.Settings” SettingsPropertyName=”AdventureWorksConnectionString” Provider=”System.Data.SqlClient” />

<Table Name=”Production.Product” Member=”Products”>

<Type Name=”Product”>

<Column Name=”ProductID” Type=”System.Int32″ DbType=”Int NOT NULL IDENTITY” IsPrimaryKey=”true” IsDbGenerated=”true” CanBeNull=”false” />

<Column Name=”Name” Type=”System.String” DbType=”NVarChar(50) NOT NULL” CanBeNull=”false” />

<Column Name=”ProductNumber” Type=”System.String” DbType=”NVarChar(25) NOT NULL” CanBeNull=”false” />

<Column Name=”MakeFlag” Type=”System.Boolean” DbType=”Bit NOT NULL” CanBeNull=”false” />

<Column Name=”FinishedGoodsFlag” Type=”System.Boolean” DbType=”Bit NOT NULL” CanBeNull=”false” />

<Column Name=”Color” Type=”System.String” DbType=”NVarChar(15)” CanBeNull=”true” />

<Column Name=”SafetyStockLevel” Type=”System.Int16″ DbType=”SmallInt NOT NULL” CanBeNull=”false” />

<Column Name=”ReorderPoint” Type=”System.Int16″ DbType=”SmallInt NOT NULL” CanBeNull=”false” />

<Column Name=”StandardCost” Type=”System.Decimal” DbType=”Money NOT NULL” CanBeNull=”false” />

<Column Name=”ListPrice” Type=”System.Decimal” DbType=”Money NOT NULL” CanBeNull=”false” />

<Column Name=”Size” Type=”System.String” DbType=”NVarChar(5)” CanBeNull=”true” />

<Column Name=”SizeUnitMeasureCode” Type=”System.String” DbType=”NChar(3)” CanBeNull=”true” />

<Column Name=”WeightUnitMeasureCode” Type=”System.String” DbType=”NChar(3)” CanBeNull=”true” />

<Column Name=”Weight” Type=”System.Decimal” DbType=”Decimal(8,2)” CanBeNull=”true” />

<Column Name=”DaysToManufacture” Type=”System.Int32″ DbType=”Int NOT NULL” CanBeNull=”false” />

<Column Name=”ProductLine” Type=”System.String” DbType=”NChar(2)” CanBeNull=”true” />

<Column Name=”Class” Type=”System.String” DbType=”NChar(2)” CanBeNull=”true” />

<Column Name=”Style” Type=”System.String” DbType=”NChar(2)” CanBeNull=”true” />

<Column Name=”ProductSubcategoryID” Type=”System.Int32″ DbType=”Int” CanBeNull=”true” />

<Column Name=”ProductModelID” Type=”System.Int32″ DbType=”Int” CanBeNull=”true” />

<Column Name=”SellStartDate” Type=”System.DateTime” DbType=”DateTime NOT NULL” CanBeNull=”false” />

<Column Name=”SellEndDate” Type=”System.DateTime” DbType=”DateTime” CanBeNull=”true” />

<Column Name=”DiscontinuedDate” Type=”System.DateTime” DbType=”DateTime” CanBeNull=”true” />

<Column Name=”rowguid” Type=”System.Guid” DbType=”UniqueIdentifier NOT NULL” CanBeNull=”false” />

<Column Name=”ModifiedDate” Type=”System.DateTime” DbType=”DateTime NOT NULL” CanBeNull=”false” />

</Type>

</Table>

</Database>

Listing 15

Linq to SQL enables modeling stored procedures as methods of the DataContext class. Let’s suppose we need to return a list of a product based on a given product subcategory id (see Listing 15).

create procedure spSelectProductBySubcategory@pSubcategoryId int

as

begin

select *

from Production.Product

where ProductSubcategoryID=@pSubcategoryId;

end;

go

Listing 16

Now we can use the Server Explorer windows to drag and drop this stored procedure on the in the right pane of the designer surface (see Figure 3).

Figure 15

Executing CRUD operations using Linq to SQL

Now that we have defined our object model representing the data model, we are ready to execute CRUD (create, read, update, delete) operations over the relational data schema through the object model in C#.

The first example is to display a list of the products in the database (see Listing 17). The first step is to create a ProductionDataContext instance and then develop a Linq query similar to SQL to return the list of products based on the product makeflag equals to true. In this case the where clause enables filtering features on the query. Notice that the filter expression follows the C# syntax rather the SQL syntax, in this case, the comparison uses the “==” logical operator rather than the “=” logical operator. The result is stored in the objResultset object which is defined by using the var keyword to define a strongly type compile time variable reference by inferring the type at compile time. You can also see that a relational projection operation is achieved by using the new features of C# language such as anonymous type and object initialization in order to return a subset of the fields. Anonymous types enable defining an inline class without having to explicitly declare it.

using System;using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LinqToSqlTestConsApp

{

public class Program

{

static void Main(string[] args)

{

ProductionDataContext objDataContext = new ProductionDataContext();

var objResultset = from objProduct in objDataContext.Products

where objProduct.MakeFlag == true

select new { ProductId= objProduct.ProductID, Number = objProduct.ProductNumber, Name= objProduct.Name, Color = objProduct.Color };

foreach (var objProduct in objResultset)

{

System.Console.WriteLine(“ProductId={0}, Product Number={1}, Name={2}, Color={3}”, objProduct.ProductId, objProduct.Number, objProduct.Name, objProduct.Color);

}

System.Console.WriteLine(“Press any key to finish …”);

System.Console.ReadKey();

}

}

}

Listing 17

Now let’s create a new product item (see Listing 19).

using System;using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LinqToSqlTestConsApp

{

public class Program

{

static void Main(string[] args)

{

ProductionDataContext objDataContext = new ProductionDataContext();

Product objProduct = new Product();

objProduct.Name = “Ad Race 11”;

objProduct.ProductNumber = “AR-53323”;

objProduct.MakeFlag = true;

objProduct.FinishedGoodsFlag = true;

objProduct.SafetyStockLevel = 100;

objProduct.ReorderPoint = 750;

objProduct.StandardCost = 0;

objProduct.DaysToManufacture = 0;

objProduct.ProductSubcategoryID = 22;

objProduct.ProductModelID = 31;

objProduct.SellStartDate = DateTime.Now;

objProduct.ModifiedDate = DateTime.Now;

objDataContext.Products.InsertOnSubmit(objProduct);

objDataContext.SubmitChanges();

System.Console.WriteLine(“Press any key to finish …”);

System.Console.ReadKey();

}

}

}

Listing 19

When you execute the SubmitChanges method of the DataContext, then all the updates to the data are wrapped in a transaction, so the underlying relational database will never be in an inconsistent state after updating the changes.

If no transaction is already in the scope, then the SubmitChanges method will automatically start a database transaction. You can also define your transaction scope using the TransactionScope object. This makes very easy to integrate your transactional code with existing one.

In the following step, we’re going to retrieve the newly created product item and update its Name field value (see Listing 20).

using System;using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LinqToSqlTestConsApp

{

public class Program

{

static void Main(string[] args)

{

ProductionDataContext objDataContext = new ProductionDataContext();

var objProduct = (from objProd in objDataContext.Products

where objProd.Name == “Ad Race 11”

select objProd).First();

objProduct.Name = “Ad Race 111”;

objDataContext.SubmitChanges();

System.Console.WriteLine(“Press any key to finish …”);

System.Console.ReadKey();

}

}

}

Listing 20

The last CRUD operation to test is the delete operation. Now we’re going to delete the created product item (see Listing 21).

using System;using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace LinqToSqlTestConsApp

{

public class Program

{

static void Main(string[] args)

{

ProductionDataContext objDataContext = new ProductionDataContext();

var objProduct = (from objProd in objDataContext.Products

where objProd.Name == “Ad Race 111”

select objProd).First();

objDataContext.Products.DeleteOnSubmit(objProduct);

objDataContext.SubmitChanges();

System.Console.WriteLine(“Press any key to finish …”);

System.Console.ReadKey();

}

}

}

Listing 21

Now let’s call for the stored procedure defined in the Listing 1 (see Listing 6).

ProductionDataContext objDataContext = new ProductionDataContext();var arrProduct = objDataContext.spSelectProductBySubcategory(1);

Listing 22

In order to implement database paging in Linq to SQL, we need to use the Skip and Take methods (see Listing 7).

ProductionDataContext objDataContext = new ProductionDataContext();var objProductSubcategory = (from objProdSubc in objDataContext.ProductSubcategories

where objProdSubc.ProductSubcategoryID == 2

select objProdSubc).Skip(200).Take(10);

Listing 23

Conclusion

In this article, I’ve covered the principles, techniques and tools to write persistent layers using DLinq and Hibernate technologies.

Scalability

Scalability is the system’s ability to accept higher load (to grow) without degradation is called scalability. It´s one quality attribute to take in consideration in the architectural definition of enterprise applications. From my perspective, it´s one of the most important because bad architectural decisions that impact negatively in product scalability; it also impacts negatively in the growth of the product as well as in the growth of the enterprise which supports its business process in the underlying enterprise application. So it´s important to follow good architectural decisions on the product design to impact positively on the scalability.

Scalable hardware or software can expand to support increasing workloads. This capability allows computer equipment and software programs to grow over time, rather than needing to be replaced. Scalable software typically refers to business applications that can adapt to support an increasing amount of data or a growing number of users.

In order to impact positively the scalability of an enterprise application, we need to follow best practices. I will explain a bunch of techniques that I´ve applied during my career as a software architect to support correctly software scalability as well as I´ve confirmed by researching about this topic on these days.

The rationale behind the techniques is to split your application logic into several modules and sub-systems according to the principle of separation of responsability and the premise that if you can´t split it, you can´t scale it. Related pieces of functionality must belong together, while unrelated pieces of functionality must belong apart. Splitting your solution artifacts assures that the workload can be broken down into manageable units. These components must be decoupled and communicate each other asynchronously as much as possible.

At the application tier is implemented by the following techniques:

  • applications in different application pool. This allows scaling each pool of processes and servers, according to the demand and resource consumption. Applications are further divided by sub-systems and components on separated processes or set of nodes (distributed processing)
  • decoupling the components in different modules and sub-systems according to its responsability in the solution
  • avoid synchronous communication (coupling) between the components as much as possible. Once the components are decoupled, then these components must communicate each other using asynchronous mechanisms using queues, multicast messages, ESB, batch process, so they can be scaled independently. The rationale is that if component A calls to component B synchronously (they´re tighly coupled), if you need to scale component A, you must also scale component B. Equally, this coupling impacts negatively on the availability of the system (if component B is not available, then component A may fail in its behavior)
  • farm of applications using clustering and load-balancer techniques (if we need more processing power, we just add another node)
  • business logic optimization (refactoring)
  • application hosting environment tuning
  • caching techniques (memcache)
  • avoid distributed transactions

At the database tier is implemented by the following techniques:

  • sharding (partitioning) the data horizontally and vertically
  • running each partition on separated RDBMS or set of nodes
  • farm of RDBMS using clustering and load-balancer techniques (if we need more processing power, we just add another node)
  • optimization techniques (DBMS tuning, indexes)

At the infrastructure tier is implemented by the following techniques:

  • OS tuning
  • Storage system tuning
  • Hardware optimization

In this article, I´ve covered the key concepts and principles of scalability in enterprise applications as well as a bunch of techniques that I´ve applied to impact positively in this important quality attribute.

Load data on forms with ExtJS and ASPNET MVC

Introduction

Now I’ve followed researching a lot about ExtJS support for rich Internet applications and nice user experience and the more I read about this library, the more I like it. S, I’ve decided to write this article to illustrate how to create an edit form in ExtJS and integrated with ASP.NET MVC framework. After researching a lot in order to know how to get request parameter from the URL string using Ext libraries, I’ve developed my own solution.

Getting started with the solution

We’re going to implement the Edit Employee use case for a Human Resources Management system. The Edit Employee use case description is as follows: A screen prompts the user to update valid information (whether optional or mandatory) for an existing employee such as employee identifier, full name, address, age, salary and department. The screen shows employee information by the employee identifier passed by the screen parameters.

This use case fits well to illustrate the main artifacts and steps for a solution using ExtJS and ASP.NET. The implementation strategy for this use case is to create an ExtJS form on the client-side to load data and send the updated data to the server to be processed. The server-side application is developed using ASP.NET MVC framework. The persistence layer will be Linq to represent business entities and to persist data to the database system. As the development environment we’re going to use Microsoft Visual Studio.NET 2008 and as the database system Microsoft SQL Server 2005/2008.

Open Visual Studio.NET 2008 and create an ASP.NET MVC application (see Figure 1).

Figure 1

Next step is to create the database schema for the solution. Our schema will contain two entities: employee and department. Let’s create the HumanResources database and the underlying tables and its constraints in order to maintain the data integrity. For this example, we also need some data on the tables (see Listing 1).

 

create table department

(

deptno varchar(20) primary key,

deptname varchar(50) not null,

location varchar(50)

);

create unique index undx_department_deptname on department(deptname);

 

insert into department

values(‘HQ-200′,’Headquarter-NY’,’New York’);

insert into department

values(‘HR-200′,’Human Resources-NY’,’New York’);

insert into department

values(‘OP-200′,’Operations-NY’,’New York’);

insert into department

values(‘SL-200′,’Sales-NY’,’New York’);

insert into department

values(‘HR-300′,’Human Resources-MD’,’Maryland’);

insert into department

values(‘OP-300′,’Operations-MD’,’Maryland’);

insert into department

values(‘SL-300′,’Sales-MD’,’Maryland’);

 

create table employee

(

empno varchar(20) primary key,

fullname varchar(50) not null,

address varchar(120),

age int,

salary numeric(8,2) not null,

deptno varchar(20) not null,

constraint fk_employee_department_belong_rltn foreign key(deptno)

references department(deptno)

);

create unique index undx_employee_fullname on employee(fullname);

 

insert into employee

values(‘EMP-0001′,’John Doe’,’20 Madison St.’, 32, 3000.99, ‘HQ-200’);

Listing 1

Then let’s create a Linq to SQL Classes item inside the Model folder to define the structure of the entities and the persistence mechanism. The object definition in Linq to SQL is shown in the Figure 2.

Figure 2

Next step is to develop the EmployeeRepository class to manage the data access logic to the employee table (CRUD operations). Regarding to our use case, we only need to implement the read by employee identifier and update operations (see Listing 2).

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

 

namespace LoadDataOnForm_ExtJS_ASPNETMVC.Models

{

public class EmployeeRepository

{

private HumanResourcesDataContext _ctxHumanResources = new HumanResourcesDataContext();

 

public employee FindByKey(string empno)

{

return (from emp in this._ctxHumanResources.employees

where emp.empno == empno

select emp).SingleOrDefault();

}

 

public void Update(employee employee)

{

var origEmployee = this.FindByKey(employee.empno);

origEmployee.fullname = employee.fullname;

origEmployee.address = employee.address;

origEmployee.age = employee.age;

origEmployee.salary = employee.salary;

origEmployee.deptno = employee.deptno;

 

this._ctxHumanResources.SubmitChanges();

}

}

}

Listing 2

Now that we have defined the business logic’s artifacts, that is the business entities and the services that process the entities, we need to move onto the presentation layer. The implementation strategy for the presentation layer is ASP.NET MVC. MVC stands for model-view-controller. We have worked on the model piece of the architecture before. Now let’s define another important piece of the architecture: the controller.

Right-click on the Controllers folder in the Solution Explorer window and select Add|Controller option from the context menu. Set EmployeeController as the name (see Figure 3).

Figure 3

Now let’s go to the presentation piece to define the graphical interface using ExtJS JavaScript library. The first step is to download and copy the distribution of ExtJS inside the Scripts directory. For our solution, we only need ext-all.js file, ext-base.js file and the resources directory (see Figure 4).

Figure 4

Now let’s include this library in our project. For this purpose, let’s go to the Site.Master page and adding the references to the ExtJS files inside the head HTML element (highlighted in yellow in the Figure 14). As well, we need to add a <asp:ContentPlaceHolder> tag element as container of the customized JavaScript and CSS code for each page (highlighted in green in the Listing 5).

<head runat=”server”>

<title><asp:ContentPlaceHolder ID=”TitleContent” runat=”server” /></title>

<link href=”../../Content/Site.css” rel=”stylesheet” type=”text/css” />

 

<!– Include the ExtJS framework –>

<link href=”../../Scripts/ext/resources/css/ext-all.css” rel=”stylesheet” type=”text/css” />

<script type=”text/javascript” src=”../../Scripts/ext/ext-base.js”></script>

<script type=”text/javascript” src=”../../Scripts/ext/ext-all.js”></script>

<!– Placeholder to include CSS and JS files customized for each page –>

<asp:ContentPlaceHolder ID=”Scripts” runat=”server” />

</head>

Figure 5

Now let’s add the view to present the form to edit the data related to one employee. Go to the EmployeeController controller and right-click on the Index action method and select Add View option from the context menu. Click on the Add button on Add View dialog box (see Figure 6).

Figure 6

In order to implement the ExtJS form, we need to add a JavaScript file to the Scripts directory (see Figure 7).

Figure 7

Then include the JavaScript file and add a div element (with id=employeeeditform) into the Index.aspx view (see Listing 4).

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage” %>

 

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

Index

</asp:Content>

 

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

 

<h2>Edit Employee form</h2>

<div id=”employeeeditform”></div>

 

</asp:Content>

 

<asp:Content ID=”Content3″ ContentPlaceHolderID=”Scripts” runat=”server”>

<script type=”text/javascript” src=”../../Scripts/employee_editform.js”></script>

</asp:Content>

 

Listing 3

Now it’s time to go to the employee_editform.js file and write some code in JavaScript to configure the ExtJS form and its underlying widgets.

The first step is to define the form. The properties are self-descriptive. In this case, the url property points to the UpdateEmployee action method on the EmployeeController controller. This method is also accessed using POST HTTP verb (see Listing 6).

var form= new Ext.FormPanel({

title:’Edit Employee Form’,

renderTo: ’employeeeditform’,

width: 400,

url:’employee/updateemployee’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

Listing 4

The items property is the list of widgets for the fields of the form. Here the default widget is textfield (this is specified in the defaults property). The first field is employee number which is required (specified by the allowBlank property) textfield. The second field is the fullname which is also a required textfield. The address field is an option textarea. The age field is an optional numberfield. The salary field is a required numberfield. And finally, the department number field (see Listing 7).

          items:[

{fieldLabel:’Employee ID’,name:’empno’, allowBlank:false},

{fieldLabel: ‘Fullname’,name: ‘fullname’, allowBlank:false},

{xtype: ‘textarea’,fieldLabel: ‘Address’,name: ‘address’,multiline: true},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype:’numberfield’,fieldLabel:’Salary’,name:’salary’, allowBlank:false},

{fieldLabel: ‘Department ID’,name: ‘deptno’, allowBlank:false}

],

Listing 5

Then the buttons property is defined (see Listing 8). As you can see in order to save button will submit the data (each field and its value will be posted in the request parameter). This can be analyzed in details in my previous articles about forms in ExtJS and the way to submit its data. In this article, we don’t implement the UpdateEmployee action in the Employee controller in order to focus on the loading data logic.

        buttons: [{

text: ‘Save’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

Listing 6

And the final ExtJS code is to load the initial data for the employee by passing the employee identifier by the id parameter.  After researching about getting request parameter from the URL string using Ext JS libraries, I have not found any code exceprt with the solution. The only thing that I’ve found is a little function written in pure JavaScript. After thinking myself about the problem nature, I’ve found out that the solution can’t be in any JavaScript code because the responsibility to process HTML request along with the request parameters resides in the server-side of the solution. So, I’ve figured out my own solution using global variables in JavaScript along with HTML request process model in ASP.NET MVC . The first step is to define a global JavaScript variable and assigned the value of the employee identifier taking from the request parameters. We do this by defining the global variable (before including the employee_editform.js library) in the script section of the Listing 3 in the Index.aspx view of the Index action in Employee controller (see highlighted in yellow in the Listing 7).

<asp:Content ID=”Content3″ ContentPlaceHolderID=”Scripts” runat=”server”>

<script type=”text/javascript”>

var emp_id = ‘<%=Request[“emp_id”] %>’;

</script>

<script type=”text/javascript” src=”../../Scripts/employee_editform.js”></script>

</asp:Content>

Listing 7

The next step is to define the data load ExtJS load logic to load data from the GetEmployee action in the Employee controller and specify to send the employee identifier by the request parameter empno and the value of empno request parameter is taken from the previous defined global variable emp_id as shown highlighted in yellow in the Listing 8.

    form.getForm().load({

url: ‘/employee/getemployee’,

method: ‘GET’,

params: {’empno’: emp_id},

failure: function(form, action) {

Ext.Msg.alert(“Load employee data failed”, action.result.errorMessage);

}

});

Listing 8

Then, you have the complete employee_editform.js file (see Listing 8).

Ext.ns(’employeeditform’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

employeeditform.FormTutorial = {

init: function(){

//Begin of code   here

Ext.QuickTips.init();

var form= new Ext.FormPanel({

title:’Edit Employee Form’,

renderTo: ’employeeeditform’,

width: 400,

url:’/employee/updateemployee’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Employee ID’,name:’empno’, allowBlank:false},

{fieldLabel: ‘Fullname’,name: ‘fullname’, allowBlank:false},

{xtype: ‘textarea’,fieldLabel: ‘Address’,name: ‘address’,multiline: true},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype:’numberfield’,fieldLabel:’Salary’,name:’salary’, allowBlank:false},

{fieldLabel: ‘Department ID’,name: ‘deptno’, allowBlank:false}

],

buttons: [{

text: ‘Save’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

form.getForm().load({

url: ‘/employee/getemployee’,

method: ‘GET’,

params: {’empno’: emp_id},

failure: function(form, action) {

Ext.Msg.alert(“Load employee data failed”, action.result.errorMessage);

}

});

//End of code here

}

}

 

Ext.onReady(employeeditform.FormTutorial.init,employeeditform.FormTutorial);

 

Listing 9

Now let’s go to the EmployeeController controller and implement the corresponding action methods (see Listing 10).

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Ajax;

using LoadDataOnForm_ExtJS_ASPNETMVC.Models;

 

namespace LoadDataOnForm_ExtJS_ASPNETMVC.Controllers

{

public class EmployeeController : Controller

{

private EmployeeRepository _repoEmployee = new EmployeeRepository();

 

//

// GET: /Employee/

 

public ActionResult Index()

{

return View();

}

 

//

// GET: /Employee/GetEmployee

[AcceptVerbs(HttpVerbs.Get)]

public ActionResult GetEmployee(string _dc, string empno)

{

try

{

var objEmployee = this._repoEmployee.FindByKey(empno);

var results = (new

{

success = “true”,

data = (new

{

empno = objEmployee.empno,

fullname = objEmployee.fullname,

address = objEmployee.address,

age = objEmployee.age,

salary = objEmployee.salary,

deptno = objEmployee.deptno

})

});

return Json(results);

}

catch (Exception)

{

var results = (new

{

success = “false”,

errorMessage = “Employee not found”

});

return Json(results);

}

}

 

//

// POST: /Employee/UpdateEmployee

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult UpdateEmployee(employee employee)

{

string strResponse = String.Empty;

try

{

this._repoEmployee.Update(employee);

strResponse = “{success: true}”;

}

catch (Exception)

{

strResponse = “{success: false, error: \”An error occurred\”}”;

}

return Content(strResponse);

}

}

}

 

 

Listing 10

Now let’s run the solution (see Figure 8). You can see that we have sent the employer identifier EMP-0001 using the emp_id request parameter in the URL string.

Figure 8

Conclusion

In this article, I’ve illustrated how to create an edit form in ExtJS and integrated with ExtJS JavaScript library and ASP.NET MVC framework.

Grid with Ajax, ExtJS and ASP.NET MVC

Introduction

In this article I want to cover a very good feature of ExtJS JavaScript library. I like a lot the use of ExtJS for the client scripting. This is the creation of very good experience grid with paging and sorting techniques. This is a common requirement in any enterprise application where we need to display a list of business entities in a fancy way. ExtJS, which is a very good JavaScript library for the development of client-side components in Web applications, has support for grid with paging and sorting with a very good look and feel providing a nice user experience. In this article, I will illustrate step by step how to implement a listing requirement using a paging and sorting grid, ExtJS and ASP.NET MVC.

Getting started with the solution

The first step is to open Visual Studio.NET 2008 and create an ASP.NET MVC Web application (see Figure 1).

 

Figure 1

In order to distribute the ExtJS libraries into our project, we need to create a directory named ext in the Scripts directory in the project and copy the following files and directories from the latest ExtJS distribution: ext-base.js file, ext-all.js file from the adapter/ext directory, and the resources directory. Then, you must include these artifacts in your project (see Figure 2).

 

Figure 2

Next step is to include the supporting ExtJS files in your project in a common place as the Site.Master file. This must be included inside the head element. We also need to include a new asp:ContentPlaceHolder to include the scripts particular for each page. We need to comment the default styles in ASP.NET MVC (highlighted in yellow in the Listing 1), because they make the ExtJS grid to look odd, for example, the columns of the grid don’t align with the underlying data and the styles of ExtJS don’t apply well. I need to research about this strange issue later (see Listing 1).

<head runat=”server”>

    <title><asp:ContentPlaceHolder ID=”TitleContent” runat=”server” /></title>

    <!–

    <link href=”../../Content/Site.css” rel=”stylesheet” type=”text/css” />

    –>

    <link href=”../../Scripts/ext/resources/css/ext-all.css” rel=”stylesheet” type=”text/css” />

      <script src=”../../Scripts/ext/ext-base.js” type=”text/javascript”></script>

      <script src=”../../Scripts/ext/ext-all.js” type=”text/javascript”></script>

    <asp:ContentPlaceHolder ID=”Scripts” runat=”server” />

</head>

Listing 1

Next step is to define the domain model for the enterprise application. We’re going to display a list of products and support paging and sorting techniques. The information related to the Product entity is stored in the Production.Product table on the AdventureWorks database. As the persistent layer, we’re going to use Linq to SQL technology, so right-click on the model directory on the solution and select Add | New Item option from the context menu and create a Linq to SQL classes artifact (see Figure 3).

 

Figure 3

Then create the definition of the Product entity (see Figure 4).

 

Figure 4

Next step is to create the DAL component with the CRUD operations by implementing the Repository design pattern. According to our use case, we just need a list of products, so we define two methods: one for getting the total number of products, and the other one to get the underlying list of products. You can see that we have added support to paging and sorting techniques in our GetAllProducts method in order to get a list of products more efficiently (see Listing 2).

using System;

using System.Collections.Generic;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Linq.Dynamic;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

 

namespace GridAjaxExtJSMvcApp.Models

{

    public class ProductsRepository

    {

        private ProductsDataContext _productDataContext = new ProductsDataContext();

 

        public int GetCount()

        {

            return this._productDataContext.Products.Count();

        }

 

        public IQueryable<Product> GetAllProducts(int nStartRow, int nRowCount, string strSort, string strSortDir)

        {

            IQueryable<Product> qryProducts = from product in this._productDataContext.Products

                                              orderby product.ProductID

                                              select product;

            string strCriteria = strSort + ” ” + strSortDir;

            return qryProducts.OrderBy(strCriteria).Skip(nStartRow).Take(nRowCount);

        }

    }

}

Listing 2

In the code in the Listing 2, you can see that we are using dynamic queries in Linq to SQL, that is, converting strings to SQL queries that can be parsed into an expression tree. Because creating dynamic queries in Linq is not a very trivial task, we’re going to use a library written in C# which can be downloaded from http://msdn2.microsoft.com/en-us/vcsharp/bb894665.aspx. After that, I create a Class Library project include the Dynamic.cs file and compile in order to create a distributable assembly. After that, we need to include this assembly and add the “using System.Linq.Dynamic;” statement to our code. Finally, let create a dynamic sort criteria in a string and use this criteria in the OrderBy method of the Linq query (highlighted in yellow in the Listing 2).

Next step is to add a controller to our application to handle the HTTP request in order to get the list of products and displaying them. Right-click on the controller folder and select Add | Controller option from the context menu. Let’s call this controller ProductController (see Figure 5).

 

Figure 5

Then, we need to create a view for each Index action method (the default action method) of this controller, so right-click on this method and select Add View option from the context menu for defining the view (see Figure 6).

 

Figure 6

Then the Index.aspx view inside the Views/Products directory is created. We’re going to display a list of products using ExtJS grid support, so we need to create a JavaScript file inside the Scripts folder and reference it from this view inside asp:Content tag to be included in the final HTML output (highlighted in yellow). We also need to add a container for the ExtJS grid using the div element (highlighted in green) (see Listing 3).

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage” %>

 

<asp:Content ID=”Scripts” ContentPlaceHolderID=”Scripts” runat=”server”>

 

      <script src=”../../Scripts/productsgrid.js” type=”text/javascript”></script>

</asp:Content>

 

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

      Index

</asp:Content>

 

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

 

    <h2>Products</h2>

    <div id=”gridProductList”></div>

</asp:Content>

Listing 3

Now it’s the time to work hard with Ext libraries. You need to go to the http://www.extjs.com/products/extjs/ site and select the paging grid from the example. You can also see the examples in the examples directory in the ExtJS distribution. After that, we need to get the underlying JavaScript example file for this component. In this case, the JavaScript file is paging.js and the example code is shown in the following listing (see Listing 4).

/*!

 * Ext JS Library 3.0.3

 * Copyright(c) 2006-2009 Ext JS, LLC

 * licensing@extjs.com

 * http://www.extjs.com/license

 */

Ext.onReady(function(){

    // create the Data Store

    var store = new Ext.data.JsonStore({

        root: ‘topics’,

        totalProperty: ‘totalCount’,

        idProperty: ‘threadid’,

        remoteSort: true,

 

        fields: [

            ‘title’, ‘forumtitle’, ‘forumid’, ‘author’,

            {name: ‘replycount’, type: ‘int’},

            {name: ‘lastpost’, mapping: ‘lastpost’, type: ‘date’, dateFormat: ‘timestamp’},

            ‘lastposter’, ‘excerpt’

        ],

        // load using script tags for cross domain, if the data in on the same domain as

        // this page, an HttpProxy would be better

        proxy: new Ext.data.ScriptTagProxy({

            url: ‘http://extjs.com/forum/topics-browse-remote.php&#8217;

        })

    });

    store.setDefaultSort(‘lastpost’, ‘desc’);

    // pluggable renders

    function renderTopic(value, p, record){

        return String.format(

                ‘<b><a href=”http://extjs.com/forum/showthread.php?t={2}” target=”_blank”>{0}</a></b><a href=”http://extjs.com/forum/forumdisplay.php?f={3}” target=”_blank”>{1} Forum</a>’,

                value, record.data.forumtitle, record.id, record.data.forumid);

    }

    function renderLast(value, p, r){

        return String.format(‘{0}<br/>by {1}’, value.dateFormat(‘M j, Y, g:i a’), r.data[‘lastposter’]);

    }

    var grid = new Ext.grid.GridPanel({

        width:700,

        height:500,

        title:’ExtJS.com – Browse Forums’,

        store: store,

        trackMouseOver:false,

        disableSelection:true,

        loadMask: true,

        // grid columns

        columns:[{

            id: ‘topic’, // id assigned so we can apply custom css (e.g. .x-grid-col-topic b { color:#333 })

            header: “Topic”,

            dataIndex: ‘title’,

            width: 420,

            renderer: renderTopic,

            sortable: true

        },{

            header: “Author”,

            dataIndex: ‘author’,

            width: 100,

            hidden: true,

            sortable: true

        },{

            header: “Replies”,

            dataIndex: ‘replycount’,

            width: 70,

            align: ‘right’,

            sortable: true

        },{

            id: ‘last’,

            header: “Last Post”,

            dataIndex: ‘lastpost’,

            width: 150,

            renderer: renderLast,

            sortable: true

        }],

        // customize view config

        viewConfig: {

            forceFit:true,

            enableRowBody:true,

            showPreview:true,

            getRowClass : function(record, rowIndex, p, store){

                if(this.showPreview){

                    p.body = ‘<p>’+record.data.excerpt+'</p>’;

                    return ‘x-grid3-row-expanded’;

                }

                return ‘x-grid3-row-collapsed’;

            }

        },

        // paging bar on the bottom

        bbar: new Ext.PagingToolbar({

            pageSize: 25,

            store: store,

            displayInfo: true,

            displayMsg: ‘Displaying topics {0} – {1} of {2}’,

            emptyMsg: “No topics to display”,

            items:[

                ‘-‘, {

                pressed: true,

                enableToggle:true,

                text: ‘Show Preview’,

                cls: ‘x-btn-text-icon details’,

                toggleHandler: function(btn, pressed){

                    var view = grid.getView();

                    view.showPreview = pressed;

                    view.refresh();

                }

            }]

        })

    });

    // render it

    grid.render(‘topic-grid’);

    // trigger the data store load

    store.load({params:{start:0, limit:25}});

});

Listing 4

What we need is to adapt this to our own configuration. Copy the code in our productsgrid.js JavaScript file. Let’s start configuring. The Ext.onReady function is called when the DOM is ready to be used. It’s a good practice to configure all the ExtJS code in there, because we know that we can access safely to the DOM elements.

The first element to be configured is the data store object which is an Ext.data.JsonStore object. It defines the HTTP method to access to the data (GET, POST) and information about the object list serialization. The root property specifies the root of the list of entities in JSON format. The totalProperty property specifies how many records of the products there exist in the database. The id property specifies the primary key of the records. The remoteSort property specificies if we want to do a sort on the server. The method property specifies the HTTP method used to get the data. The url property specifies the url to the data source, in this case, it’s the same action to show the view on the controller but using the POST method. The fields property specifies the list of fields to display. This is a JavaScript array of objects. You need to specify the name and type of each element. The setDefaultSort method is self-descriptive. For our example, we have the following datastore element. Remember to delete the proxy: config on the original ExtJS grid file (see Listing 5).

    // create the Data Store

    var store = new Ext.data.JsonStore({

        root: ‘products’,

        totalProperty: ‘totalRecords’,

        id: “ProductID”,

        remoteSort: true,

        autoLoad: false,

        method: “POST”,

        url: “product”,

        fields: [ {name:’ProductID’, type:’int’},

                  {name:’Name’, type:’string’},

                  {name:’Color’, type: ‘string’},

                  {name:’ReorderPoint’, type:’float’},

                  {name:’StandardCost’, type:’float’},

                  {name:’ListPrice’, type:’float’}

        ]

    });

    store.setDefaultSort(‘ProductID’, ‘asc’);

Listing 5

Then we have to define two renders for custom output. The first one is to output the product name enclosed in a reference for its edition. The second one is the output of possible operations on each record, in this case, we can edit or delete each record (see Listing 6).

    // pluggable renders

    function renderProduct(value, p, record)

    {

        return String.format(

                ‘<span><b><a href=”product/edit/{1}” target=”_blank”>{0}</a></b></span>’,

                value, record.id);       

    }

 

    function renderOperations(value, p, record)

    {

        return String.format(

                ‘<span><b><a href=”product/edit/{0}” target=”_blank”>Edit</a></b></span><br/><span><b><a href=”product/delete/{0}” target=”_blank”>Delete</a></b></span>’,

                record.id);       

    }

Listing 6

Next element is the grid that shows the list of products which is an instance of Ext.grid.GridPanel. The width, height, autoheight,title, trackMouseOver, disableSelection, stripeRows, viewConfig and loadMask properties are self-descriptive. The store property is the reference to the JSON store defined before (see Listing 7).

        width:740,

        autoHeight: true,

        title:’List of Products’,

        store: store,

        stripeRows: true,

        autoload: true,

Listing 7

Then, the columns definition comes, and for each column we must specify the header, dataIndex, width, a renderer for the data, if sortable properties (see Listing 8).

        // grid columns

        columns:[{

            id: ‘ProductID’,

            header: “Name”,

            dataIndex: ‘Name’,

            width: 80,

            renderer: renderProduct,

            sortable: true

        },{

            header: “Price”,

            dataIndex: ‘ListPrice’,

            width: 40,

            renderer: Ext.util.Format.usMoney,

            align: “right”,

            sortable: true

        },{

            header: “Color”,

            dataIndex: ‘Color’,

            align: “center”,

            width: 40,

            sortable: true

        },{

            header: “Reorder Point”,

            dataIndex: ‘ReorderPoint’,

            width: 40,

            align: “right”,

            sortable: true

        }

        ,{

            header: “Standard Cost”,

            dataIndex: ‘StandardCost’,

            width: 40,

            renderer: Ext.util.Format.usMoney,

            align: “right”,

            sortable: true

        }

        ,{

            header: “Operations”,

            id: ‘ProductID’,

            width: 50,

            renderer: renderOperations,

            sortable: false,

            menuDisabled: true

        }       

        ],

Listing 8

Next we need to configure the grid view (see Listing 9).

        // customize view config

        viewConfig: {

            forceFit:true

        },

Listing 9

Next we go to configure the paging bar element (see Listing 10).

        // paging bar on the bottom

        bbar: new Ext.PagingToolbar({

            pageSize: 10,

            store: store,

            displayInfo: true,

            displayMsg: ‘Displaying products {0} – {1} of {2}’,

            emptyMsg: “No products to display”

        })

Listing 10

And finally, we need to set where the grid will be rendered and load the data (see Listing 11).

    // render it

    grid.render(‘gridProductList’);

    // trigger the data store load

    store.load({params:{start:0, limit:10}});

Listing 11

The whole code for the ExtJS grid is shown in the following list (see Listing 12).

 

Ext.onReady(function(){

 

    // create the Data Store

    var store = new Ext.data.JsonStore({

        root: ‘products’,

        totalProperty: ‘totalRecords’,

        id: “ProductID”,

        remoteSort: true,

        autoLoad: false,

        method: “POST”,

        url: “product”,

        fields: [ {name:’ProductID’, type:’int’},

                  {name:’Name’, type:’string’},

                  {name:’Color’, type: ‘string’},

                  {name:’ReorderPoint’, type:’float’},

                  {name:’StandardCost’, type:’float’},

                  {name:’ListPrice’, type:’float’}

        ]

    });

    store.setDefaultSort(‘ProductID’, ‘asc’);

 

 

    // pluggable renders

    function renderProduct(value, p, record)

    {

        return String.format(

                ‘<span><b><a href=”product/edit/{1}” target=”_blank”>{0}</a></b></span>’,

                value, record.id);       

    }

 

    function renderOperations(value, p, record)

    {

        return String.format(

                ‘<span><b><a href=”product/edit/{0}” target=”_blank”>Edit</a></b></span><br/><span><b><a href=”product/delete/{0}” target=”_blank”>Delete</a></b></span>’,

                record.id);       

    }   

 

    var grid = new Ext.grid.GridPanel({

        width:740,

        autoHeight: true,

        title:’List of Products’,

        store: store,

        stripeRows: true,

        autoload: true,

 

        // grid columns

        columns:[{

            id: ‘ProductID’,

            header: “Name”,

            dataIndex: ‘Name’,

            width: 80,

            renderer: renderProduct,

            sortable: true

        },{

            header: “Price”,

            dataIndex: ‘ListPrice’,

            width: 40,

            renderer: Ext.util.Format.usMoney,

            align: “right”,

            sortable: true

        },{

            header: “Color”,

            dataIndex: ‘Color’,

            align: “center”,

            width: 40,

            sortable: true

        },{

            header: “Reorder Point”,

            dataIndex: ‘ReorderPoint’,

            width: 40,

            align: “right”,

            sortable: true

        }

        ,{

            header: “Standard Cost”,

            dataIndex: ‘StandardCost’,

            width: 40,

            renderer: Ext.util.Format.usMoney,

            align: “right”,

            sortable: true

        }

        ,{

            header: “Operations”,

            id: ‘ProductID’,

            width: 50,

            renderer: renderOperations,

            sortable: false,

            menuDisabled: true

        }       

        ],

 

        // customize view config

        viewConfig: {

            forceFit:true

        },

 

        // paging bar on the bottom

        bbar: new Ext.PagingToolbar({

            pageSize: 10,

            store: store,

            displayInfo: true,

            displayMsg: ‘Displaying products {0} – {1} of {2}’,

            emptyMsg: “No products to display”

        })

    });

 

    // render it

    grid.render(‘gridProductList’);

    // trigger the data store load

    store.load({params:{start:0, limit:10}});

});

 

Listing 12

The last part of the solution is to develop the server-side code to which the ExtJS grid communicates. We need to support the GET method to show the initial view and the POST method to implement the logic to get a list of products. In this case, the Index action method has the following signature to get the paging and sorting information (see Listing 13).

public ActionResult Index(int start, int limit, string dir, string sort)

Listing 13

And the implementation for the controller is shown in the Listing 14:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Ajax;

using GridAjaxExtJSMvcApp.Models;

 

namespace GridAjaxExtJSMvcApp.Controllers

{

    public class ProductController : Controller

    {

        private ProductsRepository _productsRepository = new ProductsRepository();

 

        //

        // GET: /Product/

        [AcceptVerbs(HttpVerbs.Get)]

        public ActionResult Index()

        {

            return View();

        }

 

        //

        // POST: /Products/

        [AcceptVerbs(HttpVerbs.Post)]

        public ActionResult Index(int start, int limit, string dir, string sort)

        {

            if (Request.IsAjaxRequest())

            {

                var arrProducts = this._productsRepository.GetAllProducts(start, limit, sort, dir);

                var nProductCount = this._productsRepository.GetCount();

 

                var results = (new

                {

                    totalRecords = nProductCount,

                    products = arrProducts

                });

 

                return Json(results);

            }

            else

            {

                return RedirectToAction(“Index”);

            }

        }

 

    }

}

 

Listing 14

Now let’s test the solution (see Figure 7).

 

Figure 7

Conclusion

In this article, I’ve illustrated how to implement a grid with paging and sorting using ExtJS and ASP.NET MVC.

Forms with ExtJS and ASP.NET MVC

Introduction

After researching a lot about ExtJS support for rich Internet applications and nice user experience, and for my bias to this JavaScript library, I’ve decided to write this article to illustrate the form support in ExtJS and how it’s well integrated with ASP.NET MVC framework. First of all, I will explain the form support in ExtJS and then we will walk through an illustrative example where we put in practice what we’ve learnt before with a real-world solution by creating, validating and submitting information to the server.

Explaining the forms support in ExtJS

In order to create forms in ExtJS, we have to instantiate objects of the class Ext.FormPanel. This class implements all the functionality of common HTML forms and corresponds to the <form> HTML tag. Let’s create our first empty form in ExtJS (see Listing 1). The title property, bodyStyle, width and html properties are self-descriptive. The renderTo points to a <div> element where the form will be rendered. The defaults property specifies the default component on the form. The url property specifies the URI send the request of the form. And finally, the html property specifies a text as the default output (see Listing 1).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

html: ‘This form is empty!’

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 1

The output is shown in the Figure 1.

Figure 1

Next step is to add different fields to this form. In order to add fields, we need to set the items property instead of working on the html property. The first two elements to add are a text field and a number field (see Listing 2).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

 

var nameTextField = new Ext.form.TextField({

fieldLabel: ‘Name’,

name: ‘name’

});

var ageNumberField = new Ext.form.NumberField({

fieldLabel: ‘Age’,

name: ‘age’

});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

nameTextField, ageNumberField

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 2

In ExtJS fields, we can find several components and its properties. In this case, the most important properties are: fieldName property to set a descriptive message accompanying the component of the form and name property to set name of the request parameter. The emptyText property defines the text that the field will contain when it is empty. The value property is the default value for the control. The output is shown in Figure 2.

Figure 2

Another way to declare controls is on the fly (highlighted in yellow in the Listing 3). As you can see for the name field we don’t have to specify the type because it’s taken from the defaults property of the form, unlike the type of the age field which is specified by the xtype property.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 3

Let’s add new elements to the form. For radio buttons, the code is shown in Listing 4 highlighted in yellow. The important thing here is to set the name to the same value.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 4

And the output is shown in the Figure 3.

Figure 3

Next element is checkbox. The checkboxes are used to select one or more items from a list, or simply to activate or deactivate any flag or permission in a system. The code is shown in the Listing 5 highlighted in yellow.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 5

The radio buttons are used to select a single choice of several items. The result is shown in the Figure 4.

Figure 4

The hidden fields are useful to send information to the server that the user doesn’t need to know, such as id of the record being edited, or a security token, and so on. ExtJS has the component “Ext.form.Hidden” which allows us to achieve this functionality. See in the Listing 6 highlighted in yellow.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 6

The combobox field is a list of pairs (key and value). The key identifies the pair and is usually submitted to the server, while the value is what users can see in the browser when he selected one from the available options.
In order to initialize the values of a combobox field, we need to use store objects, where data can be kept.

The code for the combobox is shown in the Listing 7 highlighted in yellow.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 7

And the output is shown in the Figure 5.

Figure 5

To select a particular date, we need to use the datefield            element (see Listing 8 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 8

The output is shown in the Figure 6.

Figure 6

If you only want to select the time (not the date), you need to use timefield (see Listing 9 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 9

And the output is shown in the Figure 7.

Figure 7

We also have a text area representation in ExtJS (see Listing 10 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’},

{xtype: ‘textarea’,name: ‘area’,fieldLabel: ‘Memo’,anchor: ‘90%’,multiline: true}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 10

The output is shown in the Figure 8.

Figure 8

So far, we have developed a form using ExtJS to take data from the user. Now, I will show how to send the data to the server. To send the data, we need to add a button to the form to handle the submit process (see Listing 11 highlighted in yellow). The buttons property is list of button for the form. Each button has name and handler properties. The handler property contains the logic associated to the action executed on the button. In this case, we have two buttons whose names are Save and Reset. The Save button’s handler executes a submit action on the form and shows a message indicating success or failure. The Reset button’s handler resets the field values on the form.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

var form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’submitform’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’},

{xtype: ‘textarea’,name: ‘area’,fieldLabel: ‘Memo’,anchor: ‘90%’,multiline: true}

],

buttons: [{

text: ‘Save’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, b.result.error);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 11

And the last step in the form creation is the validation. Validation is a very important topic and useful because every data entry contains invalid data. In this part of the article, we’re going to talk about the underlying techniques in ExtJS.

In order to specify required fields, we need to set the allowBlank property to false. Let’s see the techniques for name and age properties (see Listing 12 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

var form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’home/saveform’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’, allowBlank:false},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’, allowBlank:false},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’},

{xtype: ‘textarea’,name: ‘area’,fieldLabel: ‘Memo’,anchor: ‘90%’,multiline: true}

],

buttons: [{

text: ‘Save’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 12

When you run the application and click on the Save button without entering any data on the Name and Age field, then you receive an error message and the required fields are underlined in red.

To customize the error messages on the fields, we need to add the following line of code just under the Ext.onReady function (see Listing 13).

Ext.QuickTips.init();

Listing 13

Now, when the users move the mouse over the field, they will see a balloon with a message displaying the error (see Figure 9).

Figure 9

For number fields like the Age field, we have a lot of properties to validate the data such as maxValue, allowNegative, allowDecimals, allowBlank and minValue.

ExtJS has a good support for validation using regular expressions. You can learn more about this feature.

Getting started with the solution

Now, we’re going to create an example solution using ExtJS library and ASP.NET MVC. We’re going to implement the Add Employee use case for a Human Resources Management system. The Add Employee use case description is as follows: A screen prompts the user to enter valid information (whether optional or mandatory) for a new employee such as employee identifier, full name, address, age, salary and department. The department field is a list of department to choose one.

This use case fits well to illustrate the main artifacts and steps for a solution using ExtJS and ASP.NET. The implementation strategy for this use case is to create an ExtJS form on the client-side and process the data using ASP.NET MVC. The persistence layer will be Linq to represent business entities and to persist data to the database system. As the development environment we’re going to use Microsoft Visual Studio.NET and as the database system Microsoft SQL Server.

Open Visual Studio.NET and create a ASP.NET MVC application.

The first step is to create the database schema for the use case. Our schema will contain two entities: employee and department. Let’s create the HumanResources database and the underlying tables and its constraints in order to maintain the data integrity (see Listing 14).

 

create table department

(

deptno varchar(20) primary key,

deptname varchar(50) not null,

location varchar(50)

);

create unique index undx_department_deptname on department(deptname);

 

insert into department

values(‘HQ-200′,’Headquarter-NY’,’New York’);

insert into department

values(‘HR-200′,’Human Resources-NY’,’New York’);

insert into department

values(‘OP-200′,’Operations-NY’,’New York’);

insert into department

values(‘SL-200′,’Sales-NY’,’New York’);

insert into department

values(‘HR-300′,’Human Resources-MD’,’Maryland’);

insert into department

values(‘OP-300′,’Operations-MD’,’Maryland’);

insert into department

values(‘SL-300′,’Sales-MD’,’Maryland’);

 

create table employee

(

empno varchar(20) primary key,

fullname varchar(50) not null,

address varchar(120),

age int,

salary numeric(8,2) not null,

deptno varchar(20) not null,

constraint fk_employee_department_belong_rltn foreign key(deptno)

references department(deptno)

);

create unique index undx_employee_fullname on employee(fullname);

Listing 14

Then let’s create a Linq to SQL Classes item inside the Model folder to define the structure of the entities and the persistence mechanism (see Listing 13). The object definition in Linq to SQL is shown in the Figure 10.

Figure 10

Next step is to develop the EmployeeRepository class to manage the data access logic to the employee table (CRUD operations). Regarding to our use case, we only need to implement the create operation (see Listing 15).

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

 

namespace HumanResources_ExtJSASPNETMVC.Models

{

public class EmployeeRepository

{

private HumanResourcesDataContext _ctxHumanResources = new HumanResourcesDataContext();

 

public void Create(employee employee)

{

this._ctxHumanResources.employees.InsertOnSubmit(employee);

this._ctxHumanResources.SubmitChanges();

}

}

}

Listing 15

We also need to develop the DepartmentRepository class to manage the data access logic to the department table (CRUD operations). Regarding to our use case, we only need to implement the read operation in order to find a list of department (see Listing 16).

using System;

using System.Data;

using System.Configuration;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

 

namespace HumanResources_ExtJSASPNETMVC.Models

{

public class DepartmentRepository

{

private HumanResourcesDataContext _ctxHumanResources = new HumanResourcesDataContext();

 

public IQueryable<department> FindAll()

{

return from dept in this._ctxHumanResources.departments

orderby dept.deptname

select dept;

}

}

}

Listing 16

Now that we have defined the business logic’s artifacts, that is the business entities and the services that process the entities, we need to go to the presentation layer. The implementation strategy for the presentation layer is ASP.NET MVC. MVC stands for model-view-controller. We have worked on the model piece of the architecture before. Now let’s define another important piece of the architecture: the controller.

Right-click on the Controllers folder in the Solution Explorer window and select Add|Controller option from the context menu. Set HumanResourcesController as the name (see Figure 11).

Figure 11

Now let’s go to the presentation piece to define the graphical interface using ExtJS JavaScript library. The first step is to download and copy the distribution of ExtJS inside the Scripts directory. For our solution, we only need ext-all.js file, ext-base.js file and the resources directory (see Figure 12).

Figure 12

Now let’s include this library in our project. For this purpose, let’s go to the Site.Master page and adding the references to the ExtJS files inside the head element (highlighted in yellow in the Figure 13). As well, we need to add a <asp:ContentPlaceHolder> tag element as container of the customized JavaScript and CSS code for each page (highlighted in green in the Figure 14).

<head runat=”server”>

<title><asp:ContentPlaceHolder ID=”TitleContent” runat=”server” /></title>

<link href=”../../Content/Site.css” rel=”stylesheet” type=”text/css” />

 

<!– Include the ExtJS framework –>

<link href=”../../Scripts/ext/resources/css/ext-all.css” rel=”stylesheet” type=”text/css” />

<script type=”text/javascript” src=”../../Scripts/ext/ext-base.js”></script>

<script type=”text/javascript” src=”../../Scripts/ext/ext-all.js”></script>

<!– Placeholder to include CSS and JS files customized for each page –>

<asp:ContentPlaceHolder ID=”Scripts” runat=”server” />

</head>

Figure 13

Now let’s add the view to present the form to get the data related to one employee. Go to the HumanResourcesController controller and right-click on the Index action method and select Add View option from the context menu. Click on the Add button on Add View dialog box (see Figure 14).

Figure 14

In order to implement the ExtJS form, we need to add a JavaScript file to the Scripts directory (see Figure 15).

Figure 15

Then include the JavaScript file and add a div element (with id=employeeform) into the Index.aspx view (see Listing 17).

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage” %>

 

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

Add a New Employee

</asp:Content>

 

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

 

<h2>Add a New Employee</h2>

<div id=”employeeform”></div>

</asp:Content>

 

<asp:Content ID=”Content3″ ContentPlaceHolderID=”Scripts” runat=”server”>

<script type=”text/javascript” src=”../../Scripts/employee_form.js”></script>

</asp:Content>

Listing 17

Now it’s time to go to the employee_form.js file and write some code in JavaScript to configure the ExtJS form and its underlying widgets.

The first step is to define an instance of Ext.data.JsonStore class to get a list of department. The url property points to the departments action method on the HumanResourceController controller. This method is access by default http access method which is POST. The root property is the root element of the list of departments. The fields property specifies the data fields (see Listing 18).

    var departmentStore = new Ext.data.JsonStore({

url: ‘humanresource/departments’,

root: ‘departments’,

fields: [‘deptno’, ‘deptname’]

});

Listing 18

Next step is to define the form. The properties are self-descriptive. In this case, the url property points to the AddEmployee action method on the HumanResourceController controller. This method is also accessed using POST HTTP verb (see Listing 19).

var form= new Ext.FormPanel({

title:’Add Employee Form’,

renderTo: ’employeeform’,

width: 400,

url:’humanresource/addemployee’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

Listing 19

The items property is the list of widgets for the fields of the form. Here the default widget is textfield (this is specified in the defaults property). The first field is employee number which is required (specified by the allowBlank property) textfield. The second field is the fullname which is also a required textfield. The address field is an option textarea. The age field is an optional numberfield. The salary field is a required numberfield. And finally, the department number field is identifier string which is selected from a list of departments (see Listing 20).

          items:[

{fieldLabel:’Employee ID’,name:’empno’, allowBlank:false},

{fieldLabel: ‘Fullname’,name: ‘fullname’, allowBlank:false},

{xtype: ‘textarea’,fieldLabel: ‘Address’,name: ‘address’,multiline: true},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype:’numberfield’,fieldLabel:’Salary’,name:’salary’, allowBlank:false},

{xtype:’combo’,fieldLabel:’Department’,name:’deptno’, store:departmentStore,

hiddenName:’deptno’,displayField:’deptname’,valueField:’deptno’,typeAhead:true,

mode:’remote’,forceSelection: true,triggerAction: ‘all’,emptyText: ‘Please, select a department…’,

editable: false}

],

Listing 20

Then the buttons property is defined (see Listing 21).

        buttons: [{

text: ‘Add’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

Listing 21

After add the line of code of the Listing 13, you have the complete employee_form.js file (see Listing 22).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

Ext.QuickTips.init();

var departmentStore = new Ext.data.JsonStore({

url: ‘humanresource/departments’,

root: ‘departments’,

fields: [‘deptno’, ‘deptname’]

});

var form= new Ext.FormPanel({

title:’Add Employee Form’,

renderTo: ’employeeform’,

width: 400,

url:’humanresource/addemployee’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Employee ID’,name:’empno’, allowBlank:false},

{fieldLabel: ‘Fullname’,name: ‘fullname’, allowBlank:false},

{xtype: ‘textarea’,fieldLabel: ‘Address’,name: ‘address’,multiline: true},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype:’numberfield’,fieldLabel:’Salary’,name:’salary’, allowBlank:false},

{xtype:’combo’,fieldLabel:’Department’,name:’deptno’, store:departmentStore,

hiddenName:’deptno’,displayField:’deptname’,valueField:’deptno’,typeAhead:true,

mode:’remote’,forceSelection: true,triggerAction: ‘all’,emptyText: ‘Please, select a department…’,

editable: false}

],

buttons: [{

text: ‘Add’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 22

Now let’s go to the HumanResourceController and implement the corresponding action methods (see Listing 23).

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Ajax;

using HumanResources_ExtJSASPNETMVC.Models;

 

namespace HumanResources_ExtJSASPNETMVC.Controllers

{

public class HumanResourceController : Controller

{

DepartmentRepository _repoDepartment = new DepartmentRepository();

EmployeeRepository _repoEmployee = new EmployeeRepository();

 

//

// GET: /HumanResource/

public ActionResult Index()

{

return View();

}

 

//

// POST: /HumanResource/Departments

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Departments()

{

var arrDepartment = this._repoDepartment.FindAll();

var results = (new

{

departments = arrDepartment

});

return Json(results);

}

 

//

// POST: /HumanResource/AddEmployee

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult AddEmployee(employee employee)

{

string strResponse = String.Empty;

try

{

this._repoEmployee.Create(employee);

strResponse = “{success: true}”;

}

catch (Exception)

{

strResponse = “{success: false, error: \”An error occurred\”}”;

}

return Content(strResponse);

}

 

}

}

Listing 23

Now let’s run the solution (see Figure 16).

Figure 16

And when you click on the Add button, you see the result (see Figure 17).

Figure 17

And the row inserted in the dbo.employee table on the database (see Figure 18).

Figure 18

Conclusion

In this article, I’ve explained the form support of ExtJS and then we’ve walked through an illustrative example where we’ve put in practice all these concepts with a real-world solution by creating, validating and submitting information to the server.