<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://blog.aabech.no/rss/xslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Lars-Erik's blog</title>
    <link>https://blog.aabech.no/</link>
    <description>Ramblings about Umbraco, .net and JavaScript development. With a sprinkle of other stuff.</description>
    <generator>Articulate, blogging built on Umbraco</generator>
    <item>
      <guid isPermaLink="false">1138</guid>
      <link>https://blog.aabech.no/archive/morphing-ucommerce-products/</link>
      <category>umbraco</category>
      <category>ucommerce</category>
      <title>Morphing UCommerce Products</title>
      <description>&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;Today I had a new but fun challenge with UCommerce. Turns out, as usual, it's a great fit for my whims with architecture.
I was stuck between a rock and a hard place when I was looking at adding a custom pricing algoritm.
I can't go into details, but there's custom client pricing involved of course.
To add to the fun, we're mapping UCommerce products to DTOs for wire transfer. We could aslo have been mapping to view models or something else. To map we're using AutoMapper with quite a few configurations and jumps-through-hoops.&lt;/p&gt;
&lt;p&gt;I had this code (ish):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var products = productRepository.Select().Where(SomePredicate);
var mapped = products.Select(Mapper.Map&amp;lt;ProductDto&amp;gt;);
return mapped;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I immediately thought of a few options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Iterate over the products and change prices here&lt;/li&gt;
&lt;li&gt;Create a Product adapter with additional logic and map from that&lt;/li&gt;
&lt;li&gt;Execute the pricing logic from AutoMapper configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They all seemed weird and out of place though. None seemed like they would be easy to find for the next developer. Not even with unit tests. It just didn't seem right.
Changing data on the entities would mean I'd have to go out of my way to ensure nobody went and saved those products later in the request. Creating an adapter would mean loads of new instances, bloated wrapper classes and weird names.
And finally executing business logic from AutoMapper configuration means I'd been mixing responsibilities en mass.&lt;/p&gt;
&lt;h2&gt;UCommerce &amp;amp; NHibernate to the rescue&lt;/h2&gt;
&lt;p&gt;Luckily I've been using EntityFramework a lot and tried to force it into my Domain Driven Design patterns since it's infancy. I've been through the lot (and I enjoy it). So I kind of know what to expect from an ORM. When using UCommerce I'm stuck with NHibernate, but I haven't really been doing it justice by just leaving it in the background. (And fiddling with Entity Framework - which is just as good!)
Together the two systems are extremely powerful. UCommerce have even documented the possibilities,
though the documentation fails to point out the really juicy benefits.&lt;/p&gt;
&lt;p&gt;We have &lt;code&gt;ProductDefintion&lt;/code&gt;, right? It allows us to set up product types with different properties and variant options. It even supports inheritance. But we're still stuck with the &lt;code&gt;Product&lt;/code&gt; class and its &lt;code&gt;GetProperty()&lt;/code&gt; overrides. In my case, I'd like to have &lt;code&gt;ProductWithFancyPricing&lt;/code&gt; so I could override that &lt;code&gt;GetPrice()&lt;/code&gt; method. If I could have &lt;code&gt;ProductWithFancyPricing&lt;/code&gt; and &lt;code&gt;ProductWithEvenFancierPricing&lt;/code&gt; that would be totally awesome.&lt;/p&gt;
&lt;p&gt;Turns out you can have your cake and eat it too. When properly using an ORM you can exploit OOP like it's supposed to and use polymorphism for varying behavior. It's possible to set up an inheritance tree so the mapper automatically handles creation of different types for you. You've basically got three options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Table per concrete class (type)
&lt;ul&gt;
&lt;li&gt;All classes have a table of their own&lt;/li&gt;
&lt;li&gt;Useful when base classes don't have (much) data&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Table per hierarchy
&lt;ul&gt;
&lt;li&gt;One table per base class&lt;/li&gt;
&lt;li&gt;Useful when &lt;em&gt;all&lt;/em&gt; data is on the base class&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Table per subclass
&lt;ul&gt;
&lt;li&gt;One common table for base data&lt;/li&gt;
&lt;li&gt;Individual tables per derived class with only additional data&lt;/li&gt;
&lt;li&gt;Useful when there are some data in both classes. (Think umbracoNode)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my case, I don't need any new data on the derived classes. It's all there in &lt;code&gt;GetProperty()&lt;/code&gt; anyway.
&lt;em&gt;(I will add some getters though. ModelsBuilder, anyone? )&lt;/em&gt;&lt;br /&gt;
So for me it's going to be Table per hierarchy. The rest of the options are all viable for this technique if you have other requirements.
You can &lt;a href="https://docs.ucommerce.net/ucommerce/v7.12/extending-ucommerce/extending-ucommerce-entities.html"&gt;read a bit about it in the UCommerce docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Mapping some product types&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;(I inadvertently wrote document types there. ModelsBuilder, anyone?)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In order to have NHibernate treat products as subclasses with the Table per hierarchy strategy it needs a way to pick the right class for each record. That way is known as discriminator columns. I first thought I could just discriminate by the ProductDefinitionId, but it turns out NHibernate doesn't support discriminating on a column already in use for associations (foreign keys) or other means.&lt;br /&gt;
We have to add a column. I just call it &amp;quot;Discriminator&amp;quot; and make it a varchar.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alter table uCommerce_Product add Discriminator nvarchar(max)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then we need some entities. I added a couple of docu... product types:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class ProductWithFancyPricing : UCommerce.EntitiesV2.Product
{
    public override Money GetPrice(PriceGroup priceGroup)
    {
        var price = base.GetPrice(priceGroup);
        if (IsChristmas())
        {
            price = new Money(price.Value * 2, price.Culture, price.Currency);
        }
        return base.GetPrice(priceGroup);
    }
}

