Bing Maps DataType for umbraco

by Damiaan Peeters 7. October 2013 15:21

Update 2: Also available as a package on our.umbraco.org
Update: made code available on github

When we create websites, we almost always use the excellent Google Maps DataType to let the users update their contact page themselves.  But sometimes, your customer tells you that you can’t use Google Maps.  For political reasons.  Let’s say a Microsoft sponsored website for example.

That’s why I created quickly something that resembles the Google Maps DataType, and I called it “Bing Maps DataType”. It’s not as clean and well build as the GMDT, but I got something. And it works.

Get your key

If you develop public websites using Bing Maps, you need an API key.  To request a free key, go to http://www.bingmapsportal.com, click on “Create or view keys” and create a new key.
A basic key is free of charge for a limited usage amount.

Creating the usercontrol

In the website, I’ve created a usercontrol using a code behind.   This is the code, mainly javascript:

<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="BingMapPropertyEditor.ascx.cs"
Inherits="UserControls_BingMapPropertyEditor" %>
<asp:TextBox runat="server" ID="txtLocation" /> <script charset="UTF-8" type="text/javascript"
src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0"> </script> <script> $(function () { var loc = document.getElementById("<%= txtLocation.ClientID %>").value; var mapOptions = { zoom: 8, credentials: '<%= BingKey %>' }; if (loc !== '') { mapOptions.center = new Microsoft.Maps.Location(loc.split(',')[0], loc.split(',')[1]); mapOptions.zoom = parseInt(loc.split(',')[2]); } map = new Microsoft.Maps.Map(document.getElementById('mapDiv'), mapOptions); // add default pin var pushpin = new Microsoft.Maps.Pushpin(mapOptions.center, { 'draggable': true }); map.entities.push(pushpin); var attachclick = Microsoft.Maps.Events.addHandler(map, 'click', function (e) { if (e.targetType == "map") { map.entities.clear(); var point = new Microsoft.Maps.Point(e.getX(), e.getY()); var loc = e.target.tryPixelToLocation(point); var location = new Microsoft.Maps.Location(loc.latitude, loc.longitude); var pushpin = new Microsoft.Maps.Pushpin(location, { 'draggable': true }); map.entities.push(pushpin); document.getElementById("<%= txtLocation.ClientID %>").value =
location.latitude + "," + location.longitude + "," + map.getTargetZoom(); } }); }); </script> <div id='mapDiv' style="position:relative; width: <%= MapWidth %>; height: <%= MapHeight %>;"> </div>

and this is my codebehind.

using umbraco.cms.businesslogic.datatype;
public partial class UserControls_BingMapPropertyEditor 
: System.Web.UI.UserControl,
umbraco.editorControls.userControlGrapper.IUsercontrolDataEditor { [DataEditorSetting("Bing Maps key", description="get your key on http://www.bingmapsportal.com/")] public string BingKey { get; set; } [DataEditorSetting("Width", defaultValue = "400px")] public string MapWidth { get; set; } [DataEditorSetting("Height", defaultValue = "450px")] public string MapHeight { get; set; } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { txtLocation.Text = value.ToString(); } } public object value { get { return txtLocation.Text; } set { txtLocation.Text = value.ToString(); } } }

Create a datatype

I used the IUsercontrolDataEditor to create a UserControl.  After I dropped the usercontrol in the usercontrols folder, I created a datatype:

image

Language in HTML tag

by Damiaan Peeters 4. September 2013 12:48

According to W3 we should put a language attribute in our HTML tag. I’ve seen a lot of ugly and unmaintainable solutions for putting language tags in the HTML.  With MVC the problem is less

With ugly I mean the following: you don’t want to encapsulate one tag in a macro.  Do you?  As you might know, I hate inline macro’s anyway.

<umbraco:Macro language=”cshtml” runat=”server”>
<html lang=”@Model.Lang”>
</umbraco:Macro>

with unmaintainable I mean:

<html lang=”<umbraco:item field=”lang” runat=”server” recursive=”true”/>”>

You don’t want to allow the user to choose and mistype the language.   Certainly because you already set the culture on the root node?

Set culture on root node

If you haven’t you should.  It’s not difficult.  Right click the home page node, and choose “Manage hostnames”.

image

The best solution?

If you have set the culture on the parent node, you can reuse default “CurrentCulture” ASP.net object to pick up the language.  I’ve added the namespace so that it works for less technical readers, but you could strip that out off course.

<html lang="<%= System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.ToLower() %>">

If you use MVC in umbraco it’s even more readable:

<html lang=”@System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.ToLower()”>

How do you solve this?  Let me know in the comments!

Thread safety and adding items to dictionaries

by Damiaan Peeters 13. August 2013 14:52

I was looking at some code from Zack Owens “Multi Tenancy Sample”.  He has some clever code, a ThreadSafeDictionary with a GetOrAdd method. I love the idea!  (code below for my own reference)

The problem with a dictionary, is that – apparently - .Net puts somewhere a system wide lock to ensure thread safety on a dictionary anyway.  That’s the reason that, if you are working with huge dictionaries with lots of READS, you might bump into some performance issues.  In such cases, you could (and should) use the ConcurrentDictionary from the System.Collections.Concurrent namespace.  And if you are looking at this class, visit the BlockingCollection from the same namespace also, still trying to wrap my head around it, but it is ultra important.  You just feel it when reading through the MSDN article.

   /// DON’T USE THIS CODE – You probably want a System.Collections.Concurrent.ConcurrentDictionary

   using System;
   using System.Collections.Generic;
   using System.Threading;

   /// <summary>
   /// Dictionary that has a "GetOrAdd" method that is thread-safe
   /// </summary>
   /// <typeparam name="TKey">Dictionary key</typeparam>
   /// <typeparam name="TValue">Dictionary value</typeparam>
   public class ThreadSafeDictionary<TKey, TValue> : Dictionary<TKey, TValue>
   {
       /// <summary>
       /// Lock for adding values
       /// </summary>
       private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();

       /// <summary>
       /// Gets a value or adds the value in a thread-safe way
       /// </summary>
       /// <param name="key">Key in the dictionary</param>
       /// <param name="defaultValue">Delegate that will get the value</param>
       /// <returns>Value from the dictionary with given <paramref name="key"/></returns>
       public TValue GetOrAdd(TKey key, Func<TValue> defaultValue)
       {
           // enter read lock
           this.cacheLock.EnterReadLock();

           try
           {
               // test if value is in the dictionary
               if (this.ContainsKey(key))
                   return this[key];
           }
           finally
           {
               // exit read lock
               this.cacheLock.ExitReadLock();
           }

           // enter write lock
           this.cacheLock.EnterWriteLock();
           try
           {
               if (!ContainsKey(key))
                   this.Add(key, defaultValue());
               return this[key];
           }
           finally
           {
               // exit write lock
               this.cacheLock.ExitWriteLock();
           }
       }
   }

Adding the dictionary as a new section in umbraco v4.10+ and v6

by Damiaan Peeters 9. July 2013 16:41

Updating the section area in the backend is not that difficult anymore since the application.config and tree.config files were introduced.

Here is a small HowTo, helping you to put the dictionary as a separate icon in the section area

  1. Open the file /config/application.config and add this line just before the </applications>
    <add alias="dictionary" name="Dictionary" icon="dict.png" sortOrder="7" />
  2. Open the file /config/trees.config and add the following line at the end, just before </trees>
    <add application="dictionary" alias="dictionaryApp" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed=".sprTreeFolder" iconOpen=".sprTreeFolder_o" action="openDictionary()" sortOrder="0" />
  3. Last, add a new icon in the following directory /umbraco/images/tray.  I’ve added a very simple, which you can download and save at the appropriate location.  Save this file as “dict.png”.
    dict
  4. Enable the section for user who needs this separate dictionary section
    To do so, find the user in the users section.  Then mark the checkbox for this dictionary and save.

Did you used the section area for other useful things? 

Tags:

Umbraco

MVC bundling & minification in an Umbraco website (Migrating from MVC Part 2)

by Damiaan Peeters 2. April 2013 13:38

My previous blog post where I explained how easy it is to upgrade your MVC application to an umbraco website, I didn’t mentioned the compilation errors of the @Styles and @Scripts elements in your layout.  These are the bundling & minification features of MVC.

Prerequisite

  1. We have our CSS files from our migration still in the “content” folder.  This means that we will not be able to update the file from the Umbraco backend.  But for now: “we don’t care”.  This migration had to be done.  Knipogende emoticon
  2. still have the App_Start folder with your previously used by MVC.  This folder contains your bundling script.

Install optimization using nuget

I allowed the installation of the umbraco nuget packages to overwrite my web.config.  Therefor the optimization package was not working anymore.  The easiest to solve this issue, was just to remove and add the package again.  I’m not going into how this is done.  All you guys now this better than I do.  If not, I’ll read it in the comments, and I’ll be glad to help you out.  That being said: launch this from the Package Manager console:

Remove-Package Microsoft.AspNet.Web.Optimization
Install-Package Microsoft.AspNet.Web.Optimization

Register the bundle config on application startup

You can just keep your MVC bundling & minification features by simply registering this on the application startup. We are reusing the MvcStartup class from our previous post. 

Adding this to the “started” event: 

BundleConfig.RegisterBundles(BundleTable.Bundles);  

You should be able to find the BundleConfig class in your App_Start folder.

Update Web.config

Add the “~/Content/” path to the umbraco umbracoReservedPaths in the web.config.

<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/Shop/,~/Content/"/>

Add @Styles to your View

@Styles.Render("~/Content/css")

You will need to add @using System.Web.Optimization to your view where you use the @Styles or @Script tags. 

I haven’t tried it adding the namespace to the web.config yet, but I guess that will work.

Convert MVC application to Umbraco v6 using Custom Routes

by Damiaan Peeters 29. March 2013 18:53

We have this basic web shop for alternative music, once build in MVC.  However the customer asked to have more freedom to edit pages and content.  Being a Umbraco adept, we had no other possibility to move to Umbraco. 

Instead of rebuilding everything we looked at our possibilities.

  • Create a sub domain: http://shop.mydomain.com an put the shop on the subdomain.
    That would mean we have 2 projects in our Visual studio solution.  It would work very quickly, but we will be struggling with showing logged in users across the different domains.
  • Create a application folder: http://www.mydomain.com/shop/ .  This would enable us to continue to work as we are busy.  But we would need to maintain 2 different layouts.
  • Create an Umbraco website and copy some “legacy” MVC code to the new site. 
  • Add Umbraco to the MVC application using NuGet.  

In the past we already tried the first 2 solutions, and you always have some issues when upgrading 1 site, but forgetting to upgrade the latter.  The third solution was not as easy as we stumbled in compilation issues whole the time.

DISCLAMER: We are trying to get somewhere as quick as possible.  We are taking shortcuts.  Throwing best practices over board. 

The MVC implementation for Umbraco

The MVC for umbraco in the documentation introduces new concepts which might take some time to understand.  You have thinks like surface controllers and custom controllers, …  The question was: do we convert all controllers to custom controllers.  Do we create special document types?  Do we need to move our views.

We needed a “quick & dirty” solution.  Time is money.  And customers tend not to have endless budgets.  All these nice things do not enable you to do a fast migration to Umbraco.  When rebuilding a complete site, we could have done it with all the MVC customized Umbraco goodness like custom & surface controllers.  But for now we decided to move our shop to an MVC Area.

It was the blog post of Aaron about MVC in Umbraco 4, which set us in the right direction.  What we will be describing here was already in the documentation: Custom MVC Routes.  Only a little bit more condensed.

Here is our step by step guide…

Prepare your MVC app

First we started moving all our controllers & Views to an area.

image

It’s not too hard.  Move the Controllers, views and Models.  (Update the namespaces.).  We left the _layout.cshtml in the /Views/Shared folder for now.

Verify that you don’t have any special routes or configuration in your global.asax.  The global ASAX will be skipped by umbraco.  We will explain further how to run this code anyway.

Add umbraco to the solution

Right click references in the MVC application and choose “Manage NuGet Packages

image

And install the “Umbraco CMS” NuGet Package.  The “umbraco CMS core binaries” will be automatically added.

image

Or use the Package Manager Console if you wish too.

 

 

Update Web.config

We added our MVC Area (“Shop”) to the umbracoReservedPaths in the Web.config. 

<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/Shop/"/>

Register your MVC Area using custom routes.

Add a new class. Where you attach the startup handlers for MVC.  For consistency I added this file in the App_Start folder. 

The class should implement the IApplicationEventHandler interface or use the umbraco v6 ApplicationEventHandler class.  Add the MVC Area registration to the application started event.   Or add your custom routesto controllers if you don’t want to use areas (but don’t forget to update your appSettings umbracoReservedUrls).  This class will be picked up by Umbraco automatically on startup of the application.  It kind of replaces the global.asax.

using System.Web.Mvc;
using Umbraco.Core;
 
public class MvcStartup : IApplicationEventHandler 
{
    public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
 
    }
 
    public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        AreaRegistration.RegisterAllAreas();
    }
 
    public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
 
    }
}

 

Don’t forget to add or rework any other special code you had in the global.asax before starting the “upgrade” to umbraco. 

setup your umbraco as usual

  • Open the root and setup the database
  • Set MVC as your “defaultRenderingEngine” in umbracoSettings.config.

Taking your solution one step further

For now, be happy and don’t try to take this “further”. 

If you want to use your existing _Layout.  You will quickly see that you can inherit your _layout Shared View from UmbracoTemplatePage like this:

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage

This will throw compilation errors because you are probably returning custom objects!  Solving this issue would be beyond the scope of our simple solution.  If we ever get into this direction, we will take care to put up a new blog post about our path.

Enjoy, you are running your Custom MVC route in umbraco!

So that’s it.  What is your experience with upgrading MVC to umbraco?  Did you took the same approach?  What would (or have) you done to merge umbraco into your existing MVC applications?

One small last note:  special thanks to Raoul Jacobs for going through this together.

How to install a FREE startssl certificate on your IIS 7.x

by Damiaan Peeters 12. March 2013 22:32

Updated 2013-06-17: Added information about bindings when hosting multiple sites

---

Today I had to install a renewed certificate for a HTTPS web server.  Here are the steps I followed.

Create (or reauthenticate) your account

  • go to https://www.startssl.com/ and authenticate (or sign-up or use the express lane button).
  • This process involves entering a authentication code send to your e-mail address. 
  • Follow the procedure, everything is pretty straightforward.  Don’t forget to backup your certificate which is installed in your browser.  If you reinstall your pc, you will need this certificate to gain access to your account.

Do e-mail validations first

The first catch.  If you want to create a certificate for another domain.
First do a “email address validation” in the validations wizard for the domain you will be creating a certificate for.  If you want to create a certificate for domainxyz.com, then first do an email validation for postmaster, hostmaster or webmaster@domainxyz.com.  For the .com TLD you might have other possibilities also. 
If you did not validated this e-mail address, you won’t receive any verification codes on this e-mail address.

Create a certificate

If you follow all instructions on the “certificates wizard”.  If you let startssl generate your private key, you should have a at least the following files at hand

  • ssl.key (the encrypted private key)
  • ssl.crt (the certificate or public key)

The SSL.crt could be used on a windows server, but that would be only the public key.  For HTTPS you also need the private key, because you need to decrypt the encrypted data.  So you will need to link the private key and the certificate together as we will describe in the next steps. 

Decrypt private key

First go to the toolbox and click the “decrypt private key”.

image

Paste in the content of the ssl.key file, enter your password which you provided in the previous step.

You now have a DECRYPTED private key.  Copy this decrypted key.

Create Certificate for IIS

Now go to “Create PKCS#12” in the toolbox.  Paste the decrypted key in the first box (private key).  And paste the content of the ssl.crt file in the second box.  Provide a new password to protect the file you will be creating.

image

Click continue.

image

Now download the PFX and use this file to install the certificate on your IIS 7.0/7.5 or higher.

Install the certificate

Open Inetmgr (Internet Information Services – IIS Manager) and open the “server certificates” on server level.

image

Click the “IMPORT” button and supply the PFX you just created (and uploaded?).  You might not have the right file extension, but that is no problem.  Just choose *.* as file type, select the file.  Finish off with your password, before hitting return.

Redefine bindings of website

If you have only one HTTPS site running Go to your HTTPS site,

  • click “Bindings”
  • “Edit” the https (port 443) line
  • choose the right SSL certificate
  • hit “OK”,
  • and click the “Close” button

image

Bindings when hosting multiple sites

If you have multiple sites running on your website, you might want to set the binding headers for HTTPS.  This can be done using the command prompt (as administrator) using these two commands:

C:\Windows\system32>cd \windows\system32\inetsrv
C:\Windows\System32\inetsrv>appcmd set site /site.name:"<THESITENAME>" /+bindings.[protocol='https',bindingInformation='<MYIPADDRESS>:443:<WANTEDHOSTNAME>']

 

change the "<THESITENAME>", "<MYIPADDRESS>", "<WANTEDHOSTNAME>" to approprate value's.

Verify

If you want to verify that the certificate is there, open certmgr.msc

image

Hope it helped  Glimlach

UPDATE:

If you want to add the certificate to an existing site, you might want to find out the APP id using :

netsh http show sslcert

so that you can add the certificate manually to the existing website  (you can find the cert hash using the "server certificates" in IIS)

netsh http add sslcert ipport=0.0.0.0:443 certhash=baf9926b466e8565217b5e6287c97973dcd54874 appid={ab3c58f7-8316-42e3-bc6e-771d4ce4b201}

need integration with AD?

by Damiaan Peeters 10. February 2013 10:44

add the AD membership provider to the web.config

<add name="ADMembershipProvider" type="System.Web.Security.ActiveDirectoryMembershipProvider, System.Web, Version=2.0.0.0,Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />

<add name="ADConnectionString" connectionString="LDAP://server001/DC=comit,DC=local" />

change in umbracoSettings.config

  <providers>
    <users>
      <!-- if you wish to use your own membershipprovider for authenticating to the umbraco back office -->
      <!-- specify it here (remember to add it to the web.config as well) -->
      <!--<DefaultBackofficeProvider>UsersMembershipProvider</DefaultBackofficeProvider>-->
      <DefaultBackofficeProvider>ADMembershipProvider</DefaultBackofficeProvider>
    </users>
  </providers>

Tags:

Umbraco

Download all nuget packages to your local server using powershell

by Damiaan Peeters 21. January 2013 09:02

Some time ago I found this script to download the nuget Packages to you local server.  Just for a reference I’ll put it the blog. They way I run this is using the Windows Powershell ISE.

image

I don’t remember where I got the link from.  But I do know when.  That was when nuget was out and I had no way of retrieving missing packages.  Since then, I run this script to our local NAS from time to time.

The Powershell Source

# --- settings ---
$feedUrlBase = "http://go.microsoft.com/fwlink/?LinkID=206669"
# the rest will be params when converting to funclet
$latest = $true
$overwrite = $false
$top = 1500 #use $top = $null to grab all or a number to get TOP 500 packages
# $destinationDirectory = join-path ([Environment]::GetFolderPath("MyDocuments")) "NuGetLocal"
$destinationDirectory = "L:\TEMP\NuGetLocal"

# --- locals ---
$webClient = New-Object System.Net.WebClient

# --- functions ---

# download entries on a page, recursively called for page continuations
function DownloadEntries {
param ([string]$feedUrl)
$feed = [xml]$webClient.DownloadString($feedUrl)
$entries = $feed.feed.entry
$progress = 0
           
foreach ($entry in $entries) {
    $url = $entry.content.src
    $fileName = $entry.properties.id + "." + $entry.properties.version + ".nupkg"
    $saveFileName = join-path $destinationDirectory $fileName
    $pagepercent = ((++$progress)/$entries.Length*100)
    if ((-not $overwrite) -and (Test-Path -path $saveFileName))
    {
        write-progress -activity "$fileName already downloaded" `
                       -status "$pagepercent% of current page complete" `
                       -percentcomplete $pagepercent
        continue
    }
    write-progress -activity "Downloading $fileName" `
                   -status "$pagepercent% of current page complete" `
                   -percentcomplete $pagepercent

    [int]$trials = 0
    do {
        try {
            $trials +=1
            $webClient.DownloadFile($url, $saveFileName)
            break
        } catch [System.Net.WebException] {
            write-host "Problem downloading $url `tTrial $trials `
                       `n`tException: " $_.Exception.Message
        }
    }
    while ($trials -lt 3)
  }

  $link = $feed.feed.link | where { $_.rel.startsWith("next") } | select href
  if ($link -ne $null) {
    # if using a paged url with a $skiptoken like
    # http:// ... /Packages?$skiptoken='EnyimMemcached-log4net','2.7'
    # remember that you need to escape the $ in powershell with `
    return $link.href
  }
  return $null
}

# the NuGet feed uses a fwlink which redirects
# using this to follow the redirect
function GetPackageUrl {
param ([string]$feedUrlBase)
$resp = [xml]$webClient.DownloadString($feedUrlBase)
return $resp.service.GetAttribute("xml:base")
}

# --- do the actual work ---

# if dest dir doesn't exist, create it
if (!(Test-Path -path $destinationDirectory)) {
    New-Item $destinationDirectory -type directory
}

# set up feed URL
$serviceBase = GetPackageUrl($feedUrlBase)
$feedUrl = $serviceBase + "Packages"
if($latest) {
    $feedUrl = $feedUrl + "?`$filter=IsLatestVersion eq true"
    if($top -ne $null) {
        $feedUrl = $feedUrl + "&`$orderby=DownloadCount desc&`$top=$top"
    }
}

while($feedUrl -ne $null) {
    $feedUrl = DownloadEntries $feedUrl
}

Umbraco and embedded macro scripts

by Damiaan Peeters 11. January 2013 08:58

It is possible to use Embedded macro scripts in master pages.  You know:

<umbraco:Macro runat=”server” language=”cshtml”>
    @Model.Name
</umbraco:Macro>

I’ve seen a lot of these chunks of code in masterpages.  Although you might LOVE Razor, there is no reason for you to do this!   

First of all, you could solve the previous line simple with a <umbraco:Item /> tag in your master page.  Secondly, Umbraco released version 4.10 with MVC capabilities. So you don’t need to use the Masterpages anyway.  Do you? Thirdly, u can still use inline code.  I know the documentation says it’s not a recommended way, but it’s fast and for easy master page related things I think perfectly fine. <% if(condition) umbraco.NodeFactory.Node.GetCurrent().GetProperty(…).Value %> This doesn’t involve a creation overhead for each Razor macro which is being called.

But here are my personal reasons why I don’t like them:

  • Visual studio problems: if coding embedded macro’s in visual studio you have
    • no intellisense
    • bad syntax highlighting
    • impossible errors & bizar warnings
    • automatic formatting shortcut screws up everything. In VS, you can use CTRL + K , CTRL + D to format your code automatically. Your embedded macro’s will probably screws up regularly.
  • Hard(er) to configure cache parameters.  Did you ever tried to cache by page or by member?
  • Having to macro’s running next to each other:

    </umbraco:Macro>
    <umbraco:Macro runat="server" language="cshtml">
  • You can’t set a break point and really DEBUG what might be going wrong in your code.
  • When you ARE debugging
    • you end up in separate files and you do not know which masterpage you are exactly debugging
    • you can and will change - by accident – temporary generated razor scripts

Most of the time I use these rules on how we use Razor Macro’s in Umbraco:

  • Create separate files in the MacroScripts folder. 
  • If performance is importance convert Model to DynamicNode instead of working with DLR objects
  • Add @Inherits & @using umbraco.MacroEngines  to optimize Visual Studio Experience
  • Use Helpers where possible
  • Extend @Library or create own extensions in App_Code or even better: a custom .Net dll with your code precompiled
  • Choose between @umbraco.library.GetDictionaryItem(“theDictKey”) and @Dictionary.theDictKey and don’t use both.
  • Follow coding standards which are normally applied in normal .Net code.  For razor I prefer { on the same line (see post of scottgu introducing Razor).  But don’t mix!
  • If you really need an embedded macro and want a break point, use  @{                System.Diagnostics.Debugger.Break(); }

Oh.  And check out the umbraco development guidelines on our, they are there for you to read.

What do you think?  Do you agree?  What are your best practices for umbraco and Razor macro’s.

Who.I.am

Certified Umbraco, .net and Azure developer, seo lover. Magician in my spare time.

Month List