Monday, January 10, 2011

MVC Pattern in Simple C#

MVC (Model View Controller) is an architectural pattern. In brief we can describe the participants as,
• A model is an object representing data and all other data service layers beneath it.
• A view is visualization of the state of the model.
• Controller facilities to change the state of the model.
MVC is consisting of Observer, Strategy, and Composite. It also uses Factory Method and Decorator, but the main MVC relationship is defined by the Observer and Strategy patterns.

The views and models use the Publish-Subscribe protocol (Observers Pattern) -when Model data is changed, it will update the View. View uses the Controller to implement a specific type of response (Strategy Pattern).The controller can be changed to let the View respond differently to user input

A simple representation of MVC in C# is as follows.

class Program
{
static void Main(string[] args)
{
var controller = new Controller();
IView view = controller.View;
view.Radius = "5";
view.UserEvent(view.Radius);
Console.WriteLine(view.Result);

Console.ReadLine();
}
}


public class Controller : IController
{
private IView _view;
private Model _model;


public IView View
{
get
{
return _view;
}
}

public Controller()
{
_model = new Model();
_view = new View(this, _model);
}

public void CalculateRadius(string radius)
{
_model.CalculateRadius(double.Parse(radius));
}
}



public interface IController
{
void CalculateRadius(string newModelState);
}


public interface IView
{
string Radius { get; set; }
string Result { get; set; }

void UserEvent(string radius);
}

public class Model
{
private object _modelState;

public event Action OnPropertyChange;

public Model()
{
}

public object ModelState
{
get
{
return _modelState;
}

set
{
_modelState = value;
NotifyPropertyChange();
}
}

private void NotifyPropertyChange()
{
var propChange = OnPropertyChange;
if (propChange != null)
{
OnPropertyChange();
}
}

internal void CalculateRadius(double radius)
{
ModelState = (Math.PI * radius*radius).ToString();
}

}

public partial class View : IView
{
private IController _controller;
private Model _model;

public View(IController controller, Model model)
{
_controller = controller;
_model = model;

//Let the model know that this view is interested if the model change
_model.OnPropertyChange += new Action(UpdateView);

}

string radius = string.Empty;
public string Radius
{
get { return radius; }
set { radius = value; }
}

string result = string.Empty;
public string Result
{
get { return result; }
set { result = value; }
}


public void UpdateView()
{
Result = _model.ModelState.ToString();

}

public void UserEvent(string radius)
{
_controller.CalculateRadius(radius);
}

Sitecore.NVelocity

Apparently I was working with Sitecore and its mail template. Sitecore suggest using nVelocity for template rendering. I notices that they have their own version of nVelocity called Sitecore.NVelocity. The base code is essentially the same and the code for rendering the template is slightly different as follows ( as in original Velocity)

In the constructor

Velocity.Init();


For rendering call 


Velocity.Evaluate(context, generated, "nVelocityLog", reader);

nVelocity to render templates

nVelocity is a .Net-based template engine. It permits anyone to use the simple yet powerful template language to reference objects defined in .Net code. I use this template engine for rendering the mail templates in my application. This is a wonderful framework, with a defined syntax to render field values inside the template. For those who do not know, project is a port of the Jakarta Velocity to Microsoft .Net (written in C#). This is a discontinued project, but the Castle project fork  enhanced it to support their monorail implementation. There are different versions available, I used one from Castle project website which has a lot of bug fixes and features incorporated than the original.

Below is the sample code to illustrate nVelocity to render mail template.

using System;
using System.Collections.Generic;
using System.IO;
using Commons.Collections;
using NVelocity;
using NVelocity.App;
using System.Collections;

namespace NVelocitySample
{
class Program
{
static VelocityEngine velocity;
static void Main(string[] args)
{
InitializeVelocity();

string output = GenerateOutput();
Console.WriteLine(output);
}

private static void InitializeVelocity()
{
ExtendedProperties properties = new ExtendedProperties();

velocity = new VelocityEngine(properties);
}


private static string GenerateOutput()
{
Message mail = new Message();


mail.From = "sender@company.com";
mail.To = "recipient@company.com";
mail.Subject = "This a mail render example";
mail.Body = "This is the body where replace a dictionary to show the versatility of nVelocity";


Dictionary<string, string> coll = new Dictionary<string, string>();
coll["key"] = "Hi,";



string stringData = "From: $mail.From \n";
stringData += "To: $mail.To \n\n";
stringData += "Subject: $mail.Subject \n\n";
stringData += "$coll.get_Item('key') $mail.Body";


Hashtable hashTable = new Hashtable();
hashTable.Add("mail", mail);
hashTable.Add("coll", coll);

VelocityContext context = new VelocityContext(hashTable);

StringWriter generated = new StringWriter();
StringReader reader = new StringReader(stringData);
velocity.Evaluate(context, generated, "nVelocityLog", reader);
return generated.GetStringBuilder().ToString();


}


class Message
{
private string from;
private string to;
private string subject;
private string body;

public string From
{
get { return from; }
set { from = value; }
}

public string To
{
get { return to; }
set { to = value; }
}

public string Subject
{
get { return subject; }
set { subject = value; }
}

public string Body
{
get { return body; }
set { body = value; }
}
}

class Coll
{
Dictionary<string, string> fields = new Dictionary<string, string>();

public Dictionary<string, string> Fields
{
get { return fields; }
set { fields = value; }
}
}
}
}




Calling C# function in XSL

In my current project, someone was looking for calling a C# function in XSL transformation. The following example calls a C# function declared in an external assembly for XSL transformation. DollerEuroConverter class is defined in the assembly CurrencyConverter.dll. The GetEuroValue function is just a sample implementation to show how the data from xsl can be modified using C# function. I tested it using a XML Notepad, I got the following output.

clip_image002

CurrencyConverter class

using System;
namespace CurrencyConverter
{
//our custom class
public class DollerEuroConverter
{
//function that gets called from XSLT
public string GetEuroValue(string xslDollar)
{
return (float.Parse(xslDollar) / 0.749962502).ToString("##.##");
}

}
}


CD.xml (Sample from w3schools)




<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Dolly Parton</artist>
<country>USA</country>
<company>RCA</company>
<price>9.90</price>
<year>1982</year>
</cd>
<cd>
<title>Still got the blues</title>
<artist>Gary Moore</artist>
<country>UK</country>
<company>Virgin records</company>
<price>10.20</price>
<year>1990</year>
</cd>
</catalog>


CD.xsl




<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:MyClass="CurrencyConverter.DollerEuroConverter">


<msxsl:script language="C#" implements-prefix="MyClass">
<msxsl:assembly href=".\bin\Debug\CurrencyConverter.dll" />
<msxsl:using namespace="CurrencyConverter"/>

<![CDATA[

public string GetPrice(string data)

{
CurrencyConverter.DollerEuroConverter conveter = new CurrencyConverter.DollerEuroConverter();
string days = conveter.GetEuroValue(data);
return days;

}

]]>

</msxsl:script>

<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
<th>Price in Euro</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
<td>
<xsl:value-of select="MyClass:GetPrice(price)"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>