Disclaimer

The views expressed on this weblog are mine alone and do not necessarily reflect the views of my employer, Avanade.

Search
Recomends...
  • Code Complete, Second Edition
    Code Complete, Second Edition
    by Steve McConnell
Login

Code Snippets makes developers more productive

I created this tool to make reusing common functions, queries or other pieces of code easy as pie.
Thursday
Aug212014

Sitecore Development in the Real World - Page Template Development Process

I've noticed that new Sitecore developers often struggle at first to get productive. Between learning Sitecore, supporting tools and project specifics, it can be a bit overwhelming if you haven't done it before. If only there was a step by step guide that laid straight the path of what needed to be done. 

This post will serve to make it easier by laying out the steps needed to build out page templates. I recommend incorporating Team development for Sitecore and Glass Mapper as an ORM, though all steps could be completed without them. It does assume your following an organization structure similar to what I laid out in my "Sitecore Organizational Strategies" post.

A process to follow

Once you've organized your project and are ready to begin creating page templates, here are the steps:

 

 

Create Data Templates

You can't create anything without a data template. Getting to this point, you should have a good idea of what elements are on the page. Before you move forward creating fields, I do recommend ensuring the design of your template is optimal. This amounts to evaluating your templates along 3 considerations:

Field Types - Are you using the right field types?

I think we too often don't give this enough thought. For example, how do you normally choose between multilist, tree list and treelist ex? I love the simplicity of the multi list, but it can be difficult for content authors to know what they're choosing if the titles of items aren't clear. Treelists help by providing the folder structure to give authors context on what is being chosen, but configuring its data source is more complex. Treelist ex are just like treelists but more performant in the content editor as they'll only fetch records on demand.

Data Template Quick Tips

  • Don't create separate fields for link text and link url. The general link field has a text property which should be used and works correctly with the field renderer.
  • Set Rich Text fields data source to one of the HTML editor profiles.
  • Set the data source for File and Image fields to the path to a folder in the media library
  • Use the Xpath Query builder developer tool to test out multi list data source queries
  • Give developer friendly names to fields and Content Author friendly names to fields by specifying field titles.
  • Reorder groups and fields using the field sorting buttons on the builder options tab

 

Inheritance - Are you repeating yourself across templates?

The DRY principle applies to Sitecore development as well. If you think of each template as mapping to a class, getting the inheritance model correct is an essential task. Page templates should inherit from a base template which should include fields like meta tags and other common fields that span pages. At a page level, you need to really consider whether you can think of areas of your page really should be reusable components that could be applied to other pages. For example, say your template had a section for related content that showed 3 related articles to your content. This is the type of feature that I could imagine applying to multiple templates. To implement it I would create a separate template called "Related Articles" with a single mutlilist field. Then I would make my page template inherit from it. Remember when you take this approach, to set each group's Sortorder (show standard fields, in the appearance group) to ensure it gets positioned below the templates build tab defined fields.

Reuse - Are you making your templates as flexible as they need to be?

You should also consider your template from a content reuse perspective. Are you including things in your template that would be better off being linked to and stored in the data folder instead of the content tree? For example, say your page template had a section to display details about a coupon. You could include all the coupon details (image, link, text as needed) directly in the page template. But that would mean every page would require content authors to fill in all the details on every page they create. Sure you can set defaults in standard values, but it still becomes difficult to maintain if the coupon details change. A better solution might be to create a coupon template and a library for common coupons as a subfolder of the data folder in the content tree and use a drop link field to reference which coupon should be associated with your page. This makes it easier to ensure all pages use the same set of coupons and makes it trivial to update the coupons when they change.

 

Map Templates to Classes

Once you've created your data templates, the next step is to create Model classes which can be used to access data template values from your renderings and sublayouts. You may be tempted to bypass this step and just leverage the Sitecore API directly, but this in general leads to more difficult to maintain code. While you can roll your own model classes from scratch, here is where ORM frameworks like Glass Mapper really shine. They make it easy to represent your data templates as .Net classes and provide a framework for automatically mapping Sitecore Items to their corresponding classes.

If you use Team Development for Sitecore (TDS) you can even configure code generation templates to automatically generate glass Model classes for your data templates every time you sync with Sitecore. Leveraging this approach makes this step take next to no effort. After you create your data templates, sync your TDS project with Sitecore and your Model classes automatically get updated to include any changes you made in Sitecore.

One final tip on code generation. You still may find it would be useful to add additional properties or methods to Model classes. As generated classes get overwritten every time they are regenerated, the best approach for this is to leverage partial classes in .Net. Simply create another file with the partial class declaration and add field and methods as needed.

Create Renderings or Sublayouts

If you followed the previous two steps you have two things: a data repository in terms of a Sitecore data template to store CMS field values and a data access mechanism to inject their values into strongly typed model classes. At this point you have everything you need to actually create the presentation components to render those values. Here are some guidelines to follow as you go through the process of actually surfacing CMS values:

Sitecore.Context.Item Considered Harmful

Seriously, don't use Sitecore.Context.Item. If you do, your rendering will only work if it is the item being viewed. It won't support personalization or AB testing. The best practice always is to default to the Data Source parameter and only if it is not set, use the Sitecore.Context.Item. If you're not using glass, you should do this by declaring a property of type Sitecore.Data.Items.Item and setting it as early as possible. If you are using glass, this is automatically handled for you if your sublayout or view rendering inherits from the provided base classes.

Avoid Monolithic Views

Just because you could render everything in the data template in a single rendering or sublayout, doesn’t mean you should. Try to apply the single responsibility principle in that a sublayout or rendering should only be responsible for rendering a single thing. It also goes back to your data template design: If you broke out some fields into a separate template and then inherited it, then it would make sense that to render the inherited fields you should just load a separate rendering or sublayout. The rendering or sublayout could deal with just the inherited class and not the page template class and could be reused easily on other pages that inherited that template.

Static vs Dynamic Binding Considerations

Even though you segmented your sublayouts to make it easier to compose, doesn't mean you should connect everything together using Sitecore placeholders. They are a great tool and necessary if you're looking to support personalization or AB Testing. But ask yourself if it's overkill. One of my pet peeves is seeing placeholders used to specify header and footer controls. Doing that means every single template and page will have a presentation detail configuration to connect those controls to the pages. Will they ever really change? Probably not, which means it's a complete waste of effort that would have been better suited for having the header and footer statically bound in the parent layout.

Avoid Code Behind In your Sublayouts

This is probably more of a personal preference than an actual recommendation, but having spent the last several years implementing MVC solutions, I feel quite at home mixing C# with ascx markup. So much so that I avoid writing code in the code behind where possible. Glass maps the current Item to the Model property and makes it available directly in the ascx. I'll even use a foreach loop inline instead of a repeater. The code just feels cleaner. Or don't use sublayouts at all and use view and controller renderings instead,

Be consistent with Naming and Location

Don't let things get messy. There is a place for everything and for everything there is a place. Organize your folders accordingly in the web project and ensure similar organization is applied in the Layouts items you create within Sitecore.

Configure Standard Values

You're never done with your page template until you connect everything together and completely configure it for use. This amounts to creating and configuring the standard values for your data templates. Here are the main areas you want to hit:

  • Presentation Details
    The first thing you should do is configure your page templates presentation details on its standard values. Configure all the layouts, sublayouts, data source and other parameters as needed. Once that's setup, create an instance of your page in the content tree and test things out. Unless by some miracle you go things working without needing to debug, but that never happens. 
  • Defaults
    The basic of the basics. Set the default values and use $name, $date and $time as needed.
     
  • Insert Options
    How do you intend for you template to be created anyway? And think about not only your template but any referenced template. You may need to make sure the subfolder you created for those content items are configured properly as well.
  • Validation
    This is a topic that deserves its own blog pose, but if there is a checklist of things to do before you're done done, configuring validation belongs there. Understand the difference between error types and make sure you understand how much it's going to inconvenience your content authors.
  • Workflow
    Don't forget to configure workflow for your templates otherwise you'll need to explain how certain content was published without approval. Trust me, not a mistake you want to make.
  • Icons
    For some strange reason I take great pleasure in looking through all the icons available to find an appropriate image for my template. I haven't probably seen them all hundreds of times but damned if I remember whether that icon was in the business or people category. That probably tells you something about me. Anyway, they are recommended and content authors probably do appreciate them, so you're not done till they're configured.

 

Conclusion

If you're new to Sitecore development, following the 4 steps outlined in the post will help point you in the right direction toward becoming productive developing page templates.

Did I miss any steps? Let me know what you think in the comments?

Monday
Aug182014

Sitecore Development in the real world - Organizational Strategies

There is a bit of a delta between understanding Sitecore development after taking training and understanding Sitecore development after delivering a project. Training doesn't discuss design best practices and tradeoffs. Training doesn't cover the use of source control in managing Sitecore artifacts, nor how to best package and deploy them between environments. Training doesn't explain the use of tools like Team Development for Sitecore (TDS) or ORM's like Glass Mapper.

Having spent close to the last year figuring it all out while developing solutions with Sitecore and seeing other developers go through the same process I did to get to the point when things "really clicked," I thought to capture some of my thoughts and lessons learned.

Your Sitecore Instance isn't part of your Project

 In some training courses, you actually will put a visual studio project in the same place where your Sitecore instance is installed. This leads to a fundamental misunderstanding about what Sitecore is and its relationship to the code you write. Sitecore is a platform, and you need to think of it as such. If you think about it like it's only purpose is to house your specific solution, you are going to make design decisions that will make sure that's all that will be possible.

Instead, think that every Sitecore artifact you create and every piece of code that you write will have to be deployed to an environment you may not entirely control. An environment where other code, other sites created by other developers, may run at the same time. This will impact the way you develop with Sitecore from the way you structure your Visual Studio solution to the way you organize Sitecore items in the content tree and more.

Flexibility and Isolation in VS Solution Configuration

From a visual studio perspective, this means that you need to think about your web projects being deployed to a Sitecore instance via xcopy. This means all existing files in the target Sitecore instance will be over written every time you deploy and more to the point, other projects may overwrite your files every time they deploy. This kind of thinking is both limiting and freeing at the same time.

Namespace Gotcha 
Don’t use "Sitecore" in your project namespaces. This will just cause collisions when you need to use Sitecore's API's. Instead make your namespaces relevant to your domain. If it is Sitecore specific, use SC instead. Libraries like Glass do this.

It feels limiting in the defensive measures you will need to take to fend off such issues. Making extensive use of custom Sitecore configuration files and avoiding making changes to the web.config ensure your configuration doesn't get lost and even helps avoid issues when you have to upgrade or patch your Sitecore instance. Putting your layouts, sublayouts, renderings, scripts and css files in subfolders named with your project will ensure their paths are unique and avoids overwriting collisions when multiple solutions have common file names like "header.ascx."

Deployment Strategy
You have a few options to facilitate builds to your local Sitecore Instance. If you're using Team Development for Sitecore (TDS), it makes it extremely easy as it will automatically deploy your web project to your Sitecore instance root on build. If you don't have TDS, you'll need to configure web deploy and a post build step to automate deployment. With either approach, I also recommend "AttachTo," a visual studio extension that will allow you to debug your local IIS instance in one click.

It feels freeing, because by keeping all the pertinent code changes isolated from each other, you can actually break your Sitecore solution into many smaller projects, which can be deployed together or separately, giving you a level of code reuse you wouldn't have otherwise. If you have a feature, a pipeline component or even just a set of templates that have high reuse potential, you can segment each into their own set of projects and package them together (code and artifacts).

Avoiding Sitecore Item Collisions

Lucky for us it is pretty straight forward to avoid other projects overwriting your custom Sitecore items. Simply create subfolders with your project's name before adding any custom items. You need to do this everywhere you create Sitecore items.

In the Layout folders: Layouts, Sublayouts, Renderings, Placeholder Settings etc, you should first create a subfolder to contain your layout items. In the media library you should not only create a subfolder for you project, but ensure every Image field in related data templates use that folder's path in that field's data source. In the dictionary, you should not only create a subfolder for your project, but use a consistent prefix in all your dictionary keys to avoid collisions. Workflows and Validation Rules should also employ the same project folder tactic. This ensures that other projects or packages will not overwrite your Sitecore items unless they are explicitly trying to do so.

Organize your Content Tree

Content organization matters a lot in Sitecore development, and though it's straightforward to move things around after the fact, it is a pain if you have live content that has been indexed, and it's not worth the hassle of dealing with redirect rules if instead you just put the effort to get it right the first time.

By default when you install Sitecore, you simple see a home item under the Content node. I generally recommend deleting that node and creating a structure that makes sense and can scale easily to meet you requirements now and in the future. Sure, you'll need to adjust the Sites configuration ( use a custom include config file ), but it will be more convenient in the long run to manage.

I'll tend to create at least 3 folders for every site hosted in Sitecore I create as well as a Global folder to store content and configuration that impacts multiple sites.

The Home folder is what will be mapped in the sites configuration for the url binding used for the site. In general the nodes under this will have configured presentation details and accessible via url.

The Data folder is basically the root of the "content library" specific to that site. Every type of content you need selectable in your page templates should be organized into subfolders to make it easy to find and select content that is referenced by multiple pages. Your droplink, multilist and treelist fields should reference to paths here to make reusable content selectable. The data folder under global should similarly be used, but for content that can be selected and reused across sites.

Tradeoffs
There is a tradeoff when you put content in the data folder. It makes it a little more difficult to see the relationship between your page instances and the data it references. An alternative would be to make the data template instances children of the page instance itself, and this is a viable approach if and only if the content wont and never will be used by any other pages. Any benefit of association to the page template would immediately be lost if you needed to duplicate content or try to connect content under one page with another.

The configuration folder should hold Sitecore Items that control how the sites behave. In general, these are global static items that help configure things like layout and impact everything on the site. I'll often create a navigation subfolder here to help organize menu items for global navigation. The configuration folder under global should similarly be used but for configuration items that impact multiple sites.

Data Template Organizational Strategy

Besides creating a root folder for your custom data templates, you should give some thought to how to best organize your custom data templates. Every solution will have its own nuances, but I generally recommend a minimum of 4 key folders to give a logic separation to all the templates you will create:

  • Base Templates - here is where I put templates that are meant to be inherited. This includes not only base page templates, but templates that group common fields together for reuse. If you have more than a few base types, consider creating subfolders to make it easier to understand the organization.
  • Page Templates - here is where I define the templates that will be populated in the content tree and available as insert options.
  • Component Templates - here is where I define templates that drive data that is selectable by page templates. Instances of these templates will either be stored in a subfolder of the "data" folder or as a direct descendant of a page template.
  • Configuration Templates - here is where I define templates that control global site behavior. Avoid creating monolithic templates that encompass all possible settings. Instead try to group the configuration settings to logical groups and create instances of them in either the sites or global configuration folders.

You should also carefully consider how you name each template you create and the fields within them. If you are using an ORM like glass and using code generation to create classes, the names of your templates will become the names of your classes and the names of your fields will become the names of that classes members. Remember that at least with fields, you can give a developer friendly name to the field and a content author friendly name by leveraging the fields "title" property (you'll need to click on the field in the content tree instead of the builder tab of the template).

Conclusion

A lot of what I discussed in this post relates to just thinking through your solution and understanding the impacts of the decisions you make on the maintainability of your Sitecore project. In the end, understanding what you are trying to accomplish and how will it be executed before beginning to make design decisions will save time spent on rework.

What do you think? Share your tips for organizing Sitecore items in the comments.

Saturday
Jan252014

Announcing Mtelligent, My first attempt at open source.

Yes it's the name of the blog too, but I decided to name my current side project after it. And I decided to open source it. It's a A/B, Multivariant Testing and Cohort Analysis Framework for ASP.Net.

Instead of writing a blog post about it, I put all the detail into the read me file. You can find it on Git Hub here.

Over the next few weeks, I'll share more details about the internals of the framework, and hopefully make some progress toward closing some of the gaps I've already identified.

I'm releasing it now, because I think it's in good enough shape to share, and I actually wanted to get some feedback on it.

 

Sunday
Dec222013

Share Location Confusion (Geolocation Settings for IPhone and Android)

A few weeks ago I shared some tips for leveraging the HTML5 geolocation api's. The API is great, and opens some very cool possibilities, especially when coupled with Google maps API's, but the one weakness is the browser implementation of user preferences when it comes to sharing your location with a website.

Maybe if it wasn't so inconsistent between IPhone and Android devices, it would be more managable, but right now it can be downright confusing.

Android's stock browser has a bit better implementation in my opinion. The first time you come to a site that requests your current location you get prompted on whether or not you want to share your location with that website. Whatever you answer, the stock browser will remember forever. You never get prompted again, it will just continue to share or deny access to your location for that website. If you do want to change the answer, you can go to Settings (from the Browser Menu), then Content Settings, then Website Settings and actually control your location settings for each website.

IPhone and Mobile Safari is a bit more complicated. The first time you come to a site that requests your current location you get prompted on whether or not you want to share your location with that website. But unlike Android, you do get prompted a second time if you refresh the page. As long as you answer the same, after the second prompt you will never get prompted again. Plus there is no way to change your location preferences for individual websites. The only way to change it, would be to nuke all your location settings by going outside of safari to settings, General, Reset, Reset Location and Privacy. And that removes everything. You actually get prompted to allow safari access to your location before getting prompted again to allow access to the website, bringing the total number of prompts to 3 if you change your mind.

In either case, if a user deny access to a website, talking them through reversing that decision is daunting at best, and you should give it some thought when you figure out when and how to prompt a user to share their location, because chances are, you will not get a second chance if they deny you.

 

Saturday
Dec142013

IPhone scrolling woes 

We were experiencing some weird behavior when testing the mobile site we were developing on IPhones. Long pages were missing their scrollbars. Touch scrolling was not smooth at all. And on pages with form elements, the page would seem to get stuck when scrolling. Stuck such that you couldn't scroll any further down or you couldn't scroll up if you were already down. 

After a bit of research, I found this webkit css style that when applied to our outmost div, seemed to resolve these scrolling issues.

-webkit-overflow-scrolling: touch;

After adding that single line of css, all the scrolling issues mentioned earlier seemed to disappear. But there were additional issues that appeared.

The first issue surfaced when scrolling quickly on pages of our site with complex layouts. When they were scrolled too fast, white blocks temporarily showed up. The renderer caught up and displayed the content after the scrolling stopped, but it just felt and looked weird. 

The second issue we noticed on pages with text boxes. When you went to type in the textboxes, you wouldn't see the text, but it would show up after exiting the focus of that textbox.

Researching the first issue, I came across this post about rendering issues with webkit overflow scrolling which mentioned a work around. So I went through all of our css, adding an additional style rule to any rules that had position: relative defined.

-webkit-transform: translate3d(0,0,0);

And that seemed to fix both the fast scrolling and form issues I mentioned. Very strange, but applying a no move/change 3D transformation gets the css to be hardware accelerated and makes the page behave better. I know it feels like a hack, but it's a hack that seems to work.