public class ProductWithEvenFancierPricing : UCommerce.EntitiesV2.Product
{
    public override Money GetPrice(PriceGroup priceGroup)
    {
        var blackMarket = ObjectFactory.Instance.Resolve&amp;lt;IBlackMarketService&amp;gt;();
        var priceValue = blackMarket.GetPrice(Sku);
        return new Money(priceValue, priceGroup.Currency);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next thing you need is to tell NHibernate that these are our new product classes:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class ProductWithFancyPricingMapping : FluentNHibernate.Mapping.SubclassMap&amp;lt;ProductWithFancyPricing&amp;gt;
{
    public ProductWithFancyPricingMapping()
    {
        DiscriminatorValue(&amp;quot;Product with fancy pricing&amp;quot;);
    }
}

public class ProductWithEvenFancierPricingMapping : FluentNHibernate.Mapping.SubclassMap&amp;lt;ProductWithEvenFancierPricing&amp;gt;
{
    public ProductWithEvenFancierPricingMapping()
    {
        DiscriminatorValue(&amp;quot;Product with naughty pricing&amp;quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We also need to subclass UCommerce's mapping for Product in order to tell UCommerce which column to use as the discriminator:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class ProductMap : global::UCommerce.EntitiesV2.Maps.ProductMap
{
    public ProductMap()
    {
        DiscriminateSubClassesOnColumn(&amp;quot;Discriminator&amp;quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally we need a class in the same assembly with a tag on it. &lt;a href="https://docs.ucommerce.net/ucommerce/v7.12/extending-ucommerce/save-custom-data-in-the-database.html"&gt;More on that in the UCommerce docs&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class MappingMarker : IContainsNHibernateMappingsTag
{
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To have NHibernate pick the right classes now, we just need to fix the existing products if we have any.
I have called my discriminator values the same as my document types, so I can easily construct a query as such:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;update
    ucommerce_product
set 
    discriminator = case productdefinitionid
        when 10 then 'Product with fancy pricing'
        when 11 then 'Product with naughty pricing'
        else null
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now if we go...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var products = productRepository.Select();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;...we'll get a bounch of &lt;code&gt;ProductWithFancyPricings&lt;/code&gt; and &lt;code&gt;ProductWithEvenFancierPricing&lt;/code&gt;.
If you have more types, you might get into trouble though. You need to have a discriminator on them all.&lt;/p&gt;
&lt;h2&gt;The final hurdle&lt;/h2&gt;
&lt;p&gt;So that's cool. That's really cool. But there's one hurdle we have to jump over before we can cross the goal line. From very nasty experiences I knew I had to test &lt;em&gt;everything&lt;/em&gt; manually and integrated. So I went and tried to see what happened if I added a product through the UCommerce Admin UI.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;boom&lt;/em&gt; :)&lt;/p&gt;
&lt;p&gt;'Course it didn't work. It actually did, and didn't. Several weird things happened ranging from strange NHibernate mapping exceptions to products getting the discriminator &amp;quot;UCommerce.EntitiesV2.Product&amp;quot;. (Which makes a lot of sense if you think about it)&lt;/p&gt;
&lt;p&gt;The @#¤%&amp;amp; &lt;code&gt;CreateCategoryOrProduct.as[p|c]x&lt;/code&gt; WebForms control is in our way. It instantiates a &lt;code&gt;Product&lt;/code&gt; and saves it. It's completely sealed and unconfigurable. We could overwrite it with a custom one, but that would open another can of worms with regards to upgrading, source control and what-not. Luckily it's going away very very soon in UCommerce V8. (2018?)&lt;/p&gt;
&lt;p&gt;After hacking at it a bit my final resolve was to add a step right after save in the product saving pipeline. Again, UCommerce is so versatile that even when it sucks, it's got a golden workaround right up its arm.
If you're not familiar with UCommerce Pipelines, &lt;a href="https://docs.ucommerce.net/ucommerce/v7.12/extending-ucommerce/create-pipeline-task.html"&gt;go read about it here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here's the extra configuration. (In a .config file included from UCommerce's custom.config)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- PRODUCT CLASS FIX --&amp;gt;
&amp;lt;component id=&amp;quot;SaveProduct&amp;quot;
           service=&amp;quot;UCommerce.Pipelines.IPipeline`1[[UCommerce.EntitiesV2.Product, UCommerce]], UCommerce&amp;quot;
           type=&amp;quot;UCommerce.Pipelines.Catalog.ProductPipeline, UCommerce.Pipelines&amp;quot;&amp;gt;
  &amp;lt;parameters&amp;gt;
    &amp;lt;tasks&amp;gt;
      &amp;lt;array&amp;gt;
        &amp;lt;value&amp;gt;${Product.UpdateRevision}&amp;lt;/value&amp;gt;
        &amp;lt;value&amp;gt;${Product.Save}&amp;lt;/value&amp;gt;
        &amp;lt;value&amp;gt;${FixProductClass}&amp;lt;/value&amp;gt;
        &amp;lt;value&amp;gt;${Product.IndexAsync}&amp;lt;/value&amp;gt;
      &amp;lt;/array&amp;gt;
    &amp;lt;/tasks&amp;gt;
  &amp;lt;/parameters&amp;gt;
&amp;lt;/component&amp;gt;

&amp;lt;component id=&amp;quot;FixProductClass&amp;quot;
           service=&amp;quot;UCommerce.Pipelines.IPipelineTask`1[[UCommerce.EntitiesV2.Product, UCommerce]], UCommerce&amp;quot;
           type=&amp;quot;My.Awesome.Site.Persistence.FixProductClassTask, My.Awesome.Site.UCommerce&amp;quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A pipeline task gets a reference to the entity being handled, so we can't just go and replace the entire product with an instance of the right type. But we can fake it and force the database value to be correct after saving.
UCommerce uses NHibernate level 2 cache, so we need to flush that as well, but we'll get to that.&lt;/p&gt;
&lt;p&gt;Forcing the database is fairly easy. We have to resort to good old ADO code, which was actually a joyful little deja-vu experience (although I'm glad it was brief):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class FixProductClassTask : IPipelineTask&amp;lt;Product&amp;gt;
{
    private readonly IStatelessSessionProvider sessionProvider;

    public FixProductClassTask(IStatelessSessionProvider sessionProvider)
    {
        this.sessionProvider = sessionProvider;
    }

    public PipelineExecutionResult Execute(Product subject)
    {
        var command = sessionProvider.GetStatelessSession().Connection.CreateCommand();
        command.CommandText = &amp;quot;UPDATE uCommerce_Product SET Discriminator = @discriminator WHERE ProductId = @productId&amp;quot;;
        command.CommandType = CommandType.Text;
        var discriminatorParam = command.CreateParameter();
        discriminatorParam.ParameterName = &amp;quot;discriminator&amp;quot;;
        discriminatorParam.Value = subject.ProductDefinition.Name;
        var idParam = command.CreateParameter();
        idParam.ParameterName = &amp;quot;productId&amp;quot;;
        idParam.Value = subject.Id;
        command.Parameters.Add(discriminatorParam);
        command.Parameters.Add(idParam);
        command.ExecuteNonQuery();

        // TODO: Clear cache

        return PipelineExecutionResult.Success;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I'm sure a lot of sazzy devs out there could prettify this a bit, but it does the job. Insert a &lt;a href="/archive/kill-switch-weve-got-action/"&gt;switch/case (please don't)&lt;/a&gt; or whatever you fancy if the product definition name isn't what you discriminate by. I'll leave it up to you to choose between strings, ints or even enums for performance vs. readability.&lt;/p&gt;
&lt;p&gt;If you've turned off the level 2 cache, you might be fine with this. Otherwise we'd better &amp;quot;evict&amp;quot; the entity from the cache. We need to do that in order for the cached instance to change type from &lt;code&gt;Product&lt;/code&gt; to &lt;code&gt;ProductWithFancyPricing&lt;/code&gt;. Sadly the NHibernate &lt;code&gt;SessionFactory&lt;/code&gt; in charge of doing this is hidden in an internal static field in UCommerce, so we need to resort to some nasty reflection to do it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ...
command.ExecuteNonQuery();

var fieldInfo = typeof(SessionProvider).GetField(&amp;quot;_factory&amp;quot;, BindingFlags.Static | BindingFlags.NonPublic);
if (fieldInfo == null) throw new Exception(&amp;quot;SessionFactory instance has moved in this UCommerce version. %(&amp;quot;);
var sessionFactory = (ISessionFactory)fieldInfo.GetValue(null);
sessionFactory.Evict(typeof(Product), subject.Id);

return PipelineExecutionResult.Success;
// ...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Et voilá! We can now save new products, and they immediately morph into the correct derived type.
(Except for when being saved to RavenDB for the first time, ref. the config).&lt;/p&gt;
&lt;p&gt;I'm now free to go back into the instances and implement however naughty pricing I fancy. \o/&lt;/p&gt;
&lt;h2&gt;Added bonuses&lt;/h2&gt;
&lt;p&gt;I already &lt;a href="https://docs.ucommerce.net/ucommerce/v7.12/extending-ucommerce/save-custom-data-in-the-database.html"&gt;have a custom entity in the database and NHibernate model&lt;/a&gt;. It has two associations to &lt;code&gt;Product&lt;/code&gt;. Had I realized what I had under my fingertips it would already have been collections on my new shiny subclasses.&lt;/p&gt;
&lt;p&gt;I recon you noticed I referenced ModelsBuilder a couple of times. How 'bout having all your properties statically typed on your product instances. How about some interfaces?&lt;/p&gt;
&lt;p&gt;I'm sure you're getting the drift.&lt;/p&gt;
&lt;p&gt;I for one am quite embarrased I didn't think of this before. I've had the knowledge and tools for years. But there you go. We learn something every day. And I love doing it with Umbraco, UCommerce, EntityFramework and apparently now also... NHibernate. :)&lt;/p&gt;
</description>
      <pubDate>Tue, 30 Jan 2018 23:48:27 Z</pubDate>
      <a10:updated>2018-01-30T23:48:27Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1127</guid>
      <link>https://blog.aabech.no/archive/umbracosupport-got-typed-content/</link>
      <category>unit testing</category>
      <category>umbraco</category>
      <title>UmbracoSupport got typed content</title>
      <description>&lt;h2&gt;What's UmbracoSupport?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;UmbracoSupport&lt;/code&gt; is a class I've been introducing to my unit tests over the last year or so.
It allows me to have my own hierarchy for tests, as well as re-using all of Umbraco's own
stubbing code. I've written about it in a post called &lt;a href="/archive/the-basics-of-unit-testing-umbraco-just-got-simpler"&gt;Unit testing Umbraco just got simpler&lt;/a&gt;,
and its gut's code is described in details in &lt;a href="/archive/the-basics-of-unit-testing-umbraco"&gt;The basics of unit testing Umbraco&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;A quick primer on what's already available&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;BaseDatabaseFactoryTest&lt;/code&gt; in &lt;code&gt;Umbraco.Tests&lt;/code&gt; has a method called &lt;code&gt;GetXmlContent&lt;/code&gt;.
It replaces the &lt;code&gt;umbraco.config&lt;/code&gt; file that acts as the cache at runtime.
It makes &lt;code&gt;UmbracoContext.Current.ContentCache&lt;/code&gt; tick in unit tests.
The base tests out of the box has a small flaw though. They can't &amp;quot;popuplate&amp;quot; properties.
All you get is the hierarchy.&lt;/p&gt;
&lt;p&gt;Usually I've injected an &lt;code&gt;IPublishedContentCache&lt;/code&gt; to my controllers. When testing them,
I've created a mock instance of the &lt;code&gt;IPublishedContentCache&lt;/code&gt;. However, all my code has to use
the non-context aware overloads. For instance &lt;code&gt;cache.GetById(umbracoContext, false, id)&lt;/code&gt;.
There's also a whole lot of ugly mocking code going on to set up queries and stubbed content.
How to stub properties on stubbed content is described in &lt;a href="/archive/slides-from-cg16-and-testing-ipublishedcontent-properties/"&gt;Slides from CG 2016 and testing IPublishedContent properties&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;So what's new?&lt;/h2&gt;
&lt;p&gt;As mentioned, I've been throwing around all kinds of ugly stubbing code for content and I've also been tampering with &lt;code&gt;Umbraco.Tests&lt;/code&gt;'s &lt;code&gt;GetXmlContent()&lt;/code&gt; to use the &amp;quot;built-in&amp;quot; content stubs.
It's all been done before in misc. tests in Umbraco. I finally got my s**t together and refactored all my setup spaghetti into a few small helpers on the &lt;code&gt;UmbracoSupport&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;Let's go over them in increasing &amp;quot;integrationness&amp;quot;.&lt;/p&gt;
&lt;h2&gt;Pure hierarchy&lt;/h2&gt;
&lt;p&gt;Your basic hierarchy structure can be set up by simply returning a string from an overload of &lt;code&gt;BaseDatabaseFactoryTest.GetXmlContent&lt;/code&gt;. &lt;code&gt;UmbracoSupport&lt;/code&gt; overloads this method and returns whatever you've set on the &lt;code&gt;UmbracoSupport.ContentCacheXml&lt;/code&gt; property. I recommend using the technique described in &lt;a href="/archive/automating-creation-of-source-data-for-tests"&gt;Automating creating of source data for tests&lt;/a&gt; with this. You can even extend that code to have fixture specific content caches.&lt;/p&gt;
&lt;p&gt;In any case, to make this work, you just need to set the XML in the setup method.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: I've got some probs with the markdown parsing here, imagine the CDATA parts of the XML is correctly written.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[SetUp]
public void Setup()
{
    umbracoSupport = new UmbracoSupport();
    umbracoSupport.SetupUmbraco();

    // This XML is what the ContentCache will represent
    umbracoSupport.ContentCacheXml = @&amp;quot;
        &amp;lt;?xml version=&amp;quot;&amp;quot;1.0&amp;quot;&amp;quot; encoding=&amp;quot;&amp;quot;utf-8&amp;quot;&amp;quot;?&amp;gt;
        &amp;lt;!DOCTYPE root [
          &amp;lt;!ELEMENT contentBase ANY&amp;gt;
          &amp;lt;!ELEMENT home ANY&amp;gt;
          &amp;lt;!ATTLIST home id ID #REQUIRED&amp;gt;
          &amp;lt;!ELEMENT page ANY&amp;gt;
          &amp;lt;!ATTLIST page id ID #REQUIRED&amp;gt;
        ]&amp;gt;
        &amp;lt;root id=&amp;quot;&amp;quot;-1=&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;gt;
          &amp;lt;home id=&amp;quot;&amp;quot;1103=&amp;quot;&amp;quot;&amp;quot;&amp;quot; key=&amp;quot;&amp;quot;156f1933-e327-4dce-b665-110d62720d03=&amp;quot;&amp;quot;&amp;quot;&amp;quot; parentID=&amp;quot;&amp;quot;-1=&amp;quot;&amp;quot;&amp;quot;&amp;quot; level=&amp;quot;&amp;quot;1=&amp;quot;&amp;quot;&amp;quot;&amp;quot; creatorID=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; sortOrder=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; createDate=&amp;quot;&amp;quot;2017-10-17T20:25:12=&amp;quot;&amp;quot;&amp;quot;&amp;quot; updateDate=&amp;quot;&amp;quot;2017-10-17T20:25:17=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeName=&amp;quot;&amp;quot;Home=&amp;quot;&amp;quot;&amp;quot;&amp;quot; urlName=&amp;quot;&amp;quot;home=&amp;quot;&amp;quot;&amp;quot;&amp;quot; path=&amp;quot;&amp;quot;-1,1103=&amp;quot;&amp;quot;&amp;quot;&amp;quot; isDoc=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeType=&amp;quot;&amp;quot;1093=&amp;quot;&amp;quot;&amp;quot;&amp;quot; creatorName=&amp;quot;&amp;quot;Admin=&amp;quot;&amp;quot;&amp;quot;&amp;quot; writerName=&amp;quot;&amp;quot;Admin=&amp;quot;&amp;quot;&amp;quot;&amp;quot; writerID=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; template=&amp;quot;&amp;quot;1064=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeTypeAlias=&amp;quot;&amp;quot;home=&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;gt;
            &amp;lt;title&amp;gt;Welcome!&amp;lt;/title&amp;gt;
            &amp;lt;excerptCount&amp;gt;4&amp;lt;/excerptCount&amp;gt;
            &amp;lt;page id=&amp;quot;&amp;quot;1122=&amp;quot;&amp;quot;&amp;quot;&amp;quot; key=&amp;quot;&amp;quot;1cb33e0a-400a-4938-9547-b05a35739b8b=&amp;quot;&amp;quot;&amp;quot;&amp;quot; parentID=&amp;quot;&amp;quot;1103=&amp;quot;&amp;quot;&amp;quot;&amp;quot; level=&amp;quot;&amp;quot;2=&amp;quot;&amp;quot;&amp;quot;&amp;quot; creatorID=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; sortOrder=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; createDate=&amp;quot;&amp;quot;2017-10-17T20:25:12=&amp;quot;&amp;quot;&amp;quot;&amp;quot; updateDate=&amp;quot;&amp;quot;2017-10-17T20:25:17=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeName=&amp;quot;&amp;quot;Page=&amp;quot;&amp;quot; 1=&amp;quot;&amp;quot;&amp;quot;&amp;quot; urlName=&amp;quot;&amp;quot;page1=&amp;quot;&amp;quot;&amp;quot;&amp;quot; path=&amp;quot;&amp;quot;-1,1103,1122=&amp;quot;&amp;quot;&amp;quot;&amp;quot; isDoc=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeType=&amp;quot;&amp;quot;1095=&amp;quot;&amp;quot;&amp;quot;&amp;quot; creatorName=&amp;quot;&amp;quot;Admin=&amp;quot;&amp;quot;&amp;quot;&amp;quot; writerName=&amp;quot;&amp;quot;Admin=&amp;quot;&amp;quot;&amp;quot;&amp;quot; writerID=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; template=&amp;quot;&amp;quot;1060=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeTypeAlias=&amp;quot;&amp;quot;page=&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;gt;
              &amp;lt;title&amp;gt;Welcome!&amp;lt;/title&amp;gt;
              &amp;lt;excerpt&amp;gt;[CDATA[Lorem ipsum dolor...]]&amp;lt;/excerpt&amp;gt;
              &amp;lt;body&amp;gt;
                [CDATA[&amp;lt;p&amp;gt;Lorem ipsum dolor...&amp;lt;/p&amp;gt;]]
              &amp;lt;/body&amp;gt;
              &amp;lt;image&amp;gt;123&amp;lt;/image&amp;gt;
            &amp;lt;/page&amp;gt;
            &amp;lt;page id=&amp;quot;&amp;quot;1123=&amp;quot;&amp;quot;&amp;quot;&amp;quot; key=&amp;quot;&amp;quot;242928f6-a1cf-4cd3-ac34-f3ddf3526b2e=&amp;quot;&amp;quot;&amp;quot;&amp;quot; parentID=&amp;quot;&amp;quot;1103=&amp;quot;&amp;quot;&amp;quot;&amp;quot; level=&amp;quot;&amp;quot;2=&amp;quot;&amp;quot;&amp;quot;&amp;quot; creatorID=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; sortOrder=&amp;quot;&amp;quot;1=&amp;quot;&amp;quot;&amp;quot;&amp;quot; createDate=&amp;quot;&amp;quot;2017-10-17T20:25:12=&amp;quot;&amp;quot;&amp;quot;&amp;quot; updateDate=&amp;quot;&amp;quot;2017-10-17T20:25:17=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeName=&amp;quot;&amp;quot;Page=&amp;quot;&amp;quot; 2=&amp;quot;&amp;quot;&amp;quot;&amp;quot; urlName=&amp;quot;&amp;quot;page2=&amp;quot;&amp;quot;&amp;quot;&amp;quot; path=&amp;quot;&amp;quot;-1,1103,1123=&amp;quot;&amp;quot;&amp;quot;&amp;quot; isDoc=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeType=&amp;quot;&amp;quot;1095=&amp;quot;&amp;quot;&amp;quot;&amp;quot; creatorName=&amp;quot;&amp;quot;Admin=&amp;quot;&amp;quot;&amp;quot;&amp;quot; writerName=&amp;quot;&amp;quot;Admin=&amp;quot;&amp;quot;&amp;quot;&amp;quot; writerID=&amp;quot;&amp;quot;0=&amp;quot;&amp;quot;&amp;quot;&amp;quot; template=&amp;quot;&amp;quot;1060=&amp;quot;&amp;quot;&amp;quot;&amp;quot; nodeTypeAlias=&amp;quot;&amp;quot;page=&amp;quot;&amp;quot;&amp;quot;&amp;quot;&amp;gt;
              &amp;lt;title&amp;gt;More welcome!&amp;lt;/title&amp;gt;
              &amp;lt;excerpt&amp;gt;[CDATA[More lorem ipsum dolor...]]&amp;lt;/excerpt&amp;gt;
              &amp;lt;body&amp;gt;[CDATA[Even more lorem ipsum dolor...]]&amp;lt;/body&amp;gt;
              &amp;lt;image&amp;gt;234&amp;lt;/image&amp;gt;
            &amp;lt;/page&amp;gt;
          &amp;lt;/home&amp;gt;
        &amp;lt;/root&amp;gt;
    &amp;quot;.Trim();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In our tests, we can now query by anything. The returned content has the hierarchy and everything, so we can traverse it with &lt;code&gt;Children()&lt;/code&gt;, &lt;code&gt;Parent()&lt;/code&gt; and whatnot.
The only missing piece is the properties. Here's a test showing that we have everything but the title property of Page 1:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const int Page1Id = 1122;

[Test]
public void Returns_Empty_Documents()
{
    var contentCache = umbracoSupport.UmbracoContext.ContentCache;
    var page1 = contentCache.GetById(Page1Id);

    Assert.That(page1, Is
        .Not.Null
        .And
        .InstanceOf&amp;lt;PublishedContentWithKeyBase&amp;gt;()
        .And
        .Property(&amp;quot;Name&amp;quot;).EqualTo(&amp;quot;Page 1&amp;quot;)
        .And
        .Matches&amp;lt;IPublishedContent&amp;gt;(c =&amp;gt; c[&amp;quot;title&amp;quot;] == null)
        .And
        .Property(&amp;quot;Parent&amp;quot;)
            .Property(&amp;quot;Children&amp;quot;)
                .With.Count.EqualTo(2)
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don't be discouraged though. This method is excellent for testing URL providers, ContentFinders, Menus, Sitemaps. You name it. I know I've written my fair share of hierarchy traversing code or fancy XPath queries. Unless of course, you need property values.&lt;/p&gt;
&lt;p&gt;Instead of pulling your leg about it, here's how we fix that.&lt;/p&gt;
&lt;h2&gt;Put some meat on the content&lt;/h2&gt;
&lt;p&gt;The reason the properties are not there isn't because they weren't read. It's because the &lt;code&gt;XmlPublishedContent&lt;/code&gt; that we get out ultimately relies on the &lt;code&gt;PublishedContentType&lt;/code&gt; for it's respective document type. Luckily, all Umbraco's services are already stubbed up for us, so we can give it what it needs.&lt;/p&gt;
&lt;p&gt;The gory guts of it is that it needs an &lt;code&gt;IContentType&lt;/code&gt; from the &lt;code&gt;ContentTypeService&lt;/code&gt;. We can easily stub one up with Moq: &lt;code&gt;var contentType = Mock.Of&amp;lt;IContentType&amp;gt;()&lt;/code&gt;. Further, it uses the &lt;code&gt;IContentType.CompositionPropertyTypes&lt;/code&gt; collection to iterate the properties. These &lt;code&gt;PropertyType&lt;/code&gt; instances are actually completely dependency-less, so we can just create some:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Mock.Get(contentType)
    .Setup(t =&amp;gt; t.CompositionPropertyTypes)
    .Returns(new[] {
        new PropertyType(&amp;quot;Umbraco.TinyMCEv3&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;body&amp;quot;)
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, we set it up on the &lt;code&gt;ContentTypeService&lt;/code&gt; stub:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Mock.Get(umbracoSupport.ServiceContext.ContentTypeService)
    .Setup(s =&amp;gt; s.GetContentType(alias))
    .Returns(contentType);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If only it were so easy. We depend on the &lt;code&gt;BaseWebTest&lt;/code&gt; class from &lt;code&gt;Umbraco.Tests&lt;/code&gt;. It sets up a content type factory that's being used somewhere in the hierarchy. It feeds &lt;code&gt;AutoPublishedContent&lt;/code&gt; instances instead of what we've stubbed up. We need to turn that off. There's a trick here. &lt;code&gt;UmbracoSupport&lt;/code&gt; should now live in an assembly called &lt;code&gt;Umbraco.UnitTests.Adapter&lt;/code&gt;. If you're pre 7.6.4 you need to go with &lt;code&gt;Umbraco.VisualStudio&lt;/code&gt;. This is because the factory we need to reset is internal to Umbraco. By having &lt;code&gt;UmbracoSupport&lt;/code&gt; in an assembly with one of these two names, we're able to do it. (Otherwise, you use reflection.) &lt;em&gt;By no means do this with production code. Just... forget it!&lt;/em&gt;&lt;br /&gt;
This paragraph should also get it's own blog post. :)&lt;/p&gt;
&lt;p&gt;But I digress. Here's the line you need to have the content use the &lt;code&gt;ContentTypeService&lt;/code&gt; to fetch its type:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PublishedContentType.GetPublishedContentTypeCallback = null;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It's tempting to leave setup code like this lying around in all our &lt;code&gt;SetUp&lt;/code&gt; methods or even in our &amp;quot;Arrange&amp;quot; sections. I've sinned too much, so those few lines are now part of &lt;code&gt;UmbracoSupport&lt;/code&gt; and can be used to set up multiple types for your fixture or test.&lt;/p&gt;
&lt;p&gt;Here's a test that fetches the same document as before, but can now read properties:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Test]
public void With_DocumentTypes_Setup_Returns_Full_Blown_Documents()
{
    umbracoSupport.SetupContentType(&amp;quot;page&amp;quot;, new[]
    {
        new PropertyType(&amp;quot;textstring&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;title&amp;quot;),
        new PropertyType(&amp;quot;textarea&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;excerpt&amp;quot;),
        new PropertyType(&amp;quot;Umbraco.TinyMCEv3&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;body&amp;quot;),
        new PropertyType(&amp;quot;media&amp;quot;, DataTypeDatabaseType.Integer, &amp;quot;image&amp;quot;)
    });

    var page1 = contentCache.GetById(Page1Id);

    Assert.Multiple(() =&amp;gt;
    {
        Assert.That(page1[&amp;quot;title&amp;quot;], Is.EqualTo(&amp;quot;Welcome!&amp;quot;));
        Assert.That(page1[&amp;quot;excerpt&amp;quot;], Is.EqualTo(&amp;quot;Lorem ipsum dolor...&amp;quot;));
        Assert.That(page1[&amp;quot;body&amp;quot;].ToString(), Is.EqualTo(&amp;quot;&amp;lt;p&amp;gt;Lorem ipsum dolor...&amp;lt;/p&amp;gt;&amp;quot;));
        Assert.That(page1[&amp;quot;image&amp;quot;], Is.EqualTo(123));
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Notice the .ToString() on the body. It's actually not a string, but some weird dynamic Umbraco thingy. I never saw that type before, but I didn't pursue it in time for this post. I don't want anything to do with it though, so let's storm on to the grand finale.&lt;/p&gt;
&lt;h2&gt;Let's make them strong already!&lt;/h2&gt;
&lt;p&gt;We're finally there. The last piece of the puzzle. Strongly typed content!&lt;/p&gt;
&lt;p&gt;It's managed by two resolvers: &lt;code&gt;PublishedContentModelFactoryResolver&lt;/code&gt; and &lt;code&gt;PropertyValueConvertersResolver&lt;/code&gt;. I won't go into details about those now, but suffice to say all resolvers have to be initialized before &lt;code&gt;BaseWebTest.Initialize&lt;/code&gt; and its ancestors.
I've added an &lt;code&gt;InitializeResolvers&lt;/code&gt; method to the &lt;code&gt;UmbracoSupport&lt;/code&gt; class where these two are initialized. The &lt;code&gt;PublishedContentModelFactoryResolver&lt;/code&gt; is set to a &lt;code&gt;FakeModelFactoryResolver&lt;/code&gt; that lets you register constructors for document type aliases. &lt;a href="https://github.com/lars-erik/umbraco-unit-testing-samples/blob/master/Umbraco.UnitTesting.Adapter/Support/FakeTypedModelFactory.cs"&gt;The code for this is available in my &amp;quot;Umbraco unit testing samples&amp;quot; repo on github&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;To set up property value converters, we also need to do that before registering the resolver. The resolver takes all the converters as constructor arguments. I've added a list of those types as a property on &lt;code&gt;UmbracoSupport&lt;/code&gt;, so we can add &lt;code&gt;IPropertyValueConverter&lt;/code&gt; implementing types before calling &lt;code&gt;UmbracoSupport.SetupUmbraco&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[SetUp]
public void Setup()
{
    umbracoSupport = new UmbracoSupport();

    // Converter types need to be added before setup
    umbracoSupport.ConverterTypes.Add(typeof(TinyMceValueConverter));

    umbracoSupport.SetupUmbraco();

    //...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To register the typed model, there's just one line you can do in your setup, or even in your tests. Here I've refactored out the setup for the content type from earlier, and I register a model type for the document type alias:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private void SetupContentType()
{
    umbracoSupport.SetupContentType(&amp;quot;page&amp;quot;, new[]
    {
        new PropertyType(&amp;quot;textstring&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;title&amp;quot;),
        new PropertyType(&amp;quot;textarea&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;excerpt&amp;quot;),
        new PropertyType(&amp;quot;Umbraco.TinyMCEv3&amp;quot;, DataTypeDatabaseType.Nvarchar, &amp;quot;body&amp;quot;),
        new PropertyType(&amp;quot;media&amp;quot;, DataTypeDatabaseType.Integer, &amp;quot;image&amp;quot;)
    });
}

[Test]
public void With_DocumentTypes_And_Models_Setup_Returns_Fully_Functional_Typed_Content()
{
    SetupContentType();

    // Register strongly typed models with the ModelFactory
    umbracoSupport.ModelFactory.Register(&amp;quot;page&amp;quot;, c =&amp;gt; new Page(c));

    var page1 = contentCache.GetById(Page1Id);

    Assert.That(page1, Is
        .InstanceOf&amp;lt;Page&amp;gt;()
        .And.Property(&amp;quot;Body&amp;quot;)
            .Matches&amp;lt;IHtmlString&amp;gt;(s =&amp;gt; 
                s.ToString() == &amp;quot;&amp;lt;p&amp;gt;Lorem ipsum dolor...&amp;lt;/p&amp;gt;&amp;quot;
            )
    );
}

public class Page : PublishedContentModel
{
    public Page(IPublishedContent content) : base((IPublishedContentWithKey)content)
    {
    }

    public string Title =&amp;gt; Content.GetPropertyValue&amp;lt;string&amp;gt;(&amp;quot;title&amp;quot;);
    public string Excerpt =&amp;gt; Content.GetPropertyValue&amp;lt;string&amp;gt;(&amp;quot;excerpt&amp;quot;);
    public IHtmlString Body =&amp;gt; Content.GetPropertyValue&amp;lt;IHtmlString&amp;gt;(&amp;quot;body&amp;quot;);
    public int Image =&amp;gt; Content.GetPropertyValue&amp;lt;int&amp;gt;(&amp;quot;image&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There you go! There's nothing more to it. Well, there is...&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Page&lt;/code&gt; class here is bundled with the test. If we use a common interface both for our runtime model and our test model, we're safe. But we should really use the runtime models. This means you shouldn't use &lt;em&gt;runtime generated&lt;/em&gt; models. &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Install-And-Configure"&gt;Go through the instructions for ModelsBuilder&lt;/a&gt; to have your models compiled and accessible from the tests.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And although the XML is pretty ugly, you can flush it out into files bundled with your tests. You can also exploit the umbraco.config file and just copy segments from there into your test source files. That way, you spend no time writing the stubs, and the content is cleanly separated from your tests.&lt;/p&gt;
&lt;p&gt;That's &lt;em&gt;really&lt;/em&gt; all there is to it! It is. Now go test a bit, or a byte, or a string, or even a &lt;a href="/archive/testing-views-with-razorgenerator/"&gt;view&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/lars-erik/umbraco-unit-testing-samples/tree/master/Umbraco.UnitTesting.Adapter/Support"&gt;The new version of UmbracoSupport including the fake model factory is available here.&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Tue, 17 Oct 2017 21:18:06 Z</pubDate>
      <a10:updated>2017-10-17T21:18:06Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1097</guid>
      <link>https://blog.aabech.no/archive/marrying-ditto-with-modelsbuilder/</link>
      <title>Marrying Ditto with ModelsBuilder</title>
      <description>&lt;p&gt;I was happy to be allowed to speak at this years Umbraco UK Festival.&lt;br /&gt;
The topic was based on my &lt;a href="//blog.aabech.no/archive/comparing-modelsbuilder-and-ditto/"&gt;previous post where I compare Ditto and ModelsBuilder&lt;/a&gt;. 
While preparing for that talk, I couldn't help but notice that the tools and techniques 
aren't mutually exclusive at all. On the contrary, they can compliment each other in a really nice way.&lt;br /&gt;
&lt;em&gt;&lt;a href="#further-info"&gt;Slides and video from presentation linked further down&lt;/a&gt;.&lt;/em&gt;  
&lt;/p&gt;
&lt;p&gt;I won't dive into too many details in this article, I recommend you &lt;a href="//blog.aabech.no/archive/comparing-modelsbuilder-and-ditto/"&gt;read the previous article&lt;/a&gt;,
and take a swim through the code at &lt;a href="https://github.com/lars-erik/DittoDemoModelsBuilderified"&gt;the github repository&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Cleaning up the processors&lt;/h3&gt;
&lt;p&gt;In the Dittoified TXT site Matt Brailsford made, we saw a bunch of processors querying the hierarchy.
In my Modelsbuilderified version, we do nice and clean domain oriented queries.&lt;/p&gt;
&lt;p&gt;Take for instance the top navigation on the site, where we look up all the visible children of the home page.
The Ditto processor looks as such:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class MainNavAttribute : DittoProcessorAttribute
{
    public override object ProcessValue()
    {
        var content = Value as IPublishedContent;
        if (content == null) return Enumerable.Empty&amp;lt;NavLink&amp;gt;();

        var homePage = content.AncestorsOrSelf(1).First();
        return new[] { homePage }.Union(homePage.Children.Where(x =&amp;gt; x.IsVisible()));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With ModelsBuilder, we point to the homepage from the base document type,
and implemented the navigation items query on the homepage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public partial class UmbHomePage
{
    IEnumerable&amp;lt;INavigationContent&amp;gt; INavigation.MenuItems
    {
        get
        {
            return new[] { this }
                .Union(
                    Children
                    .OfType&amp;lt;INavigationContent&amp;gt;()
                    .Where(c =&amp;gt; c.IsVisible)
                );
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What we keep forgetting though, is that the ModelsBuilder models are created before the content leaves the cache.
If we install Ditto in the ModelsBuilderified version, or vice versa, we can actually use that MB query in the processor.
Whether we'd like to keep the query and interface segregation on our ModelsBuilder classes, 
or we'd like to put most logic in the Ditto processors is still a matter of taste.&lt;/p&gt;
&lt;p&gt;However, by just letting MB generate its models in the Dittoified project, not writing one single interface, 
we can refactor the &lt;code&gt;MainNavAttribute&lt;/code&gt; as such:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class MainNavAttribute : DittoProcessorAttribute
{
    public override object ProcessValue()
    {
        var content = Value as IPublishedContent;
        if (content == null) return Enumerable.Empty&amp;lt;NavLink&amp;gt;();

        var homePage = content.AncestorOrSelf&amp;lt;UmbHomePage&amp;gt;();
        return new[] { homePage }.Union(homePage.Children.Where(x =&amp;gt; x.IsVisible()));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The same can be done to the &lt;code&gt;BaseNewsProcessorAttribute&lt;/code&gt; with even more &amp;quot;domain language&amp;quot;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public abstract class BaseNewsAttribute : DittoProcessorAttribute
{
    protected IEnumerable&amp;lt;UmbNewsItem&amp;gt; GetNews()
    {
        var content = Value as UmbMaster;
        if (content == null) return Enumerable.Empty&amp;lt;UmbNewsItem&amp;gt;();

        var newsArchive = content.Home.FirstChild&amp;lt;UmbNewsOverview&amp;gt;();
        if (newsArchive == null) return Enumerable.Empty&amp;lt;UmbNewsItem&amp;gt;();

        return newsArchive.Children&amp;lt;UmbNewsItem&amp;gt;()
            .OrderByDescending(x =&amp;gt; x.DisplayDate);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You'll notice I've added the &lt;code&gt;DisplayDate&lt;/code&gt; implementation to &lt;code&gt;UmbNewsItem&lt;/code&gt; so we don't need to
think about the &lt;code&gt;PublishDate&lt;/code&gt; and &lt;code&gt;CreateDate&lt;/code&gt; properties every time we do ordering.&lt;/p&gt;
&lt;h3&gt;Where to start&lt;/h3&gt;
&lt;p&gt;I'd recommend that if you don't use either tool today, you should really just start using ModelsBuilder.
It will improve your code immensly over using magic strings, level-based queries and all that comes
with the basic IPublishedContent implementation. When you start to see that you want more
separation of concerns and interfaces don't do that for you, look into adding Ditto on top.&lt;/p&gt;
&lt;h3&gt;Serialization&lt;/h3&gt;
&lt;p&gt;The main pain point of using ModelsBuilder today is that &lt;code&gt;IPublishedContent&lt;/code&gt; implementations
lend themselves badly to serialization. Serializing it without care will lead to cyclic references
and/or super big graphs of parents and children.&lt;/p&gt;
&lt;p&gt;By mapping the content to POCOs with Ditto, you don't have to care about this.&lt;/p&gt;
&lt;h3&gt;Strike a balance&lt;/h3&gt;
&lt;p&gt;In my opinion, one can go way too far with the processors in Ditto.
Separation of concerns is good, but not at the cost of having to wade through 10-20 classes for
one coherent piece of functionality.&lt;/p&gt;
&lt;p&gt;The same can be said about ModelsBuilder. Creating too many compositions, adding to many interfaces,
creating too many extensions can be just as overwhelming.&lt;/p&gt;
&lt;p&gt;It basically boils down to the &lt;a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it"&gt;good old YAGNI principle&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Further exploration&lt;/h3&gt;
&lt;p&gt;&lt;a id="further-info"&gt;&lt;/a&gt;
The examples in this article is &lt;a href="https://github.com/lars-erik/DittoDemoModelsBuilderified/tree/can-i-haz-both"&gt;avaiable in a branch on GitHub&lt;/a&gt;.&lt;br /&gt;
I also did a presentation comparing the two tools, and marrying them at last at this years Umbraco UK Festival.&lt;br /&gt;
&lt;a href="https://www.youtube.com/watch?v=dNZG4DOk6Vk"&gt;The presentation can be seen on YouTube&lt;/a&gt;.&lt;br /&gt;
&lt;a href="https://1drv.ms/p/s!AnYHs3nuLdwBjo1k2EJOTJ4IYrOwLA"&gt;The slides from the presentation are available here&lt;/a&gt;.&lt;/p&gt;
</description>
      <pubDate>Sat, 05 Nov 2016 17:00:29 Z</pubDate>
      <a10:updated>2016-11-05T17:00:29Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1068</guid>
      <link>https://blog.aabech.no/archive/getting-real-business-value-from-strongly-typed-models-in-umbraco/</link>
      <title>Getting real business value from strongly typed models in Umbraco</title>
      <description>&lt;h3&gt;Unmasking &amp;quot;Code First&amp;quot;&lt;/h3&gt;
&lt;p&gt;There was a &lt;a href="https://twitter.com/peteduncanson/status/724875855579742208"&gt;thread on twitter the other day&lt;/a&gt; where someone had asked
someone about &amp;quot;Code First&amp;quot; in Umbraco. &amp;quot;Code First&amp;quot; has been something like a holy grail for many developers, including me. The thread ended with a conclusion that nobody wants it.
But that discussion reminded me of something. how my own attempts at &lt;a href="https://en.wikipedia.org/wiki/Round-trip_engineering"&gt;&amp;quot;round-trip engineering&amp;quot;&lt;/a&gt;
document types in Umbraco just faded. I even made a &lt;a href="https://github.com/lars-erik/Umbraco.CodeGen"&gt;tool that does it&lt;/a&gt;,
but neither did it get many users, nor did I actually use it for &amp;quot;Code First&amp;quot; myself. What I used my tool for was generating
strongly typed models for Umbraco, and all the benefits it brings.  
&lt;/p&gt;
&lt;p&gt;With Umbraco 7.4, &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder"&gt;Umbraco ModelsBuilder&lt;/a&gt; is now built-in to Umbraco.
It does what my tool does, and is now available to all Umbraco developers with the &lt;a href="https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Install-And-Configure"&gt;flip of an appSetting&lt;/a&gt;. 
If you'd like to tag along with this article, you should make sure it's set to &lt;code&gt;PureLive&lt;/code&gt; mode.&lt;/p&gt;
&lt;p&gt;So what does generated strongly typed models enable us developers (and designers) to do? Ignoring the elevator answer &amp;quot;IntelliSense and compiler errors when we make a typo&amp;quot;. 
Why would you use this, unless you're one of those guys who come back from conventions full of &amp;quot;good ideas&amp;quot;? 
Turns out it opens up a plethora of useful techniques to use and squeeze for value. Business value!  
&lt;/p&gt;
&lt;p&gt;Not only that! By leveraging compositional document types, you actually may do a kind of &amp;quot;Code First&amp;quot;.&lt;br /&gt;
There's only thing associated with &amp;quot;Code First&amp;quot; that you won't get. It is something that updates the document models in Umbraco, based on your code. &lt;/p&gt;
&lt;p&gt;But why would you want that? There's an excellent UI that lets you annotate and describe all the fields for the editors. You also get to preview the editor experience. And you get to configure stuff using well crafted tools.&lt;/p&gt;
&lt;p&gt;Coding your document types would mean messing around with loads of ugly metadata attributes.
In the end your business artifacts would drown in irrelevant data.
Not to mention you'd have to remember all the bloody editor aliases and types and everything.&lt;/p&gt;
&lt;h3&gt;Real value, with a sprinkle of code first on top&lt;/h3&gt;
&lt;p&gt;So how do we use these techniques, and how do we get &lt;em&gt;value&lt;/em&gt; from them?&lt;/p&gt;
&lt;p&gt;Some of you are probably familiar with the &lt;a href="https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)"&gt;SOLID&lt;/a&gt; programming principles. Leveraging the I and the D is what gets things going with typed models. The I stands for &amp;quot;Interface Segregation&amp;quot; and the D stands for &amp;quot;Dependency Inversion&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Dependency Inversion principle&lt;/strong&gt; states that you should &lt;em&gt;depend on abstractions, not on concretions&lt;/em&gt;.
In the &amp;quot;typed model world&amp;quot; it means that you don't use instances of the generated type Article. You code against an interface IArticle said class implements. You can also one of the compositions the document type is built from.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Interface Segregation principle&lt;/strong&gt; states that you should &lt;em&gt;make fine grained interfaces that are client specific&lt;/em&gt;.
Again, in a &amp;quot;typed model world&amp;quot; this can be applied as &amp;quot;compose your document types of several types, each relevant for a specific use in the site&amp;quot;.&lt;/p&gt;
&lt;p&gt;Let's have a look at how we can extract value from these patterns. We'll try to apply it to a simple feature most of us have in all our sites.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Prototyping&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;With all sites, I'm sure we promote some content in a more or less generic way. While prototyping and wireframing we sketch it. We use static HTML, PowerPoint or some other tool.&lt;/p&gt;
&lt;p&gt;What if we could already prepare a Razor file that would still work when the site is live? Before we even set up the Umbraco site. With or without Umbraco, you can quickly create what you need to get started. Just to really prove the point that we're prototyping here, let's just start with a view:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ~/Views/Partials/Promotion.cshtml
&amp;lt;div class=&amp;quot;promotion&amp;quot;&amp;gt;
    &amp;lt;a href=&amp;quot;/promoted-content&amp;quot;&amp;gt;
        &amp;lt;img src=&amp;quot;/media/1001/fancy-picture.jpg&amp;quot; /&amp;gt;
        &amp;lt;h2&amp;gt;Lorem Ipsum&amp;lt;/h2&amp;gt;
        &amp;lt;p&amp;gt;More lorem ipsum with sugar on top.&amp;lt;/p&amp;gt;
    &amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So that's more or less what we've imagined we're gonna use for promotions for now.
Maybe we'll add a &lt;code&gt;col-md-x&lt;/code&gt; later, but for now, the HTML is good.
Of course it can't stay like that. We need to show some Umbraco data.
So we need a model to bind to. It could be an IPublishedContent, or it could be a dynamic object like before.
However, the markup would prabably be ugly, and either way you'd need to remember all the aliases.
I'll just remind you before we continue:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h2&amp;gt;@(Model.Content.GetPropertyValue&amp;lt;IHtmlString&amp;gt;(&amp;quot;summray&amp;quot;))&amp;lt;/h2&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We need something to help us out. So we create an interface:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ~/Models/IPromotable.cs
namespace YourWeb.Models
{
    public interface IPromotable
    {
        string Title { get; }
        object Image { get; }
        IHtmlString Summary { get; }
        string Url { get; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we can revisit the view and use some @ markup without getting complaints from our IDE.
If you type this, you'll even get help along the way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ~/Views/Partials/Promotion.cshtml
@model YourWeb.Models.IPromotable
&amp;lt;div class=&amp;quot;promotion&amp;quot;&amp;gt;
    &amp;lt;a href=&amp;quot;@Model.Url&amp;quot;&amp;gt;
        &amp;lt;img src=&amp;quot;@Model.Image&amp;quot; /&amp;gt;
        &amp;lt;h2&amp;gt;@Model.Title&amp;lt;/h2&amp;gt;
        &amp;lt;p&amp;gt;@Model.Summary&amp;lt;/p&amp;gt;
    &amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now it's actually in a form where it doesn't have to change at all until the requirements actually change.&lt;br /&gt;
But we haven't viewed it yet. Let's do that too without bringing Umbraco into the picture.&lt;br /&gt;
We'll create a simple controller:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ~/Controllers/PrototypingController.cs
public class PrototypeController : Controller
{
    public ActionResult Promotion()
    {
        return View(
            &amp;quot;~/Views/Partials/Promotion.cshtml&amp;quot;,
            new Promotable
            {
                Title = &amp;quot;Here's a fake promotable&amp;quot;,
                Image = &amp;quot;/media/1001/fancy.jpg&amp;quot;,
                Summary = new HtmlString(&amp;quot;&amp;lt;p&amp;gt;Fancy markup&amp;lt;/p&amp;gt;&amp;quot;),
                Url = &amp;quot;/fancy-url&amp;quot;
            }
        );
    }

    class Promotable : IPromotable
    {
        public string Title { get; set; }
        public object Image { get; set; }
        public IHtmlString Summary { get; set; }
        public string Url { get; set; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I'll let the simplicity of the code speak for itself.&lt;/p&gt;
&lt;p&gt;To actually get to run and view this, we just need one more step.&lt;br /&gt;
Depending on whether you've installed Umbraco, used an MVC template or have a blank project, we need to get the route configured.
I say we bring Umbraco into the picture now. We can still prototype peacefully alongside it.&lt;br /&gt;
Above or below the &lt;code&gt;PrototypeController&lt;/code&gt;, just add a simple &lt;code&gt;ApplicationEventHandler&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class PrototypeRouting : ApplicationEventHandler
{
    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        RouteTable.Routes.MapRoute(&amp;quot;prototyping&amp;quot;, &amp;quot;prototype/{action}&amp;quot;, new { controller = &amp;quot;Prototype&amp;quot; });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now build, and navigate to:&lt;br /&gt;
http://localhost:nnnn/prototype/promotion&lt;/p&gt;
&lt;p&gt;You should see something like:  
&lt;/p&gt;
&lt;div class="promotion" style="border: 1px solid black; padding: 10px;"&gt;
    &lt;a href="/fancy-url"&gt;
        &lt;img src="https://blog.aabech.no/media/1001/umbarcelonajpeg.jpg" /&gt;
        &lt;h2&gt;Here&amp;#39;s a fake promotable&lt;/h2&gt;
        &lt;p&gt;Fancy markup&lt;/p&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;So we've got a live Razor view with a server-side model.
This is a simple sample, but imagine modifying or adding to the model.
Imagine using logic in your view (or controller) to test different behavior.&lt;/p&gt;
&lt;p&gt;Now let's boot up Umbraco and add some real content.
We'll create a re-usable composition type called Promotion to match our partial.  
&lt;/p&gt;
&lt;table&gt;
    &lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Property Editor&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Title&lt;/td&gt;&lt;td&gt;Textstring&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Image&lt;/td&gt;&lt;td&gt;Image picker&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Summary&lt;/td&gt;&lt;td&gt;Rich text editor&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Then we'll create a promotable Article type to use as our first real content type.
Make it usable on root for our current purposes. Add Promotable as a composition.&lt;/p&gt;
&lt;table&gt;
    &lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Property Editor&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Body&lt;/td&gt;&lt;td&gt;Rich text editor&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Go ahead and create one article while you're at it. It should get the URL &amp;quot;/&amp;quot;.&lt;/p&gt;
&lt;p&gt;Now if you go back to your project and have a look in the ~/App_Data/Models folder,
you'll see that there's a few generated files there.&lt;br /&gt;
You've got &lt;code&gt;all.generated.cs&lt;/code&gt;, &lt;code&gt;models.generated.cs&lt;/code&gt; and &lt;code&gt;models.hash&lt;/code&gt;.
Go ahead and open the &lt;code&gt;models.generated.cs&lt;/code&gt; file.
This code is actually being compiled at runtime and loaded into your application.
Now look closer at the (hopefully) top type. It's a partial interface called &lt;code&gt;IPromotable&lt;/code&gt;.
Does it look familiar?&lt;/p&gt;
&lt;p&gt;Add a file to the ~/App_Data/Models folder:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace Umbraco.Web.PublishedContentModels
{
    public partial interface IPromotable : YourWeb.Models.IPromotable
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now go over to the &lt;code&gt;Article.cshtml&lt;/code&gt; template Umbraco generated for you in the &lt;code&gt;~/Views&lt;/code&gt; folder.
Add a line to it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@inherits UmbracoTemplatePage&amp;lt;ContentModels.Article&amp;gt;
@using ContentModels = Umbraco.Web.PublishedContentModels;
@{
    Layout = null;
}
@Html.Partial(&amp;quot;Promotion&amp;quot;, Model.Content) // &amp;lt; this one
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Don't even care to build. Navigate to http://localhost:nnnn.&lt;/p&gt;
&lt;p&gt;You should see something similar to this:&lt;/p&gt;
&lt;div class="promotion" style="border:1px solid black; padding: 10px;"&gt;
    &lt;a href="/"&gt;
        &lt;img src="https://blog.aabech.no/media/1001/umbarcelonajpeg.jpg" /&gt;
        &lt;h2&gt;Here&amp;#39;s a real promotable&lt;/h2&gt;
        &lt;p&gt;&lt;p&gt;Here's some real markup.&lt;/p&gt;&lt;/p&gt;
    &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;Seem familiar? It's our prototype view! Unchanged! And it's working with real Umbraco content!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(
    If you've gotten this far you're probably swearing at me for putting an integer in the image source attribute.
    To the best of my knowledge, there's a lack of good built-in property value converters for images.
    I'll leave it up to you as an excercise to figure out how to expose a URL.
)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We showed the promotion on the content itself now, but in the real world, we'd probably be using it
from the front-page or some area node in our web. Well, there's not much to that.
If you'd like to show anything that has the composition Promotable now, you'll just query for it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Html.Partial(&amp;quot;promotion&amp;quot;, Umbraco.TypedContent(Model.Content.PromotedId))
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You might have to check for the type, though, but let's not think about that yet.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Re-using our logic&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;So how about keeping this HTML snippet and promotional logic around for the next web that needs promoted content?&lt;br /&gt;
We'll need to move the code out of the site itself. (I'll assume you're using Visual Studio from now)&lt;br /&gt;
For now, create a new Class Library project in your solution. Name it something nice, personal and re-usable.&lt;br /&gt;
You'll also have to add a reference to System.Web.Mvc.&lt;br /&gt;
Move the IPromotable interface over to that project and adjust its namespace.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace YourReusableLibrary
{
    public interface IPromotable
    {
        string Title { get; }
        object Image { get; }
        IHtmlString Summary { get; }
        string Url { get; }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's also be so naive to believe we'll never change the markup of a promotion.&lt;br /&gt;
Create another class in the library called &lt;code&gt;PromotableExtensions&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public static class PromotableExtensions
{
    public static IHtmlString Promotion(this IPromotable promotable)
    {
        return String.Format(@&amp;quot;
            &amp;lt;div class=&amp;quot;&amp;quot;promotion&amp;quot;&amp;quot;&amp;gt;
                &amp;lt;a href=&amp;quot;&amp;quot;{0}&amp;quot;&amp;quot;&amp;gt;
                    &amp;lt;img src=&amp;quot;&amp;quot;{4}&amp;quot;&amp;quot; /&amp;gt;
                    &amp;lt;h2&amp;gt;{2}&amp;lt;/h2&amp;gt;
                    &amp;lt;p&amp;gt;{3}&amp;lt;/p&amp;gt;
                &amp;lt;/a&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;quot;,
            promotable.Url,
            promotable.Image,
            promotable.Title,
            promotable.Summary
            );
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Let's go back to our partial again. It can now be modified as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@model YourWeb.Models.IPromotable
@using YourReusableLibrary
@this.Promotion()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That's it! I'd say we'll just scrap it and revisit the article view:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@inherits UmbracoTemplatePage&amp;lt;ContentModels.Article&amp;gt;
@using ContentModels = Umbraco.Web.PublishedContentModels;
@using YourReusableLibrary
@{
    Layout = null;
}
@this.Promotion()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What? Right! We need to do it from our grid-editor view, property editor or whatever:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@using YourReusableLibrary
@(((IPromotable)Umbraco.TypedContent(Model.Content.PromotedItemId)).Promotion())
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bah, it's to verbose. Back to &lt;code&gt;PromotableExtensions&lt;/code&gt; and add:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public static IHtmlString Pomotion(IPublishedContent candidate)
{
    var promotable = candidate as IPromotable;
    if (promotable != null)
        return promotable.Promotion();
    return new HtmlString(&amp;quot;&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And our view:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@using YourReusableLibrary
@Umbraco.TypedContent(Model.Content.ProbablyAPromotedItemId).Promotion()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we have an extension that assumes we have a composition called Promotable.
It assumes said promotable has a title, an image and a summary. 
If we call &lt;code&gt;.Promotion()&lt;/code&gt; on any content, it'll return a nice promotion snippet if it's promotable, or blank if not.
All we have to do is add the tiny partial in &lt;code&gt;~/App_Data/Models&lt;/code&gt;.
We can re-use our logic in any site.&lt;/p&gt;
&lt;p&gt;We made the whole thing in a &amp;quot;code-first&amp;quot; sense, and we never have to create a promotional HTML snippet again.&lt;/p&gt;
&lt;p&gt;Now that's what I call value for coding!&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Applying to &amp;quot;real business logic&amp;quot;&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The example in this article is dead simple. You won't save hours with it.&lt;br /&gt;
However, the principles it demonstrates can be applied to almost any use-case.&lt;br /&gt;
Coupled with property value converters and well thought through compositional models,
you create rich code that clearly states it's purpose. As well as code that is re-usable and simple.  
&lt;/p&gt;
&lt;p&gt;A final point that we haven't touched upon, but is at least as valuable, is unit testing.&lt;br /&gt;
All the code we've written for promotional content is completely testable. It has no dependencies,
except MVC for the IHtmlString, but that's also a solvable issue using the exact same principles.&lt;/p&gt;
&lt;p&gt;With that, happy modeling, and happy &amp;quot;code-firsting&amp;quot;. :)&lt;/p&gt;
</description>
      <pubDate>Sun, 08 May 2016 19:02:56 Z</pubDate>
      <a10:updated>2016-05-08T19:02:56Z</a10:updated>
    </item>
  </channel>
</rss>