-
Notifications
You must be signed in to change notification settings - Fork 6
Getting Started
First, I would suggest downloading or at least browsing the Source Code For The SampleUCDArchApp. This application shows what a basic UcdArch site looks like and it also shows how to use a few features.
Getting UcdArch into a new ASPNET MVC 3 application is easy with NuGet. There are 3 different UcdArch packages, depending on your desired level of integration and functionality:
- UcdArch- The UcdArch DLL only. Other packages use this package, and also you could reference this by itself in a separate library if you only needed the DLL.
- UcdArch.NHibernate- UcdArch along with everything required for NHibernate integration.
- UcdArch.Mvc- Adds everything a healthy UcdArch MVC project needs, including a pre-application startup file with helpful configuration defaults and web.config settings
Since we are creating a new ASPNET MVC 3 application, we'll focus on the last one (which actually references the other two).
To get started, create a new ASPNET MVC 3 application and then install UcdArch.Mvc from NuGet. The easiest way to do this is to right-click on your project's "References" folder and then choose "Manage NuGet Packages." Under "Online," search for 'ucdarch' and install the UcdArch.Mvc package. This will bring in UcdArch, NHibernate references, and many other common tools like elmah, Castle Windsor, and DataAnnotationsExtensions.
In additional to binary references, the UcdArch.Mvc package also helps by getting you started with basic configuration. First and foremost, a new file has been added under App_Start/UCDArchBootstrapper.cs which contains the following code:
public class UCDArchBootstrapper
{
/// <summary>
/// PreStart for the UCDArch Application configures the model binding, db, and IoC container
/// </summary>
public static void PreStart()
{
ModelBinders.Binders.DefaultBinder = new UCDArchModelBinder();
NHibernateSessionConfiguration.Mappings.UseFluentMappings(typeof(/* ClassFromMappingsAssembly */).Assembly);
IWindsorContainer container = InitializeServiceLocator();
}
private static IWindsorContainer InitializeServiceLocator()
{
IWindsorContainer container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container));
container.RegisterControllers(typeof(HomeController).Assembly);
ComponentRegistrar.AddComponentsTo(container);
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));
return container;
}
Let's walk through what this file does for you quickly:
First we have ModelBinders.Binders.DefaultBinder = new UCDArchModelBinder();
. This sets up our default model binder to be a custom model binder that lives in UCDArch.Web. This binder knows about NHibernate Repositories and can bind complex classes easily. Also if you want to tweak it a little bit, you can inherit from this class and then hook your own implementation up here.
Next we call NHibernateSessionConfiguration.Mappings.UseFluentMappings(typeof(/* ClassFromMappingsAssembly */).Assembly);
which tells UcdArch you would like to use FluentNHibernate mappings for this project (other mapping types are available) [https://github.com/ucdavis/UCDArch/wiki/Mapping-Configurations]. Before this line will compile, you must provide the name of ANY class from your mapping assembly.
Finally we call InitializeServiceLocator()
, which hooks up Castle.Windsor (our IoC of choice, but of course you can change this) as the ASP.NET MVC controller factory and also registers some default components.
This is all pretty standard except the last two lines (other than the return) need some explanation. ComponentRegistrar.AddComponentsTo(container)
is where you can register your components, which will be injected in to your project as desired. In your project root you will see ComponentRegistrar.cs, which looks like this:
public static class ComponentRegistrar
{
public static void AddComponentsTo(IWindsorContainer container)
{
AddRepositoriesTo(container);
container.AddComponent("validator", typeof(IValidator), typeof(Validator));
container.AddComponent("dbContext", typeof(IDbContext), typeof(DbContext));
}
private static void AddRepositoriesTo(IWindsorContainer container)
{
container.AddComponent("repository", typeof(IRepository), typeof(Repository));
container.AddComponent("genericRepository", typeof(IRepository<>), typeof(Repository<>));
container.AddComponent("typedRepository", typeof(IRepositoryWithTypedId<,>),
typeof(RepositoryWithTypedId<,>));
}
}
Here I am adding DataAnnotationsValidators as the IValidator implementation, adding in the DB context, and registering the Repositories.
Now also note the line ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container))
, which uses Microsoft.Practices.ServiceLocation to register a service locator (and you can create your own if you use something other than Castle Windsor)
So far the UcdArch.Mvc package has added all the previously seen code for you, but now we are ready to start the project and create a controller.
Let's create an OrderController, which will inherit from SuperController (which is the base controller class in UCDArch). Inheriting from the SuperController gives the following benefits:
- Easy access to repositories using Repository.OfType()
- Strong access to the TempData "Message" property using Message
- Shortcut to the IPrincipal object for the current user through CurrentUser
- Default Transactions (by default, every action is wrapped in a transaction)
- Default Anti Forgery Token (by default, every post requires an anti forgery token)
/Controllers/OrderController.cs
public class OrderController : SuperController
{
private readonly IRepository<Order> _orderRepository;
public OrderController(IRepository<Order> orderRepository)
{
_orderRepository = orderRepository;
}
public ActionResult Index()
{
IList<Order> orders = _orderRepository.GetAll();
return View(orders);
}
}
By convention I would usually resist inheriting directly from SuperController in case you need to make solution wide filters or properties in the future. I usually create a class called ApplicationController and inherit from that. public class ApplicationController : SuperController {}
.
In order to use the OrderController, we need to create an Order class that maps to a database. Here we'll use Northwind, so let's first look in Web.Config to setup our database configuration. Notice that towards the bottom NHibernate configuration code has already been created for us by the UcdArch.Mvc package.
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="connection.connection_string_name">MainDB</property>
<property name="default_schema">Northwind.dbo</property>
<property name="generate_statistics">true</property>
<property name="adonet.batch_size">25</property>
</session-factory>
</hibernate-configuration>
This is UcdArch's default configuration, and as you can see you just need to create a ConnectionString named "MainDB" to point to your Northwind datasource. Something like this: <add name="MainDB" connectionString="data source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=true;" providerName="System.Data.SqlClient" />
Now we need to create an Order.cs file, and let's put it in the Models folder for now.
public class Order : DomainObjectWithTypedId<string>
{
public virtual string CustomerId { get; set; }
public virtual DateTime OrderDate { get; set; }
}
public class OrderMap : ClassMap<Order>
{
public OrderMap()
{
Id(x => x.Id).Column("OrderID");
Map(x => x.CustomerId);
Map(x => x.OrderDate);
}
}
Notice the Order class inherits from DomainObjectWithTypedId<string>
. Usually we'd just inherit from DomainObject
but unfortunately Northwind is old and uses non-integer ids with non-standard "ID" names, so there is a little extra config to do, but nothing big. Also we map using FluentHibernate in the OrderMap class, with the only change here being the ID is named "OrderID" (UcdArch conventions assume your DB table is "Orders" from the plural of "Order").
That's about it, you can now run this project and get a fully transactional "Get All" from your OrderController, using FluentNHibernate and the UcdArch framework. Even though the instructions were pretty detailed, the steps basically boil down to:
- Create Your ASPNET MVC 3 Project
- Install the UcdArch.Mvc package from NuGet
- Configure your connection string to point to your DB in the web.config file
- Start creating classes and tell FluentNHibernate where to find your mapping assembly in the UCDArchBootstrapper.cs file.
This was of course just an introduction, please take a look at the SampleUCDArchApp Project in the Source Code for a little more information. I'll be improving that project over time and as new features are added.