#dotNETConf, Day 1 – Summary

Day 1 is in the books! I’ll admit I didn’t see everything, only certain sessions, but I thought I’d share what I got out of the free, virtual .NET conference hosted by Microsoft on Channel 9.

Keynote – Scott Hunter

I loved the Keynote; they got right to the heart of what’s new and cool with .NET, specifically explaining what .NET Standard is, how .NET Core is evolving and such. They went over the new templating engine – how you can use dotnet new in a console to create a new project without the need for Visual Studio. That command will show a list of available projects you can create. You would then run dotnet new Console, for instance, to create a new C# Console application.

One really cool thing they showed was the ability to edit a .csproj file without having to unload the project. I am LOVING these quality of life improvements Microsoft has been rolling out! In fact, last week I learned that in Visual Studio 2015 you can evaluate lambda expressions in a Watch window, which blew my mind, so I can’t wait to start using the newer versions of this great IDE.

Scott then showed Razor Pages, which as Razor views with .cshtml.cs code behind files included. Pretty cool, seems like MVC for Slackers basically. Probably not for me personally. Then, he showed Application Insights and Snapshots in Azure, which can provide detailed information about errors the application ran into. Good stuff.

Mobile .NET – Miguel de Icaza

Miguel showed a really cool feature of Visual Studio for Mac, where you can specify code to be run live. Meaning any change you make to the code will automatically propagate to the mobile phone / front end without having to save the file. He also shared something called the Embedinator-4000, which basically turns any .NET library into a native library, and it supports a range of things:

embedinator4000.png

Visual Studio 2017 & C# 7.x – Mads Torgersen

New notable features are available in VS 2017, including:

  1. Code Styles – setting code standards in the IDE. VS will tell you when you deviate from the standards you set up.
  2. Live Unit Testing – as you are writing a class, or a controller, you can have a unit test running and providing pass/fail information as you type
  3. Smudges – small dots under a class name that might indicate suggestions – one example:

smudge.png

.NET Foundation – Jon Galloway

This session explained what .NET Standard is and how they are improving it. I thought .NET Standard meant .NET Framework before I attended this session. .NET Standard is a set of APIs that all .NET platforms have to implement (including .NET Framework). It’s a specification, not a thing you install, and it’s primary use is code reuse across all platforms that use it. The higher your .NET Standard version, the more APIs you get; the lower the version, the more platforms support it. Jon demoed a web application that shows which APIs are available in which .NET Standard versions; I don’t think it’s live anywhere, but looks pretty useful.

Diagnostics 101 – Jon Skeet

The purpose of this task was to inform people how to diagnose and troubleshoot programming issues better, before posting on Stack Overflow. That’s something I was guilty of when I first starting writing code so I can relate. The ones I got the most out of:

  • Divide and Conquer – Reduce the size of the codebase you’re looking at when trying to solve a problem. Essentially, he’s saying that you need to do some trial and error, eliminate some pieces of code that you think may be where the bug is hiding, and keep doing that until you uncover the bug. It’s common sense to me.
  • Challenge Assumptions – Your code is probably wrong. Question everything. This is basically what happens to me every time I start writing a Stack Overflow question. There are so many questions I started that I didn’t end up submitting because I realized what the problem was while I was typing it into the site, it’s incredible.
    • Things to be skeptical of:
      • Your code
      • The debugger’s immediate window – if it seems off, don’t trust it
      • In Watch, beware of the debugger’s string repesentation

Summary

Overall, really good first day. Not sure how much I’ll be tuning in for Day 2, unless I have absolutely nothing else to do.

Advertisements

#MKEDOTNET 2017 was a blast!

This past Saturday I attended MKE DOT NET for the third time. MKE DOT NET is a .NET developer conference based in the Milwaukee area. The previous two years the conference was held in a hotel in Pewaukee. This year, they changed things up a bit and hosted it at Potowatomi Casino near downtown Milwaukee. Getting there was a bit difficult because there were a lot of closed off streets, but once I got there it was really nice.

Keynote Speaker: Maria Naggaga

Lots of people are interested in developing in .NET, but the main complaint was that it’s too difficult to learn. Maria presented some up and coming options to make .NET easier to learn for people who are currently developing in other frameworks and languages, like Python or Ruby for example.

First, she listed off some recommended code school sites. This was helpful for me because I’ve been trying to get my brother into coding with .NET and C#. Sites included Free Code Camp, Code School, Treehouse, and Javascript.com. Next, she showed an upcoming version of docs.microsoft.com, which will include everything in the current Docs site, but added a Run button for every code snippet. That part wowed me; I know one of the big annoyances with developers learning .NET was having to install Visual Studio to do any coding, so this goes around that. Great job MSFT!

After the keynote, I attended several sessions. I will list out the sessions which I got the most out of below:

Hardening Your ASP.NET Core Applications – Brice Williams and Robert Hansen

This session went over securing ASP.NET Core applications. Brice and Bob showed how to enforce HTTPS on a site at the global level or controller level. Additionally, they went through some common security risks, such as Cross Site Scripting (XSS) and Cross Site Request Forgery ( CSRF), and how to counteract those in your application. One cool thing I learned was that Javascript UI frameworks like React or Angular will do the HTML encoding for you as a way to protect against CSRF. The most important point made was to not create a security system yourself; it is extremely difficult and there’s probably a system available that someone else made that would work for you.

Cool SQL Server Features Every Developer Should Know About – David Berry

This presentation went over some new features in SQL Server 2016:

  1. Temporal tables – Every time a row is changed, SSMS keeps a snapshot of the old row values. This allows us to see what the value in a column was at any given date and time. The history table is created and maintained automatically by SQL Server, removing the need for us to write triggers.
  2. JSON Support – Allows you to store JSON data in a VARCHAR() data type. There are some new functions that go along with this, such as JSON_VALUE to get a value from a JSON object,  and JSON_QUERY to pull out an entire array or object.

David also showed Windowing Functions, which was actually released with SQL Server 2008 and later. “Group By on steroids”, Windowing Functions can partition and aggregate data by different criteria in the same statement. One example was the RANK() function, which can find the highest value, partitioning over various columns, and provide a rank for each row. I really need to look into these functions more…

Building Reusable UI Components in ASP.NET Core MVC – Scott Addie

.vbhtml files exist. It’s true. That wasn’t the point of this talk though. Scott showed us a brand new feature in ASP.NET Core V1 called Tag Helpers. Using this feature you can express server-side processing via HTML elements. An example would be:

<hand player="John">

Hand is the class, Player is a property of Hand. Tag Helpers are really cool for a few reasons:

  1. They offer great IntelliSense support.
  2. They eliminate context switching between HTML and C# that you would get with Razor.
  3. They were designed with testing in mind.

One other cool thing I learned is the C# nameof() feature, which can  be used to avoid hard coding class name strings. Usage: i.e. nameof(MyClass) would output “MyClass” as a string.

Conclusion

This event keeps getting better every year. Particlarly, the SQL Server Features and UI Components sessions amazed me! I learned a lot of cool things in this conference, and made note of a lot of things to look into so that I can learn more. Thanks Centare for hosting another great MKE DOT NET!

Creating a dynamic image in Rich Text fields

Have you ever inserted an image, then changed its alt or title tags in the Media Library and noticed that the change does not propagate into the rich text field? It’s because Sitecore only inserts static values into the field HTML when you insert an image. If you’ve ever wanted or needed those images to act dynamically – so that changing alt or title text affects the field HTML -then this article might help you.

The Secret? Tokens!

We can modify the rich text editor dialogs so that when a user inserts Sitecore media, the ALT and TITLE text being sent is actually just a token – i.e. {{alt}}. There is no specific syntax required, just use something that you like. That means that we’re actually inserting “{{alt}}” and “{{title}}” into the field HTML, not the actual (static) values. The goal then is to create a pipeline processor that will read the field and look for those tokens, and replace them with the current values of the Alt and Title fields of the media item.

Customizing the InsertImage dialog

The first thing we will want to do is modify the InsertImage dialog. The InsertImage dialog is a Sitecore dialog, and the source can be found with any Sitecore installation. You would need two files:

  1. The InsertImage.xml file for the dialog, which can be found in the webroot of your site under sitecore\shell\Controls\Rich Text Editor/InsertImage.
  2. The InsertImageForm.cs file (code behind file) which can be extracted from the Sitecore.Client.dll. You can use .NET Reflector, DotPeek, or JustDecompile (I personally use the last one). Look for a Sitecore.Shell.Controls.RichTextEditor.InsertImage entry.

You will want to take these two files and preferably put them in your solution. Place these in a new folder, e.g. Controls/RichTextEditor/InsertSitecoreMediaExtended and make the following changes:

  • Keep the .xml file name the same. In the .xml file, there is a line which points to the code behind file – update that with the location of the file in the solution and the assembly name.
  • Update the name of the .cs file to match the parent folder (InsertSitecoreMediaExtended.cs). In that file, remove everything except the OnOK and SetDimensions methods. You will need to modify the OnOK method so that alt and title are set using tokens:
image.Add("Alt", StringUtil.EscapeQuote("{{alt}}"));
image.Add("Title", StringUtil.EscapeQuote("{{title}}"));

Optional: You can edit the Telerik.Web.UI.Editor.DialogControls.SetImageProperties dialog by adding a title field and checkboxes next to the alt and title fields to make it easier for content editors to specify this option.

Let’s make a new pipeline!

You will want to extend the RenderField pipeline in Sitecore.Kernel, specifically the GetFieldValue processor. So when Sitecore gets the value of the RTE field, we’re going to modify the HTML by swapping tokens for media item values. Create a new folder in your pipelines folder or project named GetFieldValueExtended, and a new class file under it with the same name.

Now you’ll need to tell Sitecore to run your custom processor. There are a few options – patch:before, patch:after or overwrite completely. I personally used the patch:after option. If you choose to overwrite, make sure your processor implements all of the same code as the original. Create a new patch file in the App_Config/Include folder similar to the below. (In my case, the solution has a Processor project.)

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <pipelines>
            <renderField>
                <processor
                    type="MyProject.Processor.RenderField.GetFieldValueExtended, MyProject.Processor"
                    patch:after="processor[@type='Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel']" />
            </renderField>
        </pipelines>
    </sitecore>
</configuration>

In your custom processor class file, set up the Process event with some Asserts and other logic needed before doing the swap. Create the tokens as constants for flexibility. Here is the full code used, which is currently running in a production environment with no issues. I highly recommend HtmlAgilityPack for spelunking in the HTML. (NOTE: The code assumes your production environment Sitecore database is web, which may not be true in your case.)

    public class GetFieldValueExtended
    {
        private const string AltToken = "{{alt}}";
        private const string TitleToken = "{{title}}";

        public void Process(RenderFieldArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            Assert.ArgumentNotNull(args.Item, "args.Item");
            Assert.ArgumentNotNull(args.Item.Database, "args.Item.Database");
            Assert.ArgumentNotNull(args.GetField(), "args.GetField()");

            if (args.Item.Database.Name.Equals("web"))
            {
                if (args.GetField().Value.Contains(AltToken) || args.GetField().Value.Contains(TitleToken))
                {
                    args.Result.FirstPart =  ReplaceTokens(args.GetField().Value);
                }
            }
        }

        private string ReplaceTokens(string fieldValue)
        {
            if (fieldValue.Contains("img") == false) return fieldValue;

            var document = new HtmlAgilityPack.HtmlDocument();
            document.LoadHtml(fieldValue);

            foreach (var img in document.DocumentNode.Descendants("img"))
            {
                var imgSrc = img.Attributes["src"];
                if (imgSrc == null) continue;

                // Remove query string from src (if it exists)
                var mediaUrl = CleanImageSource(imgSrc.Value);

                // Get media item ID based on media url
                DynamicLink dynamicLink;
                if (!DynamicLink.TryParse(mediaUrl, out dynamicLink)) continue;
                MediaItem mediaItem = Sitecore.Context.Database.GetItem(dynamicLink.ItemId,
                    dynamicLink.Language ?? Sitecore.Context.Language);

                // Replace the tokens
                if (img.Attributes["alt"] != null && img.Attributes["alt"].Value.Trim() == AltToken)
                {
                    img.Attributes["alt"].Value = mediaItem.Alt;
                }

                if (img.Attributes["title"] != null && img.Attributes["title"].Value.Trim() == TitleToken)
                {
                    img.Attributes["title"].Value = mediaItem.Title;
                }
            }

            return document.DocumentNode.OuterHtml;
        }

        private string CleanImageSource(string imgSrcValue)
        {
            // First match the SHA1
            var shaMatcher = new Regex("\b[0-9a-f]{5,40}\b");
            var match = shaMatcher.Match(imgSrcValue);

            if (match.Success)
            {
                // Setup media url
                return string.Format("/~/media/{0}.ashx", match.Value);
            }

            return imgSrcValue;
        }
    }

 

Completion

Overall, this was a great feature that the client needed as they tried to make their website ADA compliant, by including the appropriate alt and title text values. I hope this helps you in your Sitecore development adventures.

Razor Template Scripting with jQuery

Recently I discovered template scripting in Razor (not sure what the actual name for it is) and it’s really saved me in some recent projects.  It’s basically a markup template/placeholder inside of a script tag, with dynamic references to model attributes. This lets you render new content onto your page using jQuery’s .render() and .appendTo() functions by targeting the ID of the template.

It starts with a controller action or method. You’ll need to return an instance of the model you’re using or a generic list of instances, depending on your situation. In my case, I made my controller action return a list of items to be added to a grid, if the user clicked a button indicating they wanted to see more items.

Some very basic code:

public ActionResult GetItems(type param1, type param2)
 {
    var itemList = new List<MyModel>();
    itemList = GetNewContent(param1, param2);
    if (itemList.Count < 1)
    {
       return Json(new { success = false }, JsonRequestBehavior.AllowGet);
    }
    return Json(new { success = true, nextItems = itemList }, JsonRequestBehavior.AllowGet);
 }

 The markup looks a little like this:

2016-03-16 14_19_27-SubZero - Microsoft Visual Studio (Administrator).png

Notice the dynamic variables in purple – those are your model attributes, which should exist in the model objects you returned in the controller action.

The JS call:

$('#gridItemTemplate').render(data.nextItems).appendTo('div#subItemGrid');

Because the type of data.nextItems is a list of those model objects, this code knows what those attributes are and how to get them. This will then append the new data based on the template provided, to the element you specify – in my case, a div.

This is a very useful method for rendering markup on the fly using jQuery.

 

Creating a Sitecore Dictionary Parser in Javascript

If you have ever worked on a multi-language site, you know the difficulty of having to make sure every last word is translated correctly. Most of this text may be on your views or web pages in which it is relatively easy to translate. However, when we write scripts for website we implement validation in them, which creates more static text that needs to be translated.

I eventually ran into a situation just like this, where the client requested that pretty much everything be translated correctly depending on the current site language. So I was stuck – how do I grab the value of the French version of a Sitecore item somewhere inside the CMS, from Javascript?

It starts with JSON, which is no surprise. Essentially you need to create a JSON dictionary in a controller method and get all the dictionary items you need, depending on the current site language, then serve that to the view in a tag, which your JS can easily read and interpret. Let’s look at some code.

Step 1: Create a DictionaryItem class (optional).

In my example, I created a DictionaryItem class to make creating the list of dictionary items easier.

public class DictionaryItem
{
   public string Key { get; set; }
   public string Phrase { get; set; }

   public DictionaryItem()
   {
   }

   public DictionaryItem(string key, string phrase)
   {
      Key = key;
      Phrase = phrase;
   }
}

Step 2: Create your controller method.

In your controller, create a public method with a return value of string. It might look something like this:

public string GetJsonDictionary()
{
   // Get a list of all dictionary items.
   var db = Database.GetDatabase(EnvironmentHelper.IsProduction ? "pub" : "web");
   var dictionaryFolder = db.GetItem("your sitecore item id as string");
   var dictionaryItems = dictionaryFolder.Axes.GetDescendants().ToList();
   var condensedDictionaryItemList = new List();

   foreach (var dictionaryItem in dictionaryItems)
   {
      var dict = new DictionaryItem();

      // Get the field value of the item based on the item ID - your implementation may differ
      dict.Key = SitecoreApiHelper.GetFieldValue(dictionaryItem.ID.ToString(), "Key");

      // Get the dictionary item from Sitecore matching dict.Key.
      dict.Phrase = GetDictionaryItem(dict.Key);
      condensedDictionaryItemList.Add(dict);
   }
   var result = JsonConvert.SerializeObject(condensedDictionaryItemList);
   return result;
}

Step 3: Call the controller method from your view.

I dynamically created an object ‘window.ncpDictionary’ for this purpose. In the Html.Action() call, the first parameter is the method name, the second, the controller name (minus “Controller”).

Make sure to make this call before any other calls that depend on it.

@using (Html.BeginScripts())
{
   window.ncpDictionary = @Html.Action("GetJsonDictionary", "NCP");
}

Step 4: Create a Javascript function to get a phrase from the dictionary given the key (and any parameters (optional)). I created a new script for shared functions across an entire section of the project, but this is optional.

function getDictionaryPhrase(key, parameter) { 
   var value = ""; 
   parameter = parameter || ""; 
   if (window.ncpDictionary != null) { 
      window.ncpDictionary.forEach(function (element) { 
         if (element.Key == key) { 
            // TODO: Enhance later to allow multiple parameters. 
            value = element.Phrase.replace('{0}', parameter);
         }
      }); 
   } 
   if (value == "") { return key; } return value; 
}

This code iterates through the dictionary we created in the controller method and checks for the supplied key to the function. If it finds it, send back the phrase (value). You may include a parameter as well; in this case, if your dictionary phrase includes {0}, this will replace it with the supplied parameter, if any.

Step 5: The function call!

Here is an example:

getDictionaryPhrase('please-enter-a-valid-day-01-31'))

Just like that, you’ve created a parser that you can use throughout your website to make sure everything gets translated nicely. Happy Sitecoring.