Ahamdulillah finally
could write a blog at geeks
.
After vacuum on
writing code with Spring.NET and NHibernate (my favorite framework
and ORM on .NET world) for several months which makes me really miss
them so much
, finally since several days ago I could write code
using them
again. Although not using them in my current work, I
am still happy with my current work because on the code I wrote for,
need some mathematics which really makes me have nostalgia with
mathematic
. Ok back to the topic.
ASP.Net MVC is the
open source technology of web framework that makes me really
interesting on it lately. And I have a wish to use Spring.NET and NHibernate with it. Let's take a look a project structure I work
with.

The Steps
needed are :
Library
The *.dll(s) needed to prepare are :
antlr.runtime.dll
-
Castle.DynamicProxy.dll
-
Common.Logging.dll
- Iesi.Collections.dll
- log4net.dll
- Nhibernate.dll
- Spring.Core.dll
- Spring.Data.dll
- Spring.Data.NHibernate12.dll
- Spring.Web.dll
Add all the libraries to the ASP.Net MVC project reference.
Web Configuration (Web.config)
- Define section
configuration :
1 <sectionGroup name="spring">
2 <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
3 <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
4 <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core"/>
5 </sectionGroup>
6 <section name="databaseSettings" type="System.Configuration.NameValueSectionHandler"/>
2. Define spring
config definition and database setting configuration
1 <spring>
2 <parsers>
3 <parser namespace="http://www.springframework.net/database"
type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data"
schemaLocation="assembly://Spring.Data/Spring.Data.Config/spring-database-1.1.xsd"/>
4 </parsers>
5 <context>
6 <resource uri="assembly://My.Web/My.Web.Config/spring-hibernate.xml"/>
7 <resource uri="assembly://My.Web/My.Web.Config/spring-dao.xml"/>
8 <resource uri="assembly://My.Web/My.Web.Config/controller.xml"/>
9 </context>
10 </spring>
11 <databaseSettings>
12 <add key="db.datasource" value="kerapansapi\sqlexpress2005" />
13 <add key="db.user" value="sa" />
14 <add key="db.password" value="c_7un" />
15 <add key="db.database" value="MyDB" />
16 </databaseSettings>
3. Define
HttpModule
1 <httpModules>
2 <add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
3 <add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate12"/>
4 .....
5 .....
6
7 </httpModules>
Spring-NHibernate
configuration
Create spring-hibenate.xml in config folder.
1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns='http://www.springframework.net'
3 xmlns:db="http://www.springframework.net/database">
4
5
6 <object name="appConfigPropertyHolder"
7 type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
8 <property name="configSections" value="databaseSettings"/>
9 </object>
10
11 <db:provider id="DbProvider"
12 provider="SqlServer-1.1"
13 connectionString="Integrated Security=false; Data Source=${db.datasource};Integrated Security=true;
Database=${db.database};User ID=${db.user};Password=${db.password};"/>
14
15
16 <object id="sessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate12">
17 <property name="DbProvider" ref="DbProvider"/>
18 <property name="MappingAssemblies">
19 <list>
20 <value>My.Web</value>
21 </list>
22 </property>
23 <property name="HibernateProperties">
24 <dictionary>
25
26 <entry key="hibernate.connection.provider"
27 value="NHibernate.Connection.DriverConnectionProvider"/>
28
29 <entry key="hibernate.dialect"
30 value="NHibernate.Dialect.MsSql2000Dialect"/>
31
32 <entry key="hibernate.connection.driver_class"
33 value="NHibernate.Driver.SqlClientDriver"/>
34
35 </dictionary>
36 </property>
37 </object>
38
39 </objects>
NHibernate Domain
Mapping
In this sample just use a simple mapping table which located in
Modes/hbm and its POCO in Models/src. I think its not a good idea to
locate this Nhibernate mapping and its POCO in presentation layer. It
is better to located in a separate project, so we could reuse it if
we decide to change our presentation layer.
Mapping
1 <?xml version="1.0" encoding="utf-8" ?>
2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="My.Web" namespace="My.Web.Models">
3 <class name="Product" table="Product" >
4 <id name="ID" type="System.Int32" column="ID">
5 <generator class="assigned"/>
6 </id>
7 <property name="Name" column="Name" type="System.String" length="25"/>
8 <property name="Price" column="Price" type="System.Decimal"/>
9
10 </class>
11 </hibernate-mapping>
POCO :
1 [Serializable]
2 public class Product : DomainObject<int>
3 {
4 private string _name;
5
6 public virtual string Name
7 {
8 get { return _name; }
9 set { _name = value; }
10 }
11 private decimal? _price;
12
13 public virtual decimal? Price
14 {
15 get { return _price; }
16 set { _price = value; }
17 }
18 }
DomainObject
Domain
Repository
1 public interface IRepository<T>
2 {
3 void Save(T entity);
4 void Save(List<T> list);
5 void Delete(T entity);
6 void Update(T entity);
7 IList<T> Load();
8 T GetById<TId>(TId id);
9 IList<T> GetByCriteria(ICriteria criteria);
10 }
As well as Nhibernate Domain mapping, the Repository/DAO should
placed in seperate library. Either in the same place as POCO/mapping
on not.
NHibernateRepository :
1 public class NHibernateRepository<T> : HibernateDaoSupport, IRepository<T>
2 {
3 #region IRepository<T> Members
4
5 public void Save(T entity)
6 {
7
8 using (ISession session = SessionFactory.OpenSession())
9 {
10 session.Save(entity);
11 session.FlushMode = FlushMode.Auto;
12 session.Flush();
13 }
14 }
15
16 public void Save(List<T> list)
17 {
18 using (ISession session = SessionFactory.OpenSession())
19 {
20 ITransaction tx = session.BeginTransaction();
21 try
22 {
23 foreach (T entity in list)
24 {
25 session.Save(entity);
26 }
27
28 tx.Commit();
29 }
30 catch (Exception ex)
31 {
32 tx.Rollback();
33 throw ex;
34 }
35 finally
36 {
37 tx.Dispose();
38 }
39 }
40 }
41
42 public void Delete(T entity)
43 {
44 using (ISession session = SessionFactory.OpenSession())
45 {
46 session.Delete(entity);
47 session.Flush();
48 }
49
50 }
51
52 public void Update(T entity)
53 {
54 using (ISession session = SessionFactory.OpenSession())
55 {
56 session.Update(entity);
57 session.Flush();
58 }
59 }
60
61 public IList<T> Load()
62 {
63 using (ISession session = SessionFactory.OpenSession())
64 {
65 return session.CreateCriteria(typeof(T)).List<T>();
66 }
67 }
68
69 public T GetById<TId>(TId id)
70 {
71 using (ISession session = SessionFactory.OpenSession())
72 {
73 return session.Get<T>(id);
74 }
75 }
76
77 public IList<T> GetByCriteria(ICriteria criteria)
78 {
79 using (ISession session = SessionFactory.OpenSession())
80 {
81 return criteria.List<T>();
82 }
83 }
84
85 #endregion
86 }
SpringControllerFactory
SpringControllerFactory
is adapted from MVCContrib. And made a few modification on it because
in this case I want use convention on naming id controller at Spring
IoC/DI configuration. The modification applied on CreateController
method.
1 public IController CreateController(RequestContext context, string controllerName)
2 {
3 if (string.IsNullOrEmpty(controllerName))
4 throw new ArgumentNullException("controllerName");
5
6 //make convention on spring naming controller in spring IoC/DI definition
7 //xxxx.controller (all in lowecase)
8 controllerName = controllerName.ToLower() + ".controller";
9
10 if (_objectFactory == null)
11 {
12 throw new ArgumentException("CreateController has been called before Configure.");
13 }
14
15 try
16 {
17 return (IController)_objectFactory.GetObject(controllerName);
18 }
19 catch (Exception e)
20 {
21 throw new InvalidOperationException("Failed creating instance of: " +
22 controllerName + " using spring.net object factory", e);
23 }
24 }
Global.asax
The
next thing that we need to do is get spring context there and
configure SpringControllerFactory.
1 public class MvcApplication : System.Web.HttpApplication
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
6 routes.IgnoreRoute("favicon.ico");
7
8
9 routes.MapRoute(
10 "Default", // Route name
11 "{controller}/{action}/{id}", // URL with parameters
12 new { controller = "Home", action = "Index", id = "" } // Parameter defaults
13 );
14
15 }
16
17 protected void Application_Start()
18 {
19 ConfigureController();
20 RegisterRoutes(RouteTable.Routes);
21 }
22
23
24 private void ConfigureController()
25 {
26 //This example just sets the default context for use with the Spring.net Controller
27 //Factory. An IObjectFactory instance is also supported, if greater control over
28 //Spring.net is desired.
29
30 WebApplicationContext ctx = ContextRegistry.GetContext() as WebApplicationContext;
31 SpringControllerFactory.Configure(ctx);
32
33 ControllerBuilder.Current.SetControllerFactory(typeof(SpringControllerFactory));
34 }
35 }
Controller
We
could add Repository property for the model (product) in the
controller, and provide method that would be invoked on HttpRequest
which the repository object would be called in.
1 [HandleError]
2 public class HomeController : Controller
3 {
4 private IRepository<Product> _productRepository;
5
6 public IRepository<Product> ProductRepository
7 {
8 get { return _productRepository; }
9 set { _productRepository = value; }
10 }
11
12 public ActionResult DynamicGridData(string sidx, string sord, int page, int rows)
13 {
14 int pageIndex = Convert.ToInt32(page) - 1;
15 int pageSize = rows;
16 int totalRecords = 0;
17 int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
18
19 //ideally do real paging not load all data like this.
20 IList<Product> context = ProductRepository.Load();
21 totalRecords = context.Count;
22 var products = context.Skip<Product>(pageIndex * pageSize).Take<Product>(pageSize);
23
24 CultureInfo ci = new CultureInfo("id-ID");
25
26 var jsonData = new
27 {
28 total = totalPages,
29 page = page,
30 records = totalRecords,
31 rows = (
32 from prod in products
33 select new
34 {
35 i = prod.ID,
36 cell = new string[] { prod.ID.ToString(), prod.Name,prod.Price.GetValueOrDefault().ToString("C",ci) }
37 }).ToArray()
38 };
39 return Json(jsonData);
40 }
41 ....
42 ....
43 }
I
use jQuery (jGrid) to view display the data. Let take a look later on
View section. The
Spring configuration for the Controller is :
1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns="http://www.springframework.net">
3 <description>
4 MVC Controller declarations.
5 </description>
6
7 <object id="home.controller" type="My.Web.Controllers.HomeController,My.Web" singleton="false">
8 <property name="ProductRepository" ref="repository.product"/>
9 </object>
10 <object id="account.controller" type="My.Web.Controllers.AccountController,My.Web" singleton="false"/>
11
12 </objects>
Spring
DAO / Repository configuration.
1 <?xml version="1.0" encoding="utf-8" ?>
2 <objects xmlns="http://www.springframework.net">
3 <description>
4 Spring DAO / Repository
5 </description>
6 <object id="repository.product" type="My.Web.Repository.NHibernateRepository<My.Web.Models.Product>,My.Web" singleton="false">
7 <property name="SessionFactory" ref="sessionFactory"/>
8 </object>
9
10 </objects>
View
The
index.aspx is:
<asp:Content
ID="indexContent"
ContentPlaceHolderID="MainContent"
runat="server">
<link
rel="stylesheet"
type="text/css"
href="/scripts/themes/coffee/grid.css"
title="coffee"
media="screen"
/>
<script
src="/Scripts/jquery-1.3.2.js"
type="text/javascript"></script>
<script
src="/Scripts/jquery.jqGrid.js"
type="text/javascript"></script>
<script
src="/Scripts/js/jqModal.js"
type="text/javascript"></script>
<script
src="/Scripts/js/jqDnR.js"
type="text/javascript"></script>
<h2><%=
Html.Encode(ViewData["Message"])
%></h2>
<br
/>
<script
type="text/javascript">
jQuery(document).ready(function()
{
jQuery("#list").jqGrid({
url:
'/Home/DynamicGridData/',
datatype:
'json',
mtype:
'GET',
colNames:
['ID',
'Name',
'Price'],
colModel: [
{
name: 'ID',
index: 'ID',
width: 40, align: 'left'
},
{
name: 'Name',
index: 'Name',
width: 200, align: 'left'
},
{
name: 'Price',
index: 'Price',
width: 100, align: 'left'}],
pager:
jQuery('#pager'),
rowNum: 10,
rowList:
[5, 10, 20, 50],
sortname:
'ID',
sortorder:
"desc",
viewrecords:
true,
imgpath:
'/scripts/themes/coffee/images',
caption:
'Product
List'
});
});
</script>
<table
id="list"
class="scroll"
cellpadding="0"
cellspacing="0"></table>
<div
id="pager"
class="scroll"
style="text-align:center;"></div>
</asp:Content>
Finally
let's test by compile and running it.

Cool,
we success use Spring.NET framework and NHibernate ORM in our ASP.MVC
application.
Btw
thanks for reading...and have a nice day 