Tags: , , | Categories: CSS, HTML Posted by Scott on 4/27/2012 3:48 PM | Comments (0)

Just a quick starter for building a responsive 2-column layout using HTML5 and CSS3 media queries. The key here is progressive enhancement; we start with a stacked layout that will work and is designed for any screen size then we progressively enhance this to add columns to the navigation and aside for wider screens and eventually move the aside to the right of the article content as the line length in the content gets too long and the screen width allows. One thing to notice is that the padding is moved from the outer container (article, aside) in the stacked layout to the child elements in the side-by-side layout.

First the HTML, nothing special here really.

<!DOCTYPE html>
<html>
	<head>
        <title>Test responsive layout</title>
		<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0" />
		<link rel="stylesheet/less" type="text/css" href="screen.less" />
        <script src="less-1.3.0.min.js" type="text/javascript"></script>
	</head>

	<body>
		<div id="banner">
            <h1>Real web developers</h1>
        </div>

		<nav id="primaryNav">
			<ul>
				<li>Primary nav one</li>
				<li>Primary nav two</li>
				<li>Primary nav three</li>
				<li>Primary nav four</li>
				<!--<li>Primary nav five</li>-->
			</ul>
		</nav>

		<div id="mainContent">
            <article>
			    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a purus eget diam tempus consectetur. Curabitur commodo mi lacinia elit placerat non facilisis nibh vestibulum. Aenean placerat felis ut sapien facilisis vitae fermentum purus molestie. Pellentesque lorem magna, placerat a mattis quis, sagittis quis sapien. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Praesent non nisi massa. Etiam lobortis sodales tristique. Fusce placerat elementum placerat. Praesent venenatis dignissim lectus id semper. Ut sagittis tellus ac odio iaculis eget semper est porttitor. Ut et metus eros, commodo laoreet ligula. Donec malesuada tristique sagittis. Quisque fringilla mi id orci eleifend ultrices. Maecenas ac tellus odio, id dignissim dui. Sed urna eros, facilisis et tincidunt in, lobortis eu dui. Vestibulum fermentum sollicitudin molestie.</p>
			    <p>Donec lobortis aliquet lacus, eget pellentesque velit lobortis ut. Nunc scelerisque consectetur dignissim. Duis fermentum iaculis sapien in consectetur. Cras est nibh, consequat a molestie eu, dictum malesuada urna. Nunc volutpat, mauris laoreet ornare hendrerit, enim lorem bibendum nulla, a luctus dolor mi id lacus. Pellentesque interdum nisl sit amet elit posuere rhoncus. Suspendisse potenti. Nulla mi nulla, ultricies at fermentum eget, aliquet et dolor. Quisque ultricies luctus arcu, quis sollicitudin arcu lacinia ut. Nullam bibendum pretium velit. Nunc leo metus, vehicula cursus mattis eget, tincidunt vitae urna.</p>
			    <p>Curabitur sagittis, ligula vel euismod lobortis, nibh felis tincidunt metus, ac gravida tortor nibh eget ligula. Nullam a erat neque, sit amet bibendum lorem. Aliquam vel urna a est convallis semper id in sem. Integer volutpat tristique nisi, id tincidunt diam pretium et. Nunc lorem libero, vulputate dignissim molestie a, pharetra eu ante. Etiam et enim molestie dolor lacinia pharetra. Duis libero nisl, eleifend eu bibendum quis, cursus at est. Nulla adipiscing nulla quis libero tincidunt ac fermentum augue ullamcorper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Quisque in sapien justo, eu imperdiet sapien. Donec auctor leo nec neque convallis placerat.</p>
			    <p>Suspendisse adipiscing, dui id tempus semper, purus elit blandit massa, nec aliquam ipsum urna vehicula lectus. Morbi purus ante, mollis in convallis ac, aliquet ac ligula. Morbi nec nulla nunc, vitae dictum neque. Nullam molestie velit at enim sollicitudin condimentum. Ut in sem purus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus euismod aliquam leo, non varius nibh ornare quis. Morbi a nulla odio. Maecenas nec leo eget libero mollis sodales in sed mi. Nulla facilisi. Mauris eu urna arcu. Pellentesque eget urna vitae quam feugiat fringilla. Vestibulum tellus justo, feugiat in egestas ac, aliquet sed massa. Aliquam erat volutpat. Phasellus sagittis, mi eu semper luctus, turpis nulla facilisis erat, non bibendum lacus velit id lectus.</p>
			    <p>Phasellus pharetra scelerisque elit et eleifend. Phasellus feugiat ultrices ipsum vitae scelerisque. Nullam bibendum lorem eget metus tristique molestie posuere purus tempus. Vivamus odio nisi, facilisis id sollicitudin sit amet, rhoncus in nisl. Praesent dignissim mauris in ante mollis vestibulum. Maecenas molestie lectus nec tellus volutpat placerat. Praesent lacinia sem in sem tempus non egestas ligula scelerisque. Nulla venenatis commodo sapien. Pellentesque in lectus justo. Fusce luctus eleifend purus, eu molestie velit consectetur at. Nullam semper auctor egestas. Quisque posuere ipsum nulla, vel ullamcorper lacus. Aenean porttitor dapibus scelerisque. Suspendisse potenti. Sed sed nibh ac mauris aliquet scelerisque a ac sapien. Pellentesque interdum nulla ac dui gravida luctus.</p>
            </article>
		</div>

		<aside id="secondaryItems">
			<ul>
				<li>Secondary item one</li>
				<li>Secondary item two</li>
				<li>Secondary item three</li>
				<li>Secondary item four</li>
				<li>Secondary item five</li>
				<li>Secondary item six</li>
				<li>Secondary item seven</li>
				<li>Secondary item eight</li>
			</ul>
		</aside>

		<div id="footer">© Real web developers limited.</div>
	</body>
</html>

Next the CSS

* { border: 0; line-height: 1.2; margin: 0; padding: 0; }
body { font-size: 100%; }
body * { font-size: 1em; font-weight: normal; }
li { list-style: none; }
p { padding-bottom: 10px; }
#banner, #primaryNav, #mainContent, #secondaryItems, #footer { padding: 10px; }

#banner { background-color: #fafafa; }
#primaryNav { background-color: #eaeaea; }
#mainContent { background-color: #dadada; }
#secondaryItems { background-color: #cacaca; }

@media screen and (min-width: 480px)
{
    /* create 2 columns in the navigation and the aside ... and clear the floats */
    #primaryNav li { float: left; width: 50%; }
    #primaryNav:after { clear: both; content: '.'; display: block; height: 0; visibility: hidden; }
    #mainContent { clear: both; }
    #secondaryItems:after { clear: both; content: '.'; display: block; height: 0; visibility: hidden; }
    #secondaryItems li { float: left; width: 50%; }
    #footer { clear: both; }
}

@media screen and (min-width: 720px) 
{
    /* change to 3 columns in the navigation and the aside */
    #primaryNav li { float: left; width: 33.3333%; }
    #secondaryItems li { float: left; width: 33.3333%; }
}

@media screen and (min-width: 960px) 
{
    /* change to 4 columns in the navigation and the aside and 2 columns in the main section - the main content spans 3 columns */
    #primaryNav li { float: left; width: 25%; }
    #mainContent { float: left; padding: 0; width: 75%; } /* remove the padding from the container so it doesn't affect the width */
    #mainContent article { margin: 10px; } /* put the padding on the child */
    #secondaryItems { float: right; padding: 0; width: 25%; } /* remove the padding from the container so it doesn't affect the width */
    #secondaryItems ul { margin: 10px; } /* put the padding on the child */
    #secondaryItems li { float: none; width: 100%; }
}

@media screen and (min-width: 1200px) 
{
    /* change to five columns in the navigation and span 4 columns with the main content */
    #primaryNav li { float: left; width: 20%; }
    #mainContent { width: 80%; }
    #secondaryItems { width: 20%; }
}
Tags: , , , , | Categories: ASP.Net, C#, LINQ, NHibernate Posted by Scott on 3/26/2012 9:10 AM | Comments (0)

Here are just a few notes on NHibernate LINQ

  • Does not support Intersect or Union - we generally get what we can using NHibernate and then perform these operations on in-memory collections.
  • Does not support IndexOf - however Contains seems to be case insensitive so we just use this instead - we believe Contains becomes a SQL LIKE comparison so this only works if your Contains is executed within SQL - the in-memory operation is case sensitive but in this case IndexOf becomes available.
  • NHibernate 3.1 is now compiled including LINQ - there's no need to reference NHibernate.Linq
Tags: , , , | Categories: C#, Framework, Validation Posted by Scott on 2/28/2012 6:32 PM | Comments (1)

public class OperationError
{
    public string OperationName { get; set; }
    public string Message { get; set; }
}
public class OperationResult
{
    private bool success = false;
    private List<OperationError> operationErrors = new List<OperationError>();

    public bool Success
    {
        get { return this.success; }
        set { this.success = value; }
    }

    public IList<OperationError> OperationErrors
    {
        get { return this.operationErrors; }
    }
}
public class OperationResult<T> : OperationResult
{
    public T Item { get; set; }
}
public interface IRepository
{
    // gets the single instance of T with the specified Id
    T Get<T>(int Id);

    // gets all instances of T
    IList<T> Get<T>();

    // Saves and instance of T and returns it as OperationResult.Item
    OperationResult<T> Save<T>(T item);

    // Deletes the instance of T
    OperationResult Delete<T>(T item);
}
public class CustomerController : Controller
{
    private IRepository repository;

    // constructor for ninject
    public CustomerController(IRepository repository)
    {
        this.repository = repository;
    }

    [HttpGet]
    public ActionResult Index()
    {
        List&l;tCustomer> allCustomers = this.repository.Get<Customer>();
        return View(allCustomers);
    }

    [HttpPost]
    public ActionResult PostCreate(Customer customer)
    {
        if (ModelState.IsValid)
        {
            OperationResult<Customer> customerResult = this.repository.Save<Customer>(customer);
            if (customerResult.Success)
            {
                return RedirectToAction("Index");
            }

            foreach (var operationError in customerResult.OperationErrors)
            {
                ModelState.AddModelError(Guid.NewGuid().ToString(), operationError.Message);
            }
        }

        return View("Create");
    }
}
Tags: , , , , , , , , , | Categories: ASP.Net, C#, MVC, Razor, HTML, HtmlHelper extensions Posted by Scott on 1/6/2012 6:42 PM | Comments (1)

So, we want a way to bind an HTML <select> to an enum, each enum value becoming an <option>. We also want to be able to hide some of the enum values from the <select> so that we can allow existing data to function but stop new data from using these values.

We start by creating an attribute that we can decorate our enum with, marking values as in use or not. If we don't add the attribute the assumption is that all the values of the enum are still in use which saves the effort of updating every enum in the application domain.

public class EnumBindingAttribute : Attribute
{
    public bool IsInUse { get; set; }
}

Then we decorate the enum with the new attribute.

public enum ContactNumberType
{
    [EnumBinding(IsInUse=false)]
    Unknown,
    [EnumBinding(IsInUse = true)]
    Home,
    [EnumBinding(IsInUse = true)]
    Work,
    [EnumBinding(IsInUse = true)]
    Mobile,
    [EnumBinding(IsInUse = false)]
    Fax,
    [EnumBinding(IsInUse = false)]
    Other
}

Now, to bind the enum to the <select> we have an extension to HtmlHelper. This emits a <select> tag with id and name attributes and then enumerates the additional attributes specified in the dictionary, adding each in turn. These additional attributes are essential for aria- and data- which you'll probably be using. Next comes the fun - reflection. We enumerate each of the values in the enum, test for the existence of the EnumBindingAttribute and skip any that have the attribute set to false. For those that we are rendering we check for a DescriptionAttribute and use that if it's present otherwise we render out the enum as a string. If the value of the enum matches the selectedValue parameter we add the selected attribute to the <option> tag.

public static MvcHtmlString DropDownListEnum<T>(this HtmlHelper helper, string name, Type enumeration, string selectedValue, Dictionary<string, object> htmlAttributes)
{
    StringBuilder output = new StringBuilder();
    output.AppendFormat("<select id=\"{0}\" name=\"{0}\"", name);
    foreach (var attribute in htmlAttributes)
    {
        if (attribute.Value != null)
        {
            output.AppendFormat(" {0}=\"{1}\"", attribute.Key, attribute.Value);
        }
        else
        {
            output.AppendFormat(" {0}", attribute.Key);
        }
    }

    output.Append(" >");
    foreach (var enumValue in enumeration.GetEnumValues())
    {
        FieldInfo fieldInfo = enumeration.GetField(enumValue.ToString());
        EnumBindingAttribute[] enumbindingAttributes = (EnumBindingAttribute[])fieldInfo.GetCustomAttributes(typeof(EnumBindingAttribute), false);
        if (!enumbindingAttributes.Any() || enumbindingAttributes.Any(e => e.IsInUse)) // no attribute set implies is in use
        {
            int enumIntValue = (int)enumValue;
            output.Append("<option");
            if (selectedValue == enumIntValue.ToString())
            {
                output.Append(" selected=\"selected\"");
            }

            output.AppendFormat(" value=\"{0}\">", enumIntValue.ToString());
            DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (attributes.Any())
            {
                output.Append(attributes[0].Description);
            }
            else
            {
                output.Append(enumValue.ToString());
            }

            output.Append("</option>");
        }
    }

    output.Append("");
    return MvcHtmlString.Create(output.ToString());
}

Now we just use the HtmlHelper extension!

@model ContactNumber
@using (Html.BeginForm("UpdateContactNumber", "Members", null, FormMethod.Post, null))
{
    @Html.HiddenFor(m => m.Id)
    
Contact Numbers @Html.DropDownListEnum("ContactNumberType", typeof(ContactNumberType), Model == null ? "0" : ((int)Model.ContactNumberType).ToString(), new Dictionary<string, object> { { "aria-required", "true" }, { "aria-labelledby", "ulblType" }, { "required", null } })
}
Tags: , , , , , , , , , , | Categories: ASP.Net, C#, MVC, NHibernate, Razor Posted by Scott on 12/19/2011 10:53 AM | Comments (2)

We keep discussing what use a view model has and where (if at all) we should be using them. Eventually we came to some conculsions, not all of which are obvious.

Firstly a view model is important to keeping your views clean; it should provide all of the data required by a view - this avoids calling entity managers from within a view to get (for arguements sake) the list of orders for a customer. Putting this kind of code in your views is bad; it puts business logic into a file that should be exclusively UI logic, it puts executable code into a file that is not (usually) compiled, it puts code beyond the reach of (most) refactoring tools and, it creates a very confusing document.

Secondly a view model provides a buffer between our domain models and our web application - yes, our web application does have visibility of the domain models and an api via the entity manager to CRUD the entities but, should an entity be forced to implement a parameterless constructor so that binding can take place? Or (as in our case) should our protected internal parameterless .ctor (written for the exclusive use of NHibernate) now become public and therefore bypass some of the business logic that is implemented within the parameterised .ctors?

Clearly the answer is no but we can create a view model within our application that mirrors the domain model and provides the required parameterless .ctor, binding can take place, validation can happen and the only cost is calling the parameterised .ctor on the domain model, passing in the values from the view model.

Let's explain this with an example. Firstly, our domain class Client, note that the default parameterless .ctor is protected internal so it will not be available within our MVC application and therefore not available to MVC model binding. The public .ctor implements our business logic that all clients must have a forename and surname (this could be further enhanced within the .ctor by adding validation errors if either forename or surname are null or empty).

namespace Playground.Models
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NHibernate.Validator.Constraints;

    public class Client : BaseEntity
    {
        private IList<ClientEmailAddress> emailAddresses = new List<ClientEmailAddress>();
        private IList<ClientTelephoneNumber> telephoneNumbers = new List<ClientTelephoneNumber>();

        // public .ctor requires forename and surname
        public Client(string forename, string surname)
        {
            this.Forename = forename;
            this.Surname = surname;
        }

        // internal .ctor for NHibernate. Never expose this publically.
        protected internal Client() { }

        // NotNullNotEmpty attribute from NHibernate.Validation.Constraints
        [NotNullNotEmpty()]
        public virtual string Forename { get; set; }

        // NotNullNotEmpty attribute from NHibernate.Validation.Constraints
        [NotNullNotEmpty()]
        public virtual string Surname { get; set; }

        public virtual IList<ClientEmailAddress> EmailAddresses
        {
            get { return this.emailAddresses; }
            private set { this.emailAddresses = value; }
        }

        public virtual IList<ClientTelephoneNumber> TelephoneNumbers
        {
            get { return this.telephoneNumbers; }
            private set { this.telephoneNumbers = value; }
        }
    }
}

So, what do we do within our MVC application that wants to perform CRUD operations on our Client type? Well, we could use the type directly within our MVC controller:

namespace Playground.Web.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Playground.BusinessLogic;
    using Playground.Models;

    public class ClientController : Controller
    {
        [HttpGet]
        public ActionResult Add()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Add(string forname, string surname)
        {
            if (!ModelState.IsValid)
            {
                return View();
            }

            Client client = new Client(forename, surname);
            client = this.entityManager.Save(client);
            if (client.ValidationErrors.Any() || client.OperationErrors.Any())
            {
                foreach (var validationError in client.ValidationErrors)
                {
                    ModelState.AddModelError(validationError.Property, validationError.Error);
                }

                foreach (var operationError in client.OperationErrors)
                {
                    ModelState.AddModelError(operationError.Operation, operationError.Error);
                }

                return View();
            }

            return RedirectToAction("Index");
        }
    }
}

The issue with this approach is that checking the ModelState.IsValid property really doesn't do anything and we're all the way into the Save method before we get any validation of our object. And when we do validate we're pulling business (or possibly database) errors and their not-so-user-friendly messages into our UI. The typical solution is to use the domain model for the parameter on the post method of the controller (and as the model in the view) which automagically wires up form values with properties on the model. This type of model binding requires a default parameterless .ctor which now doesn't exist because it would break the business rules on the Client type.

So what we really want is to use types throughout our MVC application, use binding within our controllers and, not break our business rules. If we create a model within our MVC application - a view model - we can solve our issue and get early validation with user friendly messages into the bargin. Note the namespace and the implicit default parameterless .ctor.

namespace Playground.Web.ViewModels
{
    using System; 
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.ComponentModel.DataAnnotations;

    public class Client
    {
        // Required is from the System.ComponentModel.DataAnnotations namespace.
        [Required(ErrorMessage="This is a user friendly validation message")]
        public virtual string Forename { get; set; }

        [Required()]
        public virtual string Surname { get; set; }
    }
}

Now we can update our controller to use our view model:

namespace Playground.Web.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using Playground.BusinessLogic;
    using Playground.Models;

    public class ClientController : Controller
    {
        [HttpGet]
        public ActionResult Add()
        {
            return View(new Playground.Web.ViewModels.Client());
        }

        [HttpPost]
        public ActionResult Add(Playground.Web.ViewModels.Client postedClient)
        {
            if (!ModelState.IsValid)
            {
                return View(postedClient);
            }

            Client client = new Client(postedClient.Forename, postedClient.Surname);
            client = this.entityManager.Save(client);
            if (client.ValidationErrors.Any() || client.OperationErrors.Any())
            {
                foreach (var validationError in client.ValidationErrors)
                {
                    ModelState.AddModelError(validationError.Property, validationError.Error);
                }

                foreach (var operationError in client.OperationErrors)
                {
                    ModelState.AddModelError(operationError.Operation, operationError.Error);
                }

                return View(postedClient);
            }

            return RedirectToAction("Index");
        }
    }
}

Now when we check ModelState.IsValid we're checking the attributes for the view model before we try to save the domain object.We also get the advantage of using model binding with the view like this:

@model Playground.Web.ViewModels.Client

@{
    ViewBag.Title = "Add";
}

Add

@using (Html.BeginForm()) { @Html.ValidationSummary(true)
Client
@Html.LabelFor(model => model.Forename)
@Html.EditorFor(model => model.Forename) @Html.ValidationMessageFor(model => model.Forename)
@Html.LabelFor(model => model.Surname)
@Html.EditorFor(model => model.Surname) @Html.ValidationMessageFor(model => model.Surname)

}
@Html.ActionLink("Back to List", "Index")

And we have the advantage where we can add properties to the view model that aren't required on the domain model; the user input on a registration form might require the password to be confirmed (an attempt at mitigating typos resulting in the user setting their password incorrectly) so a ConfirmPassword property can be added to the view model together with a validator but the domain model need not be sullied with this non-persisted, UI only property.

Tags: , , | Categories: C#, NHibernate Posted by Admin on 12/16/2011 10:31 AM | Comments (0)

So today we were working on a new sample project using NHibernate, Ninject and, ASP.Net MVC3 which (as is usually the case at the start of these things) we wanted to be just right. Typically we ended up with a Client type with its expected lists of phone number and email address, in each list none or one of which can be flagged as being the default. We ended up with a class hierarchy like:

public abstract class BaseEntity
{
    public virtual int Id { get; set; }
}
public abstract class BaseEmailAddress : BaseEntity
{
    public virtual string EmailAddress { get; set; }
    public virtual bool IsDefault { get; set; }
}
public class ClientEmailAddress : BaseEmailAddress
{
    private Client client;

    public virtual Client Client
    {
        get { return this.client; }
        private set { this.client = value; }
    }
}
public class Client : BaseEntity
{
    private IList<ClientEmailAddress> emailAddresses = new List<ClientEmailAddress>();

    public virtual IList<ClientEmailAddress> EmailAddresses
    {
        get { return this.emailAddresses; }
        private set { this.emailAddresses = value; }
    }
}

Everything inherits BaseEntity, ClientEmailAddress inherits BaseEmailAddress which implements the EmailAddress and IsDefault properties.

So then we questioned where do we implement the none or one ClientEmailAddress being flagged IsDefault? We decided that we could shadow the IsDefault property in ClientEmailAddress and implement the logic in the setter; if setting my IsDefault property to true then set the IsDefault property of all the other items in my parents ClientEmailAddresses collection. Like this:

public class ClientEmailAddress
{
    private Client client;

    public virtual Client Client
    {
        get { return this.client; }
        private set { this.client = value; }
    }

    public new virtual bool IsDefault
    {
        get { return base.isDefault; }
        set
        {
            if (value && this.client != null)
            {
                foreach (var clientEmailAddress in this.client.ClientEmailAddresses)
                {
                    clientEmailAddress.IsDefault = false;
                }
            }

            base.isDefault = value;
        }
    }
}

However, NHibernate did not like this very much, complaining the 'IsDefault is already mapped' or similar which got us to thinking whether the IsDefault property belonged on a BaseEmailAddress type? After some debate we can to the conclusion that the IsDefault property is only relevent to the ClientEmailAddress type since it is only in the context of a list of email addresses that being the default email address makes any sense. So we moved the IsDefault property to the relevent class:

public abstract class BaseEmailAddress
{
    public virtual string EmailAddress { get; set; }
}
public class ClientEmailAddress
{
    private Client client;

    public virtual Client Client
    {
        get { return this.client; }
        private set { this.client = value; }
    }

    private bool isDefault = false;

    public virtual bool IsDefault
    {
        get { return this.isDefault; }
        set
        {
            if (value && this.client != null)
            {
                foreach (var clientEmailAddress in this.client.ClientEmailAddresses)
                {
                    clientEmailAddress.IsDefault = false;
                }
            }

            this.isDefault = value;
        }
    }
}
Tags: , , , | Categories: ASP.Net, C#, NHibernate Posted by Admin on 12/5/2011 9:16 AM | Comments (0)

We re-factored a few namespaces and split a few class libraries into multiple assemblies to enable some code re-use but then struggled to automap them using Fluent NHibernate. We quickly noticed that types were being loaded from the different assemblies, but not all of them. It seemed that those types in assembly B that inherited from types in assembly A were not being loaded which in fact was the vast majority of the types in assembly B. We also noticed that other types in assembly B who did not inherit from types in assembly A were also not being loaded. A quick inspection of the inheritance tree showed that only those types in assembly B who inherited from an abstract type were being loaded. In our case the solution was to simple ensure that all the subclasses were defined as abstract types.

// type defined in RealWebDevelopers.Models.dll
namespace RealWebDevelopers.Models
{
    public abstract class BaseEntity
    {
        public int Id { get; set; }
    }
}
// type defined in RealWebDevelopers.Models.Jobs.dll
namespace RealWebDevelopers.Models.Jobs
{
    using RealWebDevelopers.Models;

    public class Advertisement : BaseEntity
    {
        public string Name { get; set; }
    }
}
namespace RealWebDevelopers.Data
{
    using RealWebDevelopers.Models;
    using RealWebDevelopers.Models.Jobs;

    <summary>Loads multiple assemblies into the MappingConfiguration.</summary>
    private void MapAssemblies(FluentNHibernate.Cfg.MappingConfiguration config)
    {
        config.AutoMappings.Add(
            AutoMap.Assembly(Assembly.GetAssembly(typeof(BaseEntity)))
            .Override<BaseEntity>(a =>
            {
                a.IgnoreProperty(e => e.OperationErrors);
                a.IgnoreProperty(e => e.ValidationErrors);
            })
            .Conventions.AddFromAssemblyOf<EnumConvention>());
        config.AutoMappings.Add(
            AutoMap.Assembly(Assembly.GetAssembly(typeof(Advertisement)))
            .Override<TokenTransaction>(n => n.Map(c => c.TransactionType).CustomType<int>())
            .OverrideAll(a =>
            {
                a.IgnoreProperty("Display");
            })
            .Conventions.AddFromAssemblyOf<EnumConvention>());
    }
}
Tags: , | Categories: C#, Fluent, NHibernate Posted by Admin on 11/21/2011 4:06 PM | Comments (1)

So, Country has a collection of Counties

public class Country
{
    private IList<County> counties = new List<County>();
    public virtual IList<County> Counties
    {
        get { return this.counties; }
        set { this.counties = value; }
    }
}

Therefore County has a reference to Country

public class County
{
    public virtual Country Country { get; set; }
}

I was trying to create a new County and then add it to the Counties collection of a Country instance

public static void Something()
{
    Country country = repository.Get<Country>(countryId);
    County county = new County(){ Name = "Berkshire" };
    country.Counties.Add(county);    //this executes
    repository.Save<Country>(country);    //this bails
}

The solution was to test the parent Country's County collection within the Country setter of the County class

public class County
{
    private Country country = null;
    public virtual Country Country
    {
        get { return this.country; }
        set
        {
            this.country = value;
            if (!this.country.Counties.Contains(this))
            {
                this.country.Counties.Add(this);
            }
        }
    }
}

Why? Well I don't really know, but it works. I guess that there is something going on within NHibernate and object tracking, but that is just a guess!

For a more fluent way of doing the same thing

public class County
{
    public virtual Country Country { get; protected set; }
    
    public virtual County WithCountry(Country country)
    {
        this.country = value;
        if (!this.country.Counties.Contains(this))
        {
            this.country.Counties.Add(this);
        }

        return this;
    }
}
Tags: , | Categories: C#, Fluent Posted by Admin on 9/21/2011 8:17 AM | Comments (0)

A while ago we wrote about fluent apis using interfaces, this is probably the 'text book' approach but since we're about real web development lets have a real world approach.

public class Country
{
    // backing field for the name property.
    private string name = string.Empty;

    // backing field for the code property;
    private string code = string.Empty;

    // accessor to the name backing field. The setter is private.
    public string Name
    {
        get { return this.name; }
        private set { this.name = value; }
    }

    // accessor to the code backing field. The setter is private.
    public string Code
    {
        get { return this.code; }
        private set { this.code = value; }
    }

    // chainable (fluent) method to set the name. Note this returns to instance of the entity whose property is being set.
    public Country WithName(string name)
    {
        this.Name = name;
        return this;
    }

    // chainable (fluent) method to set the code. Note this returns to instance of the entity whose property is being set.
    public Country WithCode(string code)
    {
        this.Code = code;
        return this;
    }
}

So if we were to use this class within an application we can now write code like

Country unitedKingdom = new Country().WithName("United Kingdom").WithCode("UK");
Tags: , , , , , , | Categories: ASP.Net, C#, Fluent, MVC, NHibernate, Ninject, NHibernate,Validator Posted by Admin on 9/14/2011 4:26 PM | Comments (1)

Eventually (after lots of google searches and putting together snippets from here, there and, everywhere) we now have Fluent NHibernate, NHibernate.Validator and Ninject all playing together.

First, we configure NHibernate using Fluent NHibernate passing the configuration to NHibernate.Validator so that it can configure the NHibernateSharedEngineProvider - this is important as Ninject will use the NHibernateSharedEngineProvider.

public static class Database
{
    private static ISessionFactory sessionFactory = null;

    public static ISessionFactory CreateSessionFactory()
    {
        var config = new AutoMappingConfiguration();
        ValidatorEngine validatorEngine = null;
        if (sessionFactory == null)
        {
                sessionFactory = Fluently
                .Configure()
                .Database(
                    MsSqlConfiguration
                    .MsSql2008
                    .ConnectionString(c => c.Server("").Database("").TrustedConnection()))
                .Mappings(
                    m => m.AutoMappings.Add(
                        AutoMap.AssemblyOf<EntityBase>(config)
                        .Override<EntityBase>(n => n.IgnoreProperty(c => c.ValidationErrors))
                        .Override<Country>(n => n.IgnoreProperty(c => c.DisplayName))
                        ))
                .ExposeConfiguration(c => { 
                    validatorEngine = ConfigureNHibernateValidator(c); 
                    BuildSchema(c); 
                })
                .BuildSessionFactory();
        }

        return sessionFactory;
    }

    public static ValidatorEngine ConfigureNHibernateValidator(Configuration nhibernateConfiguration)
    {
        NHibernate.Validator.Cfg.Environment.SharedEngineProvider = new NHibernateSharedEngineProvider();
        var validatorConfiguration = new NHibernate.Validator.Cfg.Loquacious.FluentConfiguration();
        validatorConfiguration
            .SetDefaultValidatorMode(ValidatorMode.UseAttribute)
            .Register(Assembly.Load("models").ValidationDefinitions())
            .IntegrateWithNHibernate
            .ApplyingDDLConstraints()
            .RegisteringListeners();
        var validatorEngine = NHibernate.Validator.Cfg.Environment.SharedEngineProvider.GetEngine();
        validatorEngine.Configure(validatorConfiguration);
        ValidatorInitializer.Initialize(nhibernateConfiguration, validatorEngine);
        return validatorEngine;
    }

    private static void BuildSchema(Configuration config)
    {
        new SchemaUpdate(config).Execute(false, true);
    }
}

Then we configure Ninject

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IEntityManager>().To<EntityManager>().InRequestScope();
    kernel.Bind<ISessionFactory>().ToMethod(x => Database.CreateSessionFactory()).InSingletonScope();
    kernel.Bind<ISession>().ToMethod(x => kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
    kernel.Bind<ISharedEngineProvider>().ToMethod(x => NHibernate.Validator.Cfg.Environment.SharedEngineProvider).InSingletonScope();
}

Then we inject both ISession and ISharedEngineProvider into our EntityManager via the .ctor. We then check the Entity is valid before saving.

public class EntityManager : IEntityManager
{
    private ISession session = null;
    private ISharedEngineProvider validator = null;

    public EntityManager(ISession session, ISharedEngineProvider validator)
    {
        this.session = session;
        this.validator = validator;
    }

    public T Save<T>(T item) where T : EntityBase
    {
        item.ValidationErrors.Clear();
        ValidatorEngine ve = this.validator.GetEngine();
        if (!ve.IsValid(item))
        {
            foreach (var invalidValue in ve.Validate(item))
            {
                item.ValidationErrors.Add(new ValidationError() { PropertyName = invalidValue.PropertyName, Message = invalidValue.Message });
            }
        }
        else
        {   
            try
            {
                this.session.SaveOrUpdate(item);
                this.session.Flush();
            }
            catch (InvalidStateException ise)
            {
                item.ValidationErrors.Clear();
                foreach (var invalidValue in ise.GetInvalidValues())
                {
                    item.ValidationErrors.Add(new ValidationError() { PropertyName = invalidValue.PropertyName, Message = invalidValue.Message });
                }
            }
        }

        return item;
    }
}

Note that within EntityManager we use ISharedEngineProvider.GetEngine() to get our pre-configured Validator. The try { ... } catch { ... } around this.Session.SaveOrUpdate(item) isn't really required but better to be safe than sorry!