#Sitecore October 2018 Chicago Meetup Impressions

This was the second Sitecore meetup this year. This one was at a different location. It was at Productive Edge in downtown Chicago. It was a scenic walk from the train. The office itself was setup nice. A lot of the attendees will be at the Sitecore Symposium, so it was nice to connect with them. We also used the Symposium app scan on the network menu to connect with each other. Of course, they had my favorite pizza, Lou Malnati’s.

The first presentation was a joint effort by Ryan Kuchler and Will Rolloff. This covered Context Marketing from both a marketer’s point of view and developers’ point of view. One of the things I believe that are overlooked by clients after a Sitecore site is complete is the powerful marketing tools that are in Sitecore.

Summary of topics:

  • Marketers – Get to know Context Marketing and deliver personalization to your audiences with out of the box Sitecore features and configurations – Today!
  • Developers – Architect and deploy the right application components that enable the business to drive context marketing and scaling it to meet your organizations needs using Microsoft Azure

They did an excellent job presenting and it was the best presentation I have seen on Context Marketing. I walked away with much more specific understanding on how all the different pieces worked. I especially liked the parts were previous versions of a page were compared to a new page, setting the score for each campaign and swapping out presentations based on visits. I will be using this information in the future.

Last, but not least Will presented tips for first time Symposium attendees. I wish I had these for my first Symposium. Even so it being my second Symposium coming up I still learned a few things.

One thing he forgot to mention. Take all the Sitecore bling you can with you.

Sitecore Symposium for Newbies #SitecoreSYM @ParagonDev

So last year being my first Symposium I did not know what to expect. I know there will be a lot of new attendees this year, so I wanted to give you some advice to make it the best experience that it can be.

Network, Network, Network

Starting at the airport I must have made at least five contacts with people also travelling to the Symposium. Waiting for my plane and the bus to the hotel. Also, I met in person a few people I have talked to online. I even ran with one of them. Yes, running with someone is a good way to network. As you make connections always make sure you have a bunch of business cards with you, so they contact you for whatever reason. A lot of the people you will meet may be someone you work on a project with in the future or may need to reach out to for some help.

Get to Know Your Co-Workers.

A lot of us work remote and don’t interact with our co-workers daily. If we do it is usually via email, skype, slack, WebEx etc.… Being at the Symposium face to face with people you work with can help establish a better working relationship. The old saying a face with the name is never more so true in today’s world. I also ran with one of my co-workers.

Get some nice bling.

From the time you arrive at the Symposium to the time you leave there are so many things with different Sitecore branding that you can take with you. I collected several buttons, flashlights, a hotel key, small plastic beer mugs, glasses, ice cubes you name it with Sitecore logos on it. Not to mention I got a lot of cool stuff from all the vendors there. Including stuff like pop sockets and socks.

Give some nice bling.

I mentioned buttons above and this year I decided to do my own to trade and give out. I think this will not only be a good way to promote my blog site, but break the ice with several other attendees. The company I work for Paragon was giving out cool flashlights last year. I made sure to hand those out whenever I could.

Be comfortable and dress nice.

Working remote I honestly don’t dress business casual these days. The recommended dress for the Symposium is business casual. I normally wear running shoes, but I thought I would get something that was like a classic sneaker, but could also work with business casual attire. Well good-looking shoes does not equate to comfortable. I was in so much pain it got harder to walk around every day (you will do a lot of walking). I learned my lesson and this year I plan on wearing shoes that are broken in and comfortable. You can look up business casual attire since it is interpretation is open, but considering you will be representing your employer there you want to dress nice. I am fortunate enough to have shirts with Paragon’s logo on it.

See you all there!

092018_0302_sitecoresym5

Adding RTE RichText Custom DropDown List in #Sitecore 9

Recently I had to do a custom implementation for an RTE dropdown list in Sitecore 9. I used @jammykam’s example to get started. This was done in a previous version of Sitecore. You can find it here. Granted the implementation did not change too much between versions, but if you are searching for a way to do it in Sitecore 9 this should help since there is at least one minor difference I found.

So, to not disturb the out of box RTE profiles I duplicated an existing one.

I created a custom dropdown button in the part of the RTE toolbar I would like to have the button available.

To tie the Rich Text Profile with its own EditorConfiguration pipeline a Configuration Type was added to the profile.

In the Visual Studio solution, I created the following which will define the button, add CSS and add JavaScript.

The InsertToken.xml contains the following:

  1. <? xml version = “1.0”  
  2. encoding = “utf-8” ?> < control xmlns: def = “Definition”  
  3. xmlns = http://schemas.sitecore.net/Visual-Studio-Intellisense&#8221; > < RichText.InsertToken > span.InsertToken {  
  4.     background – image: url(‘/sitecore/shell/Themes/Standard/Images/Editor/WebResource.png’) !important;  
  5. } < /RichText.InsertToken> < /control>  

    The InsertToken.js contains the following. Telerik controls were used in later versions of Sitecore including 9 instead of the RadEditor controls.

  6. Telerik.Web.UI.Editor.CommandList[“InsertToken”] = function(commandName, editor, args) {  
  7.     var val = args.get_value();  
  8.     editor.pasteHtml(val);  
  9.     args.set_cancel(true);  
  10. };  
  11. jQuery(document).ready(function($) {  
  12.     loadCSS = function(href) {  
  13.         var cssLink = $(“<link rel=’stylesheet’ type=’text/css’ href='” + href + “‘>”);  
  14.         $(“head”).append(cssLink);  
  15.     };  
  16.     loadCSS(“/sitecore/shell/Controls/Rich Text Editor/InsertToken/InsertToken.css”);  
  17. });  

    The InsertToken.css contains the following. The reason for this CSS code is so that the button in the RTE appears correctly. @Ja

    span.InsertToken {

  18. background – image: url(‘/temp/iconcache/office/16×16/document_json.png’) !important;  
  19. }  

    Under Pipelines\RichTextEditor an override to the EditorConfiguration was created.

    You can use DotPeek or another decompiler to get the code to override, but the main thing you want to change is the following in this case. Note the ItemsPerRow kept the column values in one single line.

  20. case “Html Editor Custom Drop Down Button”:  
  21.     var editorSplitButton1 = new EditorSplitButton {  
  22.         Name = str1, ShowIcon = true, ItemsPerRow = “1”, ImageUrl = “/temp/iconcache/office/24×24/document_json.png”  
  23.     };  
  24.     EditorSplitButton editorSplitButton2 = editorSplitButton1;  
  25.     SetProperties((EditorTool) editorSplitButton2, obj);  
  26.     EditorConfiguration.SetChildren(editorSplitButton2.Items, obj);  
  27.     toolbar.Tools.Add((EditorToolBase) editorSplitButton2);  
  28.     continue;  

    The list of values is fed from Sitecore. The token item contains a Description and TokenValue field.

    SetChildren is called which in turns calls GetTokenList to retrieve the values and set the dropdown.

  29. private static void SetChildren(EditorDropDownItemCollection items, Sitecore.Data.Items.Item parent) {  
  30.     Assert.ArgumentNotNull((object) items, “items”);  
  31.     Assert.ArgumentNotNull((object) parent, “parent”);  
  32.     foreach(Sitecore.Data.Items.Item obj in parent.Children) {  
  33.         if (parent.Name == “Insert Token” && obj.TemplateName == “Html Editor List Item”) {  
  34.             items = GetTokenList(items);  
  35.         } else {  
  36.             if (obj.TemplateName == “Html Editor List Item”) {  
  37.                 items.Add(obj[“Header”], obj[“Value”]);  
  38.             }  
  39.         }  
  40.     }  
  41. }  

  42. private static EditorDropDownItemCollection GetTokenList(EditorDropDownItemCollection items) {  
  43.     Sitecore.Data.Database master = Sitecore.Configuration.Factory.GetDatabase(“master”);  
  44.     Item parentTokenFolder = master.GetItem(“/sitecore/content/Tokens”);  
  45.     if ((parentTokenFolder == null) || (!parentTokenFolder.HasChildren)) {  
  46.         return items;  
  47.     }  
  48.     foreach(Item token in parentTokenFolder.Children) {  
  49.         items.Add(token.Fields[“TokenValue”].Value + ” – “ + token.Fields[“Description”].Value, token.Fields[“TokenValue”].Value);  
  50.     }  
  51.     return items;  
  52. }  

     

    After the changes you should see the RTE button in the editor and selecting it should insert the text that was predefined.

#Sitecore July 2018 Meetup Chicago Impressions

This was the first Chicago Sitecore meetup this year. It is always great to see familiar faces at these things and reconnect. Some of the attendees I have worked with in the past and/or is a client of Paragon. Also a lot of them I follow on Twitter, but have not met in person so it is good to put the name and face together.

I am not going to lie I always look forward to the food at these things. Lou Malnati’s is my favorite pizza. The bling is also nice too.

The first presentation was done Ahmed Okour and James Gregory from American Eagle, “Deep Dive into Sitecore Installation Framework”.

A lot of the stuff they went over were things I encountered doing my first Sitecore 9 install. It was nice to get a better picture on what happens behind the scenes. On another note I had to hold back the laughs along with others as the words “SIFless” and “Sharding” were mentioned.

The next presentation was done by Naim Al and James Gregory from American Eagle, “Understanding Sitecore Custom Analytics and Power BI”.

This was in interesting one. There was the out of the box Sitecore tool introduced as well as a third-party tool. Very useful stuff for Marketers.

After the presentations were over it was time to go. Not before snapping a few goodbye picks. I am hoping the next Chicago Sitecore meetup will be soon.

Updating #Sitecore 9 Update 1 to Update 2

I am always a little hesitant going from one Sitecore version to another, but with Sitecore 9 I believe it is a straightforward process. Using the Sitecore package updater simplified things. Steps and pictures below.

In the control panel choose Install an Update.

Choose your package and upload.

Click the Analyze the Package brings up this screen:

I then clicked the Analyze green arrow. The following screen appears.

Some of the conflicts were spaces or things that I could skip. If it was a configuration change I still needed a patch was created. Really nothing too major.

That was it for me. There are some minor things that might need to be adjusted. Keep in mind that you will need to update NuGet packages in your Sitecore Visual Studio solution. Also, any config and pipeline changes that might be different.

Upgrading to #Sitecore 9 Data Exchange Framework Module 2.0.1. What to Expect. #DEF

In last year’s blogs I did a several part series on the Data Exchange Framework or DEF. You can find that here. I decided to upgrade my DEF Reddit feed module to the latest versions of Sitecore and DEF to get more familiar with the changes.

The first thing I did to the solution after installing the new latest version of DEF into Sitecore 9 Update 1 was to replace the following files.

Code Changes:

Starting with BaseReadDataStepProcessor I noticed a slight change.

The following code:

protected override void ReadData(Endpoint endpoint, Sitecore.DataExchange.Models.PipelineStep pipelineStep, PipelineContext pipelineContext) {  

Should now be:

protected override void ReadData(Endpoint endpoint, PipelineStep pipelineStep, PipelineContext pipelineContext, ILogger logger) {  

As you can see from the above code PipelineContext was replaced with ILogger.

The function that adds the plugin has changed.

From this:

pipelineContext.Plugins.Add(dataSettings);  

To this:

pipelineContext.AddPlugin(dataSettings);  

In the RedditFeedValueReader the following method has changed since CanReadResult object is now ReadResult,

Original:

  1. public CanReadResult CanRead(object source, DataAccessContext context) {  
  2.     bool flag = source != null && source is RedditSharp.Things.Post;  
  3.     return new CanReadResult() {  
  4.         CanReadValue = flag  
  5.     };  
  6. }  

    Change:

  7. public ReadResult CanRead(object source, DataAccessContext context) {  
  8.     bool flag = source != null && source is RedditSharp.Things.Post;  
  9.     return new ReadResult(DateTime.Now) {  
  10.         ReadValue = source, WasValueRead = flag,  
  11.     };  
  12. }

    In the RedditFeedFieldValueAccessorConverter class I noticed the following issue after upgrading.


    After using DotPeek to take a look I found this method no longer exists. It looks like it has been renamed/replaced by ConvertResult. Also it has been set to protected vs public.

  13. protected override ConvertResult < IValueAccessor > ConvertSupportedItem(ItemModel source) {  
  14.     return this.PositiveResult((IValueAccessor) new ValueAccessor() {  
  15.         ValueReader = this.GetValueReader(source), ValueWriter = this.GetValueWriter(source)  
  16.     });  
  17. }  

    So, I converted by existing method and it works again.

  18. protected override ConvertResult < IValueAccessor > ConvertSupportedItem(ItemModel source) {  
  19.     var accessor = base.Convert(source);  
  20.     if (accessor == null) {  
  21.         return null;  
  22.     }  
  23.     var fieldName = base.GetStringValue(source, RedditFeedFieldValueValueAccessorItemModel.RedditFeedFieldName);  
  24.     if (string.IsNullOrEmpty(fieldName)) {  
  25.         return null;  
  26.     }  
  27.     if (string.IsNullOrEmpty(fieldName)) {  
  28.         return null;  
  29.     }  
  30.     ValueWriter = this.GetValueWriter(source);  
  31.     ValueReader = this.GetValueReader(source) ? ? new RedditFeedValueReader(fieldName);  
  32.     if (ValueWriter == null) {  
  33.         ValueWriter = new PropertyValueWriter(fieldName);  
  34.     }  
  35.     return this.PositiveResult((IValueAccessor) new ValueAccessor());  
  36. }  

    The way ids were set before is now a bit different.

    Before I would set id’s using the following:

  37. private static readonly Guid TemplateId = Guid.Parse(“{CE67E73A-40DF-4AB7-A7D3-2FD65E166E2E}”);  
  38. public RedditEndpointConverter(IItemModelRepository repository): base(repository) {  
  39.     this.SupportedTemplateIds.Add(TemplateId);  
  40. }  

    I changed that and now just do this:

  41. [SupportedIds(“{68BD9AAD-635F-40F3-9ACD-711662C59EEC}”)]  

    Sitecore Changes:

    The value mapping has changed to a Treelist instead of a droplist.

    The window that gave you updates while the batch process ran has changed. Now it links to a log file.


    Those are the changes I made for now. Unfortunately, I am not able to run the process as I did before. It seems something else has changed. I am currently digging into that and have gone to Sitecore support for help. I will document the change in my next blog and also update the code repository so you can see the new changes.

#Sitecore #SCHackathon 2018 @ParagonDev Top 5 Reasons of Failure and Top 5 Reasons the Experience Was Better

Well with very little sleep this weekend I am writing this blog as the thoughts of my second Sitecore Hackathon has ended. I was on team SIF Lords. We all love Star Wars and Sitecore if you can’t tell by the name. We came up with a clever idea this year that would combine my running world (Strava) with Sitecore. Just like last year though with a different team my team this year failed to get the needed things in time to qualify. We needed about 26 hours not 24. However just like last year all was not lost. I don’t do these contests to win. It would be nice to win, but there are more important things at play here. So here are my top 5 reasons for failure, but also top 5 reasons why the experience outshines the failures.


Top 5 Failures

Ever year is going to be a learning experience I learned from my failures last year and vowed to not make the same mistakes. Well mostly not the same mistakes. Here are the mistakes this year. Hey, we never stop learning.

  1. Not trying to cover all the bases.

    Knowing there was a lot introduced in the last year new to Sitecore we probably should have studied each thing we though might be part of the contest that was introduced in Sitecore recently. We instead had ideas and going into the assumption that they would be broad enough to fit in. We were wrong.

  2. Installing anything in Sitecore that was not out of the box.

    Well this one I learned a little from last year. We decided no Glass Mapper and we would use Unicorn instead of TDS. Well I am a huge fan of TDS, but Unicorn was lighter to install and one of our team members had experience with it. I had a little experience with it. This would be a good opportunity to learn it better. Well in the end that did us in. No fault of Unicorn which is a great product btw, we missed a few configurations so we had some syncing issues. Lesson learned. Maybe we just use Sitecore packages next year.

  3. Not spending enough time mentally preparing.

    Working all day and it being a Friday I thought it would wind down gradually and then I would be mentally prepared for the hackathon. Well as everyone knows in the programming world things can get hectic at times. So, by the time I finished work I had to go right into the hackathon. Maybe next year I take a half day off and prepare.

  4. Not meeting with the group beforehand.

    We did have some chatroom talk on Slack and email, but we never had an official phone meeting. Not sure if it would have been beneficial, but it might have helped the brainstorming session go a little quicker.

  5. Being overconfident.

    Hey coding is hard if you don’t know. However, as developers we love to code. Sometimes though when you think you know everything you just don’t. This goes back to number 1. Study anything you can that you are not familiar with.

Top 5 Experiences

No matter the failures these experiences overcame any failure that happened.

  1. I got to learn something new.

    The topics introduced to us when the contest started was something we haven’t had experience in it. We came in the contest with all these ideas, but wham we were hit with the reality that none of them will work. So, we picked the path that we hoped we can have the most success on XConnect. Also, as mentioned above I got more experience with Unicorn.

  2. Crash course into Sitecore 9.

    This goes along with learning something new, but it does deserve its own number on the list. Right before the hackathon after several tries I finally got Sitecore 9 installed. I barely had time to play around with it so as my team got coding I had to learn all the new things that come with the latest version of Sitecore.

  3. Brainstorming a unique idea and executing that idea.

    We spent a good hour or two coming up with ideas that could fit into what we wanted to do with XConnect. We hit some dead ends, but finally came up with a pretty solid idea. When you have 24 hours to code something though you don’t exactly know if that idea will work or not until you really get into it. Towards the end the idea looked like it was going to work. Too bad we ran out of time.

  4. I got to work with co-workers I normally don’t get to.

    I am very blessed to be working for a great company. I know one thing that makes the company great are the people working there. I haven’t really worked with these specific co-workers until the hackathon. I didn’t know what they would be like other than talking to them socially. In that 24 hours we were working together as a solid team. I got to know them more and I am sure when we work on an actual project for Paragon we will be even more prepared and cohesive.

  5. I love the Sitecore world.

    Knowing that there are other Sitecore developers crazy like us makes me happy to be part of the family. I think about how much Sitecore has meant to my career and anytime I can be more involved with the it I want to seize the opportunity. There is so much to learn in Sitecore no matter how long you have been using it.

So now that I am reflecting on my experience will I be back next year? Well when I am running a marathon at mile 20+ I always question myself on why the heck did I decide to do this. I felt the same way with the hackathon in the 20+ hour. However, when it was over I thought yeah, I will do that again just like a marathon. Special thanks to everyone in the Sitecore family that made this year’s Sitecore hackathon special. Most of all to team SIF Lord. Next year we got this. If you like to follow the rest of my team you can find Steve on Twitter here and Jennifer on Twitter here.

Named a #SitecoreMVP 2018 MVP Technology

As I am writing this I am still in shock. Several years ago I was just learning and developing with Sitecore at night while working on other projects during the day. Little did I know where it would lead me. I have run several marathons and I can tell you this journey was a marathon. There were some good and rough times along my way, but I kept moving forward.

My drive to become an MVP started a year ago when I got a job with Paragon and they gave me the confidence to believe I can achieve MVP status. I talked to many MVPs this past year and they gave me a lot of helpful advice. I have met so many people in the Sitecore community this past year as well and I am excited about being more involved in the community as an MVP and making new connections. The highlights of this year have been the meetups, Slack conversations and most of all getting to attend the Sitecore Symposium in Las Vegas. So, I just want to say thank you to Paragon, all the MVPs who gave me advice, aspiring MVPs that were on the ride with me, Sitecore of course and the Sitecore community.

So now what? Well no matter what if I didn’t get awarded MVP I was going to continue doing what I am doing. I learned a lot about myself this past year. I love blogging, I really love Sitecore more than I realized before and most of all I love sharing my knowledge. If I was going to add something new I think it would be coming up with a YouTube video this year. I just need to find the right blog topic.

To see all the winners check it out here. Also congratulations to my co-worker Scott Gillis who has gotten Sitecore MVP for the second year in year in a row. You can check his blog at thecodeattic.

 

Refreshing #Sitecore Links Database for an Item and Seeing What Links to the Item

I had a client and recently a question came up on Sitecore Slack about the Sitecore link database and how you can find what items link to an item. This is one of those simple solutions that I may refer to in the future and also it may help someone else. In my client’s case they needed to know what media images linked to the item. I will keep this short and sweet. You can see my comments in the code below. Let me know if you have any questions.


Limiting #Sitecore Field Descriptions Using a Partial Class and #GlassMapper

Using a partial class to manipulate/change glass mapper model fields is common. I recently had to do this and thought this little tip for shortening descriptions fields would be come in handy for others. In this case an event listing was displayed. If the description was longer than 50 we would truncate the text and display it with the three dots at the end.

To add the partial class was simple. The key here is having the namespace the same name as you do in the generated model that Glass Mapper generated. If the namespace differs than the partial will not work since it cannot match the class you are adding additional functionality too. In my case ReSharper warns me the namespace path does not match of where I placed my partial class, but that is okay as I know it matches what is in the generated model.

This is what the partial class syntax looks like:

using System;

using Glass.Mapper.Sc;

using Glass.Mapper.Sc.Configuration.Attributes;

namespace Events.Models.sitecore.templates.Feature.Events

{

public partial class Event

{

private string _mainContentDescription;

[SitecoreField(IEventConstants.MainContentFieldName)]

public virtual string MainContentDescription

{

get

{

return _mainContentDescription;

}

set

{

ISitecoreService service = new SitecoreService(Sitecore.Context.Database);

var eventsettings = service.GetItem<EventsSettings>(Constants.Items.EventsSettings);

if (!int.TryParse(eventsettings.Text_Limit, out int textlimit))

{

textlimit = 50;

}

_mainContentDescription = value;

_mainContentDescription = !string.IsNullOrEmpty(MainContentDescription) ? TruncateAtWord(MainContentDescription, textlimit) : MainContentDescription;

}

}

public static string TruncateAtWord(string value, int length)

{

if (value == null || value.Length < length || value.IndexOf(” “, length, StringComparison.Ordinal) == -1)

return value;

return value.Substring(0, value.IndexOf(” “, length, StringComparison.Ordinal))+(“…”);

}

}

}


When we go ahead and use it in the view this is what the syntax will look like.

<div class=”desc”>@Html.Raw( Model.MainContentDescription )</div>

Your description should look something like this one done:

This is a description that I don’t want to show it…

There are many possibilities you can do with partial classes and glass mapper. In this case this saved me the time of truncating the characters in the view or creating a separate model were I would have to read the descriptions in and truncate them that way and send that model to my view for example. This is a clean and easy solution and I can use the existing generated glass model so this limits the changes I normally would have to make.