Monday 2 December 2013

Sitecore Parameters Template Field

As we move into using the DMS more and more often we are also starting to use the page editor more and more often. This leads to a need for making the way we insert sub-layouts/renderings easier for our users and it turns out Sitecore has made a start on this already by giving us small features that can make a big difference, in this case the "Parameters Template" field.

When you add a presentation component to a page in Sitecore you have the option of editing its component properties and this it what it looks like by default:



And if you wanted to customise the data being passed to this instance of the sub-layout(beyond the data source) you would need to add additional properties as key value pairs to the "Parameters" section. In my mind this is fraught with danger, it is free text and there is no guarantees around the names or types of values being passed to your control.
This is where the "Parameters Template" field comes into play. If you take a look at any of your sub-layout or renderings items you will notice there is a field called "Parameters Template"
By setting this field you are giving Sitecore a prompt on how to ask for the values when editing the "Component Properties" and allows you to name and type the values. 

All you need to do is create a template that inherits from the "Standard Rendering Parameters" template: create the fields you want and set the "Parameters Template" field to point to it.


And "Hey Presto!!", when you edit the component properties of the sub-layout you get the fields, named and typed. Therefore removing the possibility of typos and making the editing process that much nicer.


Now I should probably mention that this doesn't change anything form a code point of view in as much as these values all still come in via the parameters collection that you have without this field, its just making the editing process nicer.

Wednesday 23 October 2013

Powershell File Watcher

Ok so today I had a situation where I needed a simple script to copy some website related artifacts to an output directory that would allow me to view the changes on a website. Now during this process I was making a lot of changes over time and wanted to automate the process.

PowerShell to the rescue.

The script below is fairly simple(and a little unrefined), but it does the job nicely. The script will continue to run until you press a key, at which point it will de-register all of its events and exit

The configurable parts are:

  • You can set the folder to watch with the $inputFolder variable
  • You can set the folder to copy changes to with the $outputFolder variable
  • You can set the extensions of the files that you want to copy with the $filters variable

$inputFolder = Resolve-Path '..\inputDirectory'
$outputFolder = Resolve-Path '..\outputDirectory'
$filters = @('*.css', '*.js', '*.html') 

$messageData = "$inputFolder|$outputFolder"


function RegisterWatcher($fileFilter)
{
    $fsw = New-Object IO.FileSystemWatcher $inputFolder, $fileFilter -Property @{IncludeSubdirectories = $true;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 
     
    Register-ObjectEvent $fsw Changed -SourceIdentifier "FileChanged - $fileFilter" -MessageData $messageData -Action { 
        $sourceItem = $Event.SourceEventArgs.FullPath 
        $targetItem = $sourceItem.Replace($Event.MessageData.Split('|')[0], $Event.MessageData.Split('|')[1])

        Copy-Item $sourceItem $targetItem

        Write-Host "Copied $sourceItem"
    } 
}
 
foreach($filter in $filters)
{   
    RegisterWatcher $filter
}

Write-Host "Press any key to exit"

while ($true) {
    if ($Host.UI.RawUI.KeyAvailable) {
        break;
    }
    Start-Sleep -m 1000
}

foreach($filter in $filters)
{
    Unregister-Event "FileChanged - $filter"
}

Thursday 10 October 2013

Webforms MVP and Sitecore 7 POCO/Content Search

Lately I have been doing some work with Sitecore 7 and I had a requirement to work with the webforms rendering engine(as opposed to the MVC rendering engine), while doing this implementation I came across a nice pattern, it turns out Webforms MVP and Sitecore POCO/Content Search play really well together.

Before I get into the details, let me explain what both of these tools are:

  • Webforms MVP is a in implementation of the Model View Presenter pattern that has been floating around the ASP .NET webforms world for a while now. It promotes the separation of rendering and logic concerns in a similar way to MVC. The project website is http://webformsmvp.com/ and there is a bunch more information there.
  • Sitecore POCO/Content Search is the new search API that has come out as part of Sitecore 7. The easiest way of thinking about it, and one if its most useful features, is LINQ to Lucene. This results in a nice strongly typed LINQ/IQueryable syntax for interacting with Lucene indexes, allowing you to bypass the Sitecore databases for a lot of queries, resulting in a faster site.
Now for the bit where these patterns work well together. 

Webforms MVP has been used by a lot of people in Sitecore development for a while, but has traditionally had one major floor in the resulting implementation - a lack of page editor support. With the MVP approach requiring the creation of a "model" class, a lot of developers pass this model up to the rendering layer and render the values using traditional asp .net controls (e.g. asp:literals, asp:hyperlink etc.), as opposed to using Sitecore controls(e.g sc:text, sc:image etc.). While this wasn't explicitly necessary it kind of happened by default, especially if you wanted to use test driven development on your repository/logic layers. 

But, things have changed. Sitecore 7 and its content search API is based around model classes, and facilitates test driven development in a way Sitecore 6 never did.

So if we are now working with model classes how do we use the page editor? Well Sitecore thought of this as they were developing their new API and introduced a class with a particular method: SearchResultItem.GetItem(). This method allows your to retrieve the Item relating to a model as long as it is based on SearchResultItem.

With all of this wired up we have a nice middle ground with somewhat testable code, a nice user experience and a nice separation of concerns.

A sample Model:
    public class SampleModel : SearchResultItem
    {
        public string NonEditableField { get; set; }
    }

A sample presenter with Content Search Query:
    public class SamplePresenter : Presenter<IView<SampleModel>>
    {
        public SamplePresenter(IView<SampleModel> view)
            : base(view)
        {
            this.View.Load += this.Load;
        }
        private void Load(object sender, EventArgs e)
        {
            var item = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_web_index")
                .CreateSearchContext()
                .GetQueryable<SampleModel>()
                .FirstOrDefault(model => model.NonEditableField == "something");
            this.View.Model = item;
        }
    }

A sample view:
<%@ Control Language="C#"
    AutoEventWireup="true"
    CodeBehind="SampleView.ascx.cs"
    Inherits="Layouts.SampleView" %>
<asp:Literal runat="server" ID="nonEditableField"></asp:Literal>
<sc:Text runat="server" ID="editableField"/>

And its sample code behind:
[PresenterBinding(typeof(SamplePresenter))]
    public partial class SampleView : MvpUserControl<SampleModel>
    {
        protected override void OnPreRender(EventArgs e)
        {
            this.nonEditableField.Text = this.Model.NonEditableField;
            this.editableField.Field = "Editable Field";
            this.editableField.Item = this.Model.GetItem();
        }
    }

Tuesday 9 July 2013

Sitecore 7 patch:source

One of my favourite new features in Sitecore 7 is actually a fairly small, seemingly insignificant one. If you browser the config viewer(/sitecore/admin/showconfig.aspx) in Sitecore it will now show you which config patch settings are applied from.

<sitecore>
 <events timingLevel="custom">
  <event name="item:deleted">
   <handler patch:source="Sitecore.Analytics.config"/>
  </event>
 </events>
</sitecore>


Now if you have ever worked on a project with a lot of config patch includes related to various modules, this can be extremely useful.

Friday 31 May 2013

Automation is Your Friend

Whats the biggest source of bugs/issues in developing/deploying applications? People.

My high-school computer studies teacher once said "Computers don't make mistakes, people do" and this is incredibly accurate. How many times have you heard of:

  • a build getting rejected in UAT because a developer didn't manually test all paths through the application related to their change
  • an issue slipping through regression testing and goes to production, because there were too many manual tests cases to run for every deployment
  • an issue occurring on a website because a file was missed as part of a manual deployment
I think you get the idea, doing repetitive tasks manually is both time consuming and prone to human error. I'm not saying that automating things will solve all of your problems, but it can certainly solve some.

Because automation can provide so many benefits, but can be a bit daunting to start out I have decided to collate a bunch of resources to help point you in the right direction, I will also keep updating this article over time.


Creating a Site in IIS Using PowerShell

So I have been doing a lot of work around build automation and continuous deployment lately and I thought I would do a quick post about setting up new website and application pool in IIS. I use this quite a bit in my daily work life, I use for creating development environments, test environments even remote production environments.

So firstly lets look at creating a new site and application pool:

 #Import the IIS Web Administration module
 Import-Module WebAdministration
 function AddSite($hostname, $siteRoot){
  #Check if the application pool already exists
  if (!(Test-Path "iis:\AppPools\$hostname")) {
   New-Item "iis:\AppPools\$hostname"
  }

  $NewPool = Get-Item "iis:\AppPools\$hostname"
  
  #Set the application pool's account to NETWORK SERVICE
  $NewPool.ProcessModel.IdentityType = 2
  $NewPool | Set-Item

  #Set the application pool to .NET 4
  Set-ItemProperty "IIS:\AppPools\$hostname" managedRuntimeVersion v4.0

  #Check the site exists
  if (!(Test-Path "iis:\Sites\$hostname")) {
         #Create the site and bind it to the hostname, port and folder on disk
         New-Item "iis:\Sites\$hostname" -bindings @{protocol="http";bindingInformation=":80:$hostname"} -physicalPath "$siteRoot"
  }

     #Set the site's application ppol<
     Set-ItemProperty "iis:\Sites\$hostname" -name applicationPool -value $hostname
 }

And secondly lets look at removing the site and application pool:

function RemoveSite($hostname){
    if (Test-Path "iis:\Sites\$hostname") {
        #Remove the site
        Remove-Item "iis:\Sites\$hostname" -recurse
    }

    if (Test-Path "iis:\AppPools\$hostname") {
        #Remove the application pool
        Remove-Item "iis:\AppPools\$hostname" -recurse
    }
}


Wednesday 8 May 2013

Sitecore 7 : Shooting for the Sky 100% Unit Test Coverage with Sitecore 7 & MVC

A little while ago I was asked by the company I work for (Next Digital) to write a post for the corporate blog. I decided that given I had just received early access to Sitecore 7 and that I have a thing for test driven development, that I would try and test drive an implementation in Sitecore 7 and see what sort of coverage I could get with the new features.

Below is the introduction for the post, to see the full article go here.

So I’m one of the lucky MVP’s who get early access to Sitecore 7 and I decided that for my proof of concept I would try to  completely test drive my implementation and see if I couldn't get to 100% unit test coverage.

Now some of you are going to be interested in the MVC side of things and that is great, just start reading. For those of you that are only interested in the Sitecore 7 stuff, jump straight to the Repository Layer of this post.

Again here is the link to the full post http://www.nextdigital.com/voice/shooting-for-the-sky

Wednesday 3 April 2013

Automated Publishing in Sitecore

In the time I have been working with Sitecore I have noticed that a lot of content editors are using the "Publish" button in the U.I. to publish their work, when there is a much easier way of running the publishing process.

In my mind the ideal process is that anything that is ready to be published (either in the final state of a workflow or not in a workflow) should be published automatically without the user having to do anything.

The majority of the time that I have seen this concept implemented is through the use of a workflow action, which works but it means:
  • That for each workflow you have in your site you need to associate the "publish action"
  • Out of the box your related media assets will not be published (unless you use the publishing spider module or a similar concept)
There is a simpler way. In the Sitecore configuration section of your application there is a scheduler, this scheduler can run publish jobs for you. Take a look at the configuration snippet below:


<!-- SCHEDULING -->
<scheduling>
  <!-- Time between checking for scheduled tasks waiting to execute -->
  <frequency>00:00:30</frequency>
  <!-- Agent to publish database periodically -->
  <agent type="Sitecore.Tasks.PublishAgent" method="Run" interval="00:02:00">
   <param desc="source database">master</param>
   <param desc="target database">web</param>
   <param desc="mode (full or smart or incremental)">
     incremental
   </param>
   <param desc="languages">en, da</param>
  </agent>
</scheduling>
This piece of configuration (no code required) will look for new scheduled jobs every 30 seconds. It will then run an incremental publish of the English and Danish languages from master to web every 2 minutes. 

What this means for your users is that they will never need to click "publish" ever again, they will never need to worry about whether or not an image gets published or not and as a developer you get fine grained control over when and what type of publishes occur.

Tuesday 19 March 2013

Does my Sitecore Item Have a Version in a Specific Language

So, this post is pretty heavily related to my last one "How to get Language Specific Links from Sitecore" and comes from the fact that even if you haven't created a version of your item in a specific language it will act as though it does. The quick snippet for this one is:
if (item.Versions.GetLatestVersion(language).Versions.Count >0)
{
     // you have a version
}
else
{
     // you don't
}
The thing to note here is that "GetLatestVersion" will return you an item, even if it doesn't have a version in the specified language, but the count of versions on that item will be 0.

How to get Language Specific Links from Sitecore

By default Sitecore's Link Manager class will return you a link in the context language, this is great when you have a single language site. If you have a multi-lingual site however, this can be quite annoying, especially if you want to do a "this page is also available in X language". So here is the snippet for doing it, the key part being urlOptions.Language.

public class SomeClass
{
  public void SomeMethod()
  {
    var urlOptions = UrlOptions.DefaultOptions;
    urlOptions.Language = language;
    var link = LinkManager.GetItemUrl(item, urlOptions);
  }
}

How to disable "Add Users" in Sitecore's Platform DXP

 I have seen a few posts going around the community asking how to disable the "Add Users" button in Sitecore Platform DXP.   This ...