Introduction - Web Layer
This article concerns on the Web layer of the MVC
design pattern. Model-View-Controller is also one of the parts of the web-application framework Catharsis. There is powerful Guidance which will help you to quickly create new solution and extend it with infrastructure for your business entities.
Guidance.msi, Source code and powerful example can be found:
http://www.codeplex.com/Catharsis/

Current version is:
Catharsis 1.0.1 (19.4.2009), based on ASP.NET MVC 1.0 and NHibernate 2.1 Alpha2
MVC should be still OOP
One of the OOP pillars is “encapsulation”. This requirement is so fundamental, that we should always keep it in mind. When "Encapsulation" is missing, the result is always the spaghetti code, which could be called: structured programming, based on "Functions".
There are in fact three possible approaches to UI (view) in the MVC world. But not all of them keep the above mentioned "Encapsulation" in heart.
Essential MVC WebControl
This is a pure solution. It is most powerful, clearly OOP, but also most complicated to implement. The principal starts in declaration an Interface IModel
. This interface instance is than filled on Controller and finally – the implementing WebControl
takes it as a generic parameter <IModel>
. View therefore exactly knows the contract and can use all available properties (declared in IModel
).
At first look it is not so obvious, that to implement this approach requires lot of effort. It is simply complicated.
Extension methods – HtmlHelper
ASP.NET MVC brings new feature HtmlHelper. This object is as a property available on every WebControl (derived from ViewControl).
You than can call its “extension” methods to create intended html “string”. Yes, exactly – the result is a “STRING” directly rendered to the view.
The only understandable reason for this approach (to render strings) comes form the fact that MVC implemented ASP.NET does not provide binding. You cannot append on UI standard ASP.NET WebControls which expects DataSources or dynamically filled properties. Simply there is no binding event.
ASP.NET MVC therefore provides the dynamically built html streams – “strings” rendered into the View. The “structured programming” (function based) as from the learning book.
Smart WebControls
This is surprisingly nice approach, which is extremely easy to implement, use and re-use. And what’s more, it is based on webControls, which are from the ASP.NET beginnings purely OOP designed, providing the so needed “Encapsulation”. Call the object; use its interface
== public properties; let it correctly render output when needed.
Yes, they are OBJECTS
. You are really setting theirs properties (CssClassName
, InputName
, Text
etc.) and that’s all. They are not functions or strings. And they are so smart that when they are supplied with all needed inputs (properties) they render themselves as the html stream.
And that all is working in the ASP.NET MVC world - which is without binding event.
Good - MVC essential web control
Let’s firstly concern more closely on the first approach – the real MVC WebControls
.
pure MVC WebControl
First of all MVC
means Model-Veiw-Controller design pattern. Not the abbr. for ASP.NET MVC!
Now we need an agreement. This would be done by declaring an interface
1) MVC
part - Model
interface IControlModel: ICoreModel
{
Url UrlPath { get; set; }
string Text { get; set; }
bool IsDisabled { get; set; }
}
2)
MVC
part - Controller
At this moment we know interface and we (controller) are responsible to fill it.
public ActionResult GetControl()
{
var model = Factory.CreateModel< IControlModel>()
model.UrlPath = "/Controller/Action";
model.Text = "Link to Action";
View(model)
}
3) MVC part - View
The WebControl
(View) is designed as:
public class MyControle: ViewControl<IModel> {}
On The .ascx
we have to use that all
<a href='<%= IsDisabled ? string.Empty : Model.UrlPath %>' ><%= Model.Text %></a>
Weak points
Agreement checks
On the above implementation are missing agreement checks. What if the View is provided with model, which UrlPath
is null? Or if the Text
is string.Empty
?
Who should do this job? In fact, this job – assuring that the properties are filled – is essential. If you won’t have that check you will sooner or later end up with troubles. Missing checks
will be uncovered only accidently – in the runtime. Bad design!
We have to extend this example with checks
. But where they should be?
1) Some could be in directly in the IControlModel
implanting object:
public string UrlPath
{
get { return _urlPath; }
set
{
Check.Require(!string.IsNullOrEmpty(value), ' UrlPath must be not null nor empty ');
_urlPath = value;
}
}
This is really good design: Implementer of the “agreement” extends the .NET value type checks. .NET can grant that model.UrlPath = -1M
won’t be built. Good but not enough. The null or empty string will be passed, we have to extended this requirement using chekcs
.
Disadvantage of this approach is the fact, that you cannot count on implementer! You are acting with the IControlModel
– which can be (even without your agreement) implemented by some proxy
, or TestObject
etc. In all these scenarios this checks
will fail (won't be executed at alll)
So, Model checks for IControlModel
are too rigid to be used
2) Controller checks
Simply: These are out of any logic. We need to check the controller’s job! And it cannot be done on controller.
3) WebControl
(View) Checks
"Surprisingly", the consumer of the agreement is the only good place for checks
! I believe that (at least now) it is obvious! But trust me, there is lot of “developers”, who did not understand to this trivial and obvious principal! Let’s have a look.
The best and only place where we should check
if the contract was fulfilled is the View. More preciously: The WebControls
property:
public virtual string UrlPath
{
get
{
Check.Require(!string.IsNullOrEmpty(Model.UrlPath)
, ' UrlPath must be not null nor empty ');
If(Model.IsDisabled)
{
return string.Empty;
}
return Model.UrlPath;
}
}
On the .ascx
it will looks like that
<a href='<%= UrlPath %>' ><%= Text %></a>
Great! We did it. And it was very easy in fact.
Design Failure – no ascx.cs files
Some time ago I’ve seen a horrible concept. Some “smart guys” started to use only the .ascx
files without any underlying .ascx.cs
.
How can anyone implement .only .ascx
file for such a fundamental and fragile OBJECT
as the WebControl
is? You can NEVER count on the IControlModel
properties! Please, keep in mind: we are designing the Multi-tier Architecture! What it means?
On Web layer – you can count on NOONE except of YOU (WebControl
designer). You simply do not know how will use your WebControl
.
Yes, at first time, the only consumer is you, single developer! But when the project growth, one can make Web layer, the second can fill IControlModels
in the controller's action. But he can forget to fill, what you’ve expected to be filled.
There’s no taking without possibility of misstaking!
Web layer, is the layer
– not quasi layer. It requires gentle behavior and handling, because it's fragile.
Be paranoiac. Always evaluate provided values! (Or your application user will do it instead of you - expensive tester)
Never forget on Checks
!
Large View, many IControlModels needed
Another week point of this approach is the need for different IControlModel
instance for every WebControl
on your View (page or other control).
The above example was to direct and simple, that there was only one IControlModel
passed to the view.
In day-to-day scenarios you’ll end up with this View (page):
1) Model as a basket
interface IMyModel: IWebModel
{
IControlModel Anchor1Model { get; set; }
IControlModel Anchor2Model { get; set; }
…
IControlModel AnchorNModel { get; set; }
}
2) Controller’s action will start to growth
public ActionResult GetPage()
{
var pageModel = Factory.CreateModel< IMyModel>()
pageModel.Anchor1Model = Factory.CreateModel< IControlModel>()
pageModel.Anchor1Model = "/Controller/Action";
…
pageModel.Anchor2Model = Factory.CreateModel< IControlModel>()
…
pageModel.AnchorNModel = Factory.CreateModel< IControlModel>()
…
View(pageModel)
}
3) Page will distribute the asked IControlModel
instances as shown
<myControl:Anchor Id="Anchor1" runat=""server"" ViewDataKey="Anchor1Model" />
<myControl:Anchor Id="Anchor2" runat=""server"" ViewDataKey="Anchor2Model" />
…
<myControl:Anchor Id="AnchorN" runat=""server"" ViewDataKey="AnchorNModel" />
Well. I believe that even in this example is obvious: To complicated for a such a simple controls like anchor.
When should we use MVC WebControls?
MVC
WebControls
(the ones with specific IControlModel
) are suitable for large repeating, very similar blocks. The best example is the “Table” control.
Every entity needs the list view. The table based control which allows paging, sorting, navigating to detail, to edit, to delete …
Good solution is ListWC.ascx
control (observe example) with the large IListModel
.
There is so much functionality encapsulated in there that it can cover whole article.
In a nut shell: in practice you have to override only ONE method on entitiy's Controller:
OnListToDisplay()
and there to fill Model.ListModel.ItemsToDisplay
collection.
That’s all. But the result is awesome.
Powerful MVC
WebControl
, RE-usable, easily filled, easily maintained (only one WebControl
for list view in whole application – could it be better?)
Bad - MVC design failure - HtmlHelper
WebControls
based on IControlModel
are good for larger, repeatable blocks. For smaller ones (yes, for example the Anchor
rendering) we have to find out something much more flexible.
HtmlHelper: good servant or bad master?
ASP.NET MVC brought the object HtmlHelper
available on ever ViewControl. Firstly (in previews) it was an object with methods, lately was these methods moved to “Extension methods”.
Extension methods
As any feature in .NET, also the extension method can be used correctly or any other way.
Well, let’s have a closer look to three types of extension methods: UrlHelper.Action()
, HtmeHelper.WebControl()
, object.ToDisplay()
.
object.ToDisplay()
There is one fundamental extension method in Catharsis: ToDisplay()
. It allows get any object as a string. Important part in this sentence is: any “OBJECT
”. The core part of this method is the object itself. It evaluates what the object is:
- For
IPersitent
object is used its implement ToDisplay()
operation (abstract in the base class). - For
decimal
, int
, short
, DateTime
it uses the ToString(IFormatProvider, format)
operation with user’s current culture and default (or overloaded ToDisplay(format))
formatting. result is "1 123,45" or "1,123.45" etc. - And so on.
This is a good example of extension method – the core, the essence is the object
itself.
UrlHelper.Action()
This extension method needs some parameters like controllerName
, action
name etc. But again the most important part is UrlHelper
itself. It does the environment dependent encapsulation for returning the correct result – the Url path.
It could be
- “/Controller/Action” or
- “/Controller.mvc/Action?parameter1=4” or
- “/VirtualPath/Controller.ashx”.
Great job does this UrlHelper
(despite of the fact that is called Helper, which always rises up the “structured programming approach”). It really encapsulates not so trivial routing.
HtmlHelper.WebControl()
There are many extended methods which allow render tags like <a>
, <input>
. But this is the real design failure. Let's have a look.
HtmlHelper
in fact is nothing. This is the “structured programming” design in its worth example. You in fact, have to provide everything what is needed as a parameter (yes, it encapsulates the call to UrlHelper
, but it is too few to apologize its existence).
Where is the problem (maybe you do not see it at this moment!)?
Let’s start with very very simplified example: We need an Anchor
to be rendered and let’s say there are two parameters Url UrlPath
and string Text
. Presume that both are preset to default values which can be used (UrlPath = '/'
, Text = ' '
)
To create Extension methods for this scenario we will end up with:
HtmlHelper.Anchor(Url path, string text)
HtmlHelper.Anchor(Url path)
HtmlHelper.Anchor(string text)
HtmlHelper.Anchor()
In speech of mathematics it is 2n combination (where the n ==
number of parameters). The result is 2*2 == 4 methods.
Let’s return to our previous example. Imagine that we need to render the anchor
and that there are three parameters in play: UrlPath
, Text
, IsDisabled
. Again, some of these parameters can be not provided – their default value will be used.
With a simple counting 2n ==
23 ==
8 methods.
If we'll be forced to provide more flexibility: CssClassName
, Format
=> 5 paramters 25 == 32 extension methods.
But only if they are of a different type!!! When CssClassName
, Format
and Text
are string -> we are in troubles because these methods:
HtmlHelper.Anchor(string CssClassName)
HtmlHelper.Anchor(string Format)
HtmlHelper.Anchor(string Text)
simply cannot decide what parameter you are sending. Desing failure, as already said.
What caused this design failure with HtmlHelper
extension methods?
Any other way then correct usage of .NET feature – extension method. In fact this is the “structured programming”, calling the functions, generating spaghetti code.
Why did it happen? This approach was intended as a replacement of so needed and missing “binding”. <br />HtmlHelper
was offered as the string provider, which can use dynamic (in runtime changing) values. Forget this offer. Let’s get out of the “string output” based “Functions”.
Let's Return to paradise (OOP world)
Good - MVC smart web control
ASP.NET world almost ten years supplies us with WebControl
approach. In the Form
pages (before ASP.NET MVC) they were used almost in 100%. Some of them, where using MVP
design pattern, which allowed them to be self-made-men (in the not so good meaning).
Such a WebControl
(based on MVP) was calling its Presenter
to store the user data (enclosed in the Form
) and than ask the Model-Business
for new values. They were stored in the IView
declared properties.
Some “complicated values” called DataSourceObjects
was bounded on the run. That means that the Bind()
event was essential.
MVP is dangerous (no center policeman like controller, but independent WebControls
, uf) and also out of our scope and interest.
But WebControls
itself: this is the best practice approach providing so needed encapsulation, flexibility due to property settings and one place maintenance (WebControl
code only).
The OBJECT
is back.
Simple WebControl
So, how should we design our WebControls
in the MVC
world (without binding)? Let’s start with an example.
1) There’s a code behind first:
public class AnchorControl: ViewControl {
#region members
string _urlPath = '/'
string _text =' '
#endregion members
#region properties
public virtual string UrlPath
{
get { return _urlPath; }
set
{
Check.Require(!string.IsNullOrEmpty(value), ' Url path must be not null nor empty ');
_urlPath = value;
}
}
public virtual string Text
{
get { return _text; }
set
{
Check.Require(!string.IsNullOrEmpty(value), ' Text must be not null nor empty ');
_text = value;
}
}
#endregion properties
}
2) Now the WebControl
from the .ascx
view:
<a href='<%= UrlPath %>' ><%= Text %></a>
Nothing new.
3) And finally the usage on the Page
(or other WebControl
)
<simple:AnchorControl ID='MyAnchor' runat="'server'"
Text='hello' UrlPath='/controller/action' />
That’s all. Yes I know: Nothing new. This is the usual WebControl
.
And that’s exactly what we wanted.
But it is static control. You have to know all the properties as their string representation – in design time. The property UrlPath
was set as the constant (known string)
”/controller/action”
But this scenario is not typical. We usually do not know the value of the UrlPath
string in the design time. This value will be probably changing in runtime, and we have to bind
it dynamically.
That’s obvious, but how to do that? The tricks like <%$ or <%# or anything else won’t work!
Dynamic WebControl
1) Eeeeaaasily! Let’s extend our code behind:
public class AnchorControl: ViewControl {
#region members
string _cssClassName = ' cell ';
#endregion members
#region Set()
public virtual AnchorControl SetUrlPath (string urlPath)
{
Check.Require(!string.IsNullOrEmpty(urlPath), ' urlPath parameter must be not null nor empty');
UrlPath = urlPath;
return this;
}
public virtual AnchorControl SetText (string text)
{
Check.Require(!string.IsNullOrEmpty(text), ' text parameter must be not null nor empty');
Text = text;
return this;
}
public virtual AnchorControl SetCssClassName (string cssClassName)
{
Check.Require(!string.IsNullOrEmpty(cssClassName), 'cssClassName parameter must be not null nor empty');
CssClassName = cssClassName;
return this;
}
#endregion Set()
#region properties
public virtual string CssClassName
{
get { return _cssClassName; }
set
{
Check.Require(!string.IsNullOrEmpty(value), ' CssClassName must be not null nor empty');
_cssClassName += ' ' + value;
}
}
#endregion properties
}
Ou, cool. Easy. Nothing new.
2) The .ascx
view:
<a href='<%= UrlPath %>' class='<%= CssClassName %>' ><%= Text %></a>
3) And back to our hosted Page
(or other hosting WebControl
)
<% MyAnchor.SetUrlPath(Model.BackUrlPath).SetText('Back'); %>
<simple:AnchorControl ID='MyAnchor' runat="'server'"
CssClassName='niceFace' Text='Back' />
Yes, yes, yes. Now we have dynamically bound-able WebControl
which:
- publishes the exact amount of Properties which could be set and used
- provides the dynamic setters for some (all) published properties. No 2n overflow.
- encapsulates the “render to string phase” in the WebControl. The
OBJECT
is back.
Smart WebControls
But we can still go far, much much far. We can assume something, based on our application design.
For example, that our control is hosted on Page or WebControl which is provided with some base model interface “IModel
” which can be due to framework restrictions always derived from e.g. ICoreModel
(or even from the IWebModel
, or IEntityModel
as in Catharsis).
If there is such a presumption: that every IModel
is also ICoreModel
we can extend our AnchorControl
implementation:
public class AnchorControl: ViewControl<ICoreModel> {…}
Now we know, that hosting Page
our WebControl
is passing to our AnchorControl
instance of the ICoreModel
and we can access it's properties agreed in the contract ICoreModel
!
Dummy example
Dummy EXAMPE now! For simplicity only!!! (Sorry but rather again: very simple assumption for example purposes only - will now follow!
Let’s say that ICoreModel
declares property called:
string DefaultCssClassName { get; set;}
This allows us to extend our AnchorControl
:
public class AnchorControl: ViewControl<ICoreModel> {
…
#region properties
public virtual string CssClassName
{
get
{
If (!string.IsNullOrEmpty(Model.DefaultCssClassName)
{
return Model.DefaultCssClassName + ' ' + _cssClassName;
}
return _cssClassName;
}
set
{
}
}
#endregion properties
…
}
More realistic example
Catharsis for example uses common base interface for every entity model called EntityModel
. It means that when you are on any entity detail page, you will be provided with model instance which is also IEntityModel
.
1) Because many smart WebControls
are mostly used on Entity detail pages (but not purely) we can extend our AnchorControl
in this way
public class AnchorControl: ViewControl<ICoreModel> {
#region members
string _urlPath;
#endregion members
#region Set() - public
#endregion Set()
#region Get() - protected
protected virtual string GetHref()
{
var hrefFormat = ' href=\'{0}\' ';
If(!string.IsNullOrEmpty(UrlPath))
{
return href.FormatWith(UrlPath);
}
If (EntityModel.Is()
{
return href.FormatWith(UrlHelper(EntityModel.CurrentAction, EntityModel. CurrentController));
}
return string.Empty;
}
#endregion Get()
#region properties
public virtual IEntityModel EntityModel
{
get { return Model as IEntityModel; }
}
#endregion properties
}
2) And the .ascx
will look like
<a <%= GetHref() %> class='<%= CssClassName %>' ><%= Text %></a>
3) And on Page
is AnchorControl usage still as easy:
<% MyAnchor.SetText(Model.Item.ToDisplay()); %>
<simple:AnchorControl ID='MyAnchor' runat="'server'" />
And that's all. Nice and easy. powerful OOP appraoch with strong reuse. And the "Encapsulation" is the motto.
Catharsis Smart WebControls
In the Catharsis you can use some alredy created smart WebControls
. Their purpose should be clear, names are self-describing:
Implemented smart WebControls
<smart:AnchorOrComboBoxWC />
<smart:AnchorOrFileWC />
<smart:AnchorOrSearchForWC />
<smart:CheckBoxWC />
<smart:RadioForNullableBoolWC />
<smart:TextOrInputWC />
<smart:TextOrTextAreaWC />
These are based on the approach – do implement everything only ones. So, in Catharsis there is only one View (Page
) same for the Detail
, New
and Edit
. Dependently on situation (and smart WebControls
settings e.g. ShowReadOnly
) the result is rendered:
This for New

This one for Detail

And also Edit

Smart Web Controls Example
There is a very powerful example, which serves as the showroom for the Catharsis framework.
http://www.codeplex.com/Catharsis/
Example has large searching options implemented on Data
layer, Business
rules checks on Façade
, Controller
preciously fills the ListWC.ascx
web control IListModel
and the Web
(UI) uses all of the implemented smart WebControls
.
You must observe it.
Suggestion
The example took me 4 hours. I used the power of Guidance
to create new solution and then Entity infrastructure generator to insert needed entities.
In fact the singificant time-consumer was the implementation (Dao, Façade, UI) – and that’s what we as developers need. To concern on business implementation and to count on the framework as the guy behind.
Other Catharsis stories: Catharsis.aspx
Enjoy Catharsis
Radim Köhler
History