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!

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.

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

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.

Get a prevalues dropdownlist in Razor (umbraco) for a datatype

by Damiaan Peeters 15. April 2012 19:38

Sometimes you get tired of reinventing the wheel.  Every time I start typing code using the XpathNodeIterator classes I have that feeling.  Every time I search a few minutes for a better solution, but the only solution is the umbraco.library.GetPrevalues()  . 

So I copied the code from there into a .Net class.    I created it as a Razor extention, and copied the values into a dictionary.

namespace MyRazorStuff {
  public static Dictionary<int, object> GetPrevalues(this RazorLibraryCore library, int dataTypeId) {
    XPathNodeIterator preValueRootElementIterator = umbraco.library.GetPreValues(dataTypeId); 
    preValueRootElementIterator.MoveNext(); //move to first 
    XPathNodeIterator preValueIterator = preValueRootElementIterator.Current.SelectChildren("preValue", ""); 
    var retVal = new Dictionary<int, object>(); 

    while (preValueIterator.MoveNext()) { 
      retVal.Add(Convert.ToInt32(preValueIterator.Current.GetAttribute("id", "")), preValueIterator.Current.Value); 
    } 
    return retVal; 
  } 
}

Why does it mean? After I add a using statement to the RazorScript

@using MyRazorStuff 

I can now make a dropdownbox in a razorscript from the datatype prevalues pretty easily:

@{         
  var myvalues = Library.GetPrevalues(GsTehuurTekoopDataTypeId);
  if (myvalues.Count > 0) {
    <select id="ohyeahbaby">
      @foreach (var item in myvalues) {
        <option value="@item.Key">@item.Value</option>    
      }
    </select>     
  }   
}

How about that?  Please share your thought.  Is it wrong to use a dictionary in favor of a XPathNodeIterator?  Should be using a direct database connection much faster?

How to start off with Umbraco v5 (jupiter)

by Damiaan Peeters 13. February 2012 08:30

Searching for some basic information on the new v5? Let me help you out on this one.  I tried to compile a short list of useful resources to get started with the Umbraco v5 RTM.  I’m not digging into the more advanced stuff like trees, custom datatypes, IoC, plugins,…

MVC & Razor

So, you want to start with Umbraco v5. Probably, you already heard some rumors about it. It’s not exactly the same as v4.

You should know about now that V5 is based on ASP.Net MVC.  You can find some basic tutorials on MVC on http://www.asp.net/mvc/tutorials.  Razor is the language expected by the view engine.  Even if you are not a .Net programmer, you should be able to get some results quickly.

My first v5 site by Sebastiaan Janssen

If you like to watch video, there is a 35 minutes video how he created a simple website in v5.

Languages, document types and templates

No nothing changed.  Well, a lot changed, but for languages and document types there are no big changes against v4.  Concerning the “Templates”, you only need to know that the common language is now Razor.  YES!  you can use razor in your template as well.  No need anymore for embedded razor scripts or XSLT macro’s.

Partial views

MacroScripts or partial views… What’s in a name?  Partial views are more MVC-ish, while MacroScripts are for the Umbraco v4 dinosaurs.  Nothing to worry about.  You can just create a partial view in the “Settings” section.

Although you can put everything in partial views you still have the ability to create macros.  The big advantage is that macros can be cached. This can save you precious CPU cycles and database hits.

Umbraco Jupiter has 2 new macro types.  Being Partial View and Surface action.  Shannon Deminick wrote about the new macro types in v5 on the Umbraco blog.  Please note that this is an older article and there is currently no Xslt support or xslt macro in V5. On his own blog Shannon Deminick wrote about Partial View macros.

Permissions

Matt Brailsford wrote a post on permissions in umbraco v5 which is worth reading.

Wiki

Did you know there is an “official” wiki on v5?  It might not be the most complete resource, but it contains very useful and in depth information.  The url is http://jupiter.umbraco.org/AllPages.aspx

Got issues or missing some features?

Report them at http://issues.umbraco.org or view the progress for the upcoming releases on  http://progress.umbraco.org/

Codegarden 12

Last but not least, go to codegarden 12.  The entire conference is dedicated to V5. It is said that it is a wonderful experience to be there.  It’s full of awesome sessions and activities .

You might also want to check out the videos of codegarden 11.  Umbraco v5 was still under heavy development at that time, but there are some interesting videos over there.

Got any other tips?  Post them below!  Or catch me on twitter if you have questions!

How to understand umbraco better

by Damiaan Peeters 3. January 2012 15:37

Lets give this year a good start with some valuable umbraco tips.  We are now working with Umbraco more than a year as the default choice for every web based project we get. These are my findings on how to get to know Umbraco a little better.

Make a website

How difficult can it be. Right?  Just for exercise.  Don’t use a starterkit.  Add document types (and nest them), add templates, content pages, add razor scripts.  Add a blog or photo album package or create your own scripts or even try some XSLT (as long as you can).  Need something more exotic , create your own DataType.  It gives you the feeling of what you could do with just a little bit of imagination.

Get active on the forum

I am not a regulary forum visitor as I would like to be.  But you should be one!

  • you might be able to answer a question someone asks. 
  • If you don’t know the solution by heart, but you know you can find it, then look it up and post the solution on the forum. First of all you just trained yourself and you helped out someone else not as smart as you  Smile
  • Even if you don’t know the answer to an interesting question, maybe an extra question can help.  And you are notified by e-mail if someone else might know the solution

Don’t forget, be friendly.  It’s one of the core elements of the umbraco community. 

Get a video subscription

It sounds crazy but the video’s really helped me out to understand a few basics.  It might get you started on something you didn’t touch before…

Get certified

Begin of April 2011 my and my partner both got certified. She did a level 1 umbraco certification and I am now umbraco level 2 certified. There are too much core parts you should know.  E.g. members, examine, /base, and many other components.  Easy things you might not dare to touch otherwise.

Even if you don’t need it, get the certification.  You help the umbracoHQ financially.

Get into the source.

E.g. so you use the umbraco.library functions. So have you ever seen the source of this library? Have you any idea where it lives? I bet not, if you never looked at the source.

I don’t want you to be searching for a few hours or start decompiling.  Just visit the codeplex website, click the source and navigate to the right branch (4.7.1, …).  A lot of documentation is added to the functions.

Here is e.g. the direct link to the umbraco.library class on the 4.7 release

Create a package and share it

First of all, by creating a package, you need to create something general.  Useful for everyone.  That means you will need to think about how to extend and how to configure your extention.  You will learn a lot from the cavecats other users will post back. 

Complete the wiki

When I started with umbraco, I didn’t understand umbraco at all. The lack of information on the Wiki was enormous. So I insist, if you find an article with missing, wrong or outdated information. You can and should update the WIKI, that is why it’s called a wiki.

Make your own starterkit

Although the existing starterkits are fabulous, I stopped using them.  We created our own mini starter kit with the necessary document types and templates. We added our own razor scripts which we always configure.  It helped us to create new lightweight websites more easily and quickly.  It helps us to spread the word about umbraco.

Go to events

Events are the place to be to meet some friendly people.  To talk about how to work with umbraco.  To get (free) information and find some interesting Umbraco lovers.

Who.I.am

Certified Umbraco Master, Part of Umbraco Certified partner comm-it, .Net and Azure developer, seo lover. Magician in my spare time.

Month List