uhang-585

 

I finished of last week by participating in Warren Buckley's lovely uHangout. This time I showed my latest package “The Dashboard” which also won this years package competition on CodeGarden 15. The package is a really simple dashboard that can be used to give both editors and developers a better first experience when the log on to their Umbraco backoffice. This is how it looks:

 

635698726453441911_thedasboardpng

 

Please Download The Dashboard and give it a spin! If you would like to contribute (or just leverage the source code) the project is hosted on GitHub: https://github.com/enkelmedia/TheDashboard

 

Our conversation also evolved into an overall discussion about the editor experience in Umbraco CMS and how you as a developer can improve it.

 

If you want to watch the show it on http://uhangout.co.uk/ or on YouTube: https://www.youtube.com/watch?v=fNoHxYSuBXo

 

I’ll try to post a summery of the tips and tricks and the packages that I talk about in the upcoming days.

 

Cheers! =D

Since Visual Studio 2013 update 2 VS includes a nice Json editor that makes is easier to edit files containing json data. By default this editor is only used for .json-files and since the json-formated package.manifest-file used to create new plugins for Umbraco has the manifest-extention Visual Studio won’t add any syntax highlighting.

 

This is easy to fix.

 

1. Go to Tools / Options

2. I the left menu click on Text Editor and then File Extention.

3. Write “manifest” in the upper left text box, choose JSON Editor in the dropdown and click on Add.

4. Hi OK, open your manifest file and – ta da!

 

Vs -manifest -extention

 

PS. If you like the screen recorded GIF (I do) check out this awesome project: https://screentogif.codeplex.com/

 

swetugg

 

February 2-3 next year the Swedish .NET User Group (SWENUG) will host a two day .NET-conference in Stockholm, Sweden.

 

Topics varies around the .NET-space and  I’ve got the honor to speak about Umbraco CMS. I’m planning to do a very short basic intro about Umbraco and then dive into how to extend the editor environment using AngularJS. My experience from showing Umbraco to new users is that the Angular-based property editors really impresses people. My hope is that this session will help to further grow the Umbraco community here in Sweden.

 

If you would like to join, tickets only costs 500 SEK, read more at swetugg.se

 

swetugg-speaker

As long as I can remember Umbraco has shipped with a set of presets for the url replacing feature. This is the feature that takes the node name and turns it into a valid url. These presets lives in the /config/umbracoSettings.config-file and used to look something like this.

 

<urlReplacing removeDoubleDashes="true">
   <char org=" ">-</char>
   <char org="""></char>
   <char org="."></char>
   <char org=";"></char>
   <char org="/"></char>
   <char org=":"></char>
   <char org="+">plus</char>
   <char org="*">star</char>
   <char org="&"></char>
   <char org="?"></char>
   <char org="æ">ae</char>
   <char org="ø">oe</char>
   <char org="å">aa</char>
</urlReplacing>

 

In later versions of Umbraco (I think since Umbraco 7) the urlReplacing element has been removed from the default umbracoSettings.config-file and the presets are hidden. At CodeGarden14 this year I learned very much from Stephans session about the core internals of Umbraco (Slides: http://www.zpqrtbnk.net/CoreInternalsForWebsiteDevelopment.pdf) one thing was the toAscii-property of the urlReplacing-element. Since there is hundreds of different chars that you might want to replace and it’s very likely that you’ll miss some – that why they have included this great little flag. So all the configuration above can be replaced with this simple line:

 

<requestHandler>
  ....
    <urlReplacing toAscii="true" />
</requestHandler>



I had that question in mind when I was working with a new MVC-site using Umbraco 7 and wanted to share my conclusions. Well after some googling I found this great blogpost from the Umbraco core-developer Shannon Deminick. It’s related to Umbraco 5 (RIP) but the concept still applies to the MVC-implementation in Umbraco 7 (and 6), in one of the comments he explains the difference.

So. This is the thing.

Use return CurrentUmbracoPage()

When you just want to return the current page. Here you can use the ViewData and ViewBag object to pass data from the controller to the view and that will work just fine. Generally you want to return to the current page if you want to keep the POST-data that was sent to the controller.

Use return RedirectToCurrentUmbracoPage()

When you really want to redirect the user. Shannon’s writes: “If your POST is successful, you shouldn't just return a response, you should redirect to a page so you can avoid the aweful issue of having a user press refresh and have it resubmit the POST”. To pass data back to the view you’ll need to use the TempData-object that will “survive” the redirect.

So if you’re creating a form and the model state IS valid, you should perform your actions and RedirectToCurrentUmbracoPage(), if the model is not valid you should just return the CurrentUmbracoPage(). That’s why many examples looks like this:

if(!ModelState.IsValid)
   return CurrentUmbracoPage()
// do stuff here
return RedirectToCurrentUmbracoPage()

Another thing to notice about the routing is “Just FYI, when you POST to a SurfaceController, you are just posting to your own controller which is outside of the Umbraco process, it is just a very normal MVC post. So when you do a return CurrentUmbracoPage call, that then passes execution back to Umbraco to go lookup the page that was posted from and renders it. You could in theory just return your own View(model) which will be completely outside the umbraco process, because it is just an MVC normal controller.

Thanks Shannon for making this clear! #h5yr

I’m working on a web application where I’m using the great mirco orm PetaPoco for my data access. Is a really great and super fast ORM that works with SQL Server, SQLCE. MySQL and more.

I’m not gonna cover the basics of PetaPoco in this blog post so if you have not worked with it please read the introduction from TopTen Software.

Now. In this solution we where working with stored procedures (SP) in the SQL Server which is quite simple with PetaPoco, to execute a SP called OutputDemo with two parameters, just write

 

var sql = Sql.Builder.Append(";EXEC OutputDemo @0, @1, "Markus",29);

 

So that's easy. But what if we need to grab some output parametersfrom the sp as well? That took me some more work to figure out. I googled a lot on the subject and there was not really any good recourse so i figured i had to share my solution.

First, let’s look look at the stored procedure that I’ve created for this demo

 

CREATE PROCEDURE [dbo].[OutputDemo]
    @name varchar(50),
    @age int,
    @resName varchar(50) OUTPUT,
    @resAge int OUTPUT
AS
SET @resAge= @age + 10
SET    @resName = 'Name: ' + @name   


A super simple sp that will set the values of the output parameters depending in the value in the input parameters for name and age. So the resAge-output parameter will have the value of the inputted age plus 10, and the resName-output parameter will just be prefixed with “Name:”.

Now. To use this and to get the values back from the query there is couple of thing we need to do. First we need to create variables that holds the returning values from the output parameters.

 

var opName = new SqlParameter("@resName", SqlDbType.VarChar);
opName .Direction = ParameterDirection.Output;
opName .Size = 50;

var opAge= new SqlParameter("@resAge", SqlDbType.Int);
opAge.Direction = ParameterDirection.Output;
opAge.Size = 20;

 

This is regular SqlParameters – I’ve just ignored the fact that this would “tie” me to SQL Server since my SP’s are created in SQL Server is just don’t care about this dependency. The important thing to notice is the Direction and the Size-properties that both are mandatory. Next wee need to create the query:

 

var s = Sql.Builder.Append(";EXEC OutputDemo @0, @1, @2 OUTPUT, @3 OUTPUT",
           "Markus",
           29, 
           opName ,
           opAge
          );

 

As you see here I’m adding the word “OUTPUT” after each variable for the output parameters – this tells the ADO.NET and PetaPoco that these variables should be populated with the return values of the output parameters.

 

So with this code executed the value of opName should be “Name: Markus” and opAge should be 39. Here’s the complete code:

 

      var opName = new SqlParameter("@resName", SqlDbType.VarChar);
       opName .Direction = ParameterDirection.Output;
       opName .Size = 50;
       var opAge= new SqlParameter("@resAge", SqlDbType.Int);
       opAge.Direction = ParameterDirection.Output;
       opAge.Size = 20;
       var s = Sql.Builder.Append(";EXEC OutputDemo @0, @1, @2 OUTPUT, @3 OUTPUT",
          "Markus",
          29, 
          opName ,
          opAge
         );
       new Database().Execute(s);


     

Yesterday I was listening to my favorite podcast .NET-ROCKS and heard about Troy Hunts great Azure demo - not not just a great demo - it's The world's greatest Azure demo, just wanted to share it here as well:

 

Since version 7.1 of Umbraco was released the core now contains a great image cropper. Not only that. It also contains a great image processing library called ImageProcessor written by James South (@james_m_south).

 

The image cropper in Umbraco 7 is really a piece of art based on the CropUp-package from Umbraco-genius Niels Kühnel (@nielskuhnel). The big “news” with the cropper is something called a “focal point” that the editor can set. When this point is in place Umbraco is smart enough to figure out any crop based on this point. This means that you don’t have to force the editor to make 20 different crops, they can just set the focus point and the different crops will be generated. We’re going to explore this more in this post and I'll show you how to quickly set up the image cropper and render the cropped image on the front end of your website.

 

Newsletter Studio -banner -580x 250

Here is how you do

 

1. Set up the data type in the developer-section of Umbraco 7. Right click data types and create a new data type. Let's call it "Image Cropper".

 

2. Just as with the cropper from earlier versions of Umbraco we now need to set up one or more crops. Let's just use a simple crop of 120x120 px.

imagecropper-datatype

 

3. Next, we need to add this data type to one of our document types. Let’s go and do so in the settings-section. I’m giving my new property the name “image” but you can choose what ever name that suites you’re solution.

 

imagecropper-doctype

 

4. Now let’s upload an image and set the focus point by dragging the blue dot to the part of the image that we want to focus on. Let’s don’t create any special settings for the 120x120 crop that we created – just hit “Save and publish”.

 

imagecropper-image

 

5. Let’s go to the settings-section and open the view/template for the document type that we’ve added the image cropper to. To render the crop in on the page we need to use a method called GetCropUrl() from the IPublishedContent-type in Umbraco. Let’s add this code the view and load the page in the browser.

 

<img src="@Model.Content.GetCropUrl("image", "normal")" />

 

The first parameter is the alias of the property and the second is the name of the crop, this should look something like this.

 

imagecropper-croppedimage

 

6. As you can see Umbraco 7 created a crop based on the focus point that we provided. To prove that this really works, let’s ignore the “normal” crop and set the width and height in the method call.

 

<img src="@Model.Content.GetCropUrl(propertyAlias:"image", width:300, height:100)" />

 

This will generate an image that’s 300x100 pixels, still with the face in focus

imagecropper-croppedimage2

 

7. Now, let’s try to move the focal point and look at the resulting crop

imagecropper-movedpoint

 

 

8. But, if we don’t like the default crops that Umbraco generates we can of course change them to look exactly like we want. Update the view-code to use the “normal” crop again and open the node with the crop back to the content-section. Click on the little thumbnail under the big picture, in the dialog that appears. Drag the slider to zoom and drag in the picture to adjust the part that you want to keep in the crop – click the “cross” in the upper right corner to save the custom crop beforeyou click save and publish.

 

 

imagecropper-customcrop

 

 

9. Going back to our view and refreshing the page will show our new crop

 

imagecrop-customcropfrontend 

 

 

The GetCropUrl()-method has a lot of properties that’s optional like width, height, quality, useCropDimensions, cacheBusterValue, ratioMode, upScale – see the source code of Umbraco 7 for more info on what they all means.

 

Hope you enjoy the new image cropper in Umbraco 7, follow this blog for most posts about Umbraco and please also follow me on twitter: @enkelmedia.

Tip: Looking for a integrated newsletter solution for Umbraco? Check out Newsletter Studio - sends newsletter from directly from the Umbraco backoffice.

 
Newsletter Studio -banner -580x 250

 

 

 

IMG_3739

 

It’s been a little more than a month since Umbraco 7 was released and it feels like a great timing that we announced new dates for Umbraco training in Stockholm, Sweden. Just like last time the course will be in Swedish but the course material (slides and workbook) is in English.

 

Please read more about the training here: /vi-erbjuder/utbildning-umbraco.aspx (in Swedish)

One requirement of Enkel Medias Umbraco-package Newsletter Studio is to render and use the built in rich text editor from Umbraco (TinyMCE) in the custom Newsletter Studio-section.

 

Newsletter Studio -banner -580x 250

 

TinyMCE in a custom Umbraco 7-section

 

image

Since the backoffice of Umbraco 7 is rebuilt using AngularJS all property editors are built using JavaScript and they also rely on the current AngularJS-scope to contain some information on how to render the control. So in order to render our rich text editor (rte) we need to provide this information.

There are some different ways to render the control, some are more “hacky” than others and I’m going to walk you through some options. Just to be clear –this is not a best practice guide for JavaScript so I’ve added the JavaScript controllers in script-elements inside the views. This is something that you should not do, they should live in their own .js-files – but for simplicity I ignore that in this blog post.

Option 1 –Copy the original view

The first option is to just copy the code from the original rte-view (from the Umbraco source code). It looks something like this:

<div ng-controller="Umbraco.PropertyEditors.RTEController" class="umb-editor umb-rte">
    <textarea ng-model="model.value" rows="10" id="{{model.alias}}_rte"></textarea>
</div>

This is super simple. But it won’t work. Since Umbraco loads information about all the tabs, content, property types, values and so on for a content page when it’s loaded the RTEController assumes that the current scope has all this information. So we need to simulate that with our own controller. Let’s change the view so it looks like this:

<div ng-controller="CustomSectionEditController">    
    <ng-form>
        <div ng-controller="Umbraco.PropertyEditors.RTEController" class="umb-editor umb-rte">
            <textarea ng-model="model.value" rows="10" id="{{model.alias}}_rte"></textarea>
        </div>            
        <pre>
            Value from the RTE {{model.value}}
        </pre>
    </ng-form>
</div>

And for this code we need a controller called “CustomSectionEditController”, let’s just add a simple version of this controller:

<script type="text/javascript">
    function CustomSectionEditController($scope) {

        $scope.model = {
            alias: 'myRichtexteditor',
            config: {
                editor: {
                    toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                    stylesheets: [],
                    dimensions: { height: 400, width: 250 }
                }

            }
        };
    }
</script>

With this code in place the rich text editor (rte) should be rendered and the HTML from the editor will be populated into the $scope.model.value-property.

While this works it’s not so very flexible and another problem is that it will be hard to “lazy load” properties, values and settings since the rendering of the rte-controller could start before all your data has been downloaded.

Option 2 – Use the umb-editor directive

In the views in Umbraco all the property editors are loaded dynamically the view for editing content only uses this simple tag:

<umb-editor model="myProperty"></umb-editor>

Umb-editor is a Umbraco-specific AngularJS directive that will look at the model attribute to find out which $scope-property to use for getting rendering information, in this case it’s $scope.myProperty – so let’s add that:

<script type="text/javascript">
    function CustomSectionEditController($scope) {
        $scope.myProperty= {
            label: 'bodyText',
            description: 'Load some stuff here',
            view: 'rte',
            config: {
                editor: {
                    toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                    stylesheets: [],
                    dimensions: { height: 400, width: 250 }
                }
            }
        };
    }
</script>

As you can see with this code the $scope.myProperty.view property is called “rte” which tells AngularJS to load the rte (rich text editor)-view as the current view for this umb-editor. If we were to set $scope.myProperty.view to ‘textbox’, a textbox would be loaded. Updating the view to look like this would get this code to run:

<div ng-controller="CustomSectionEditController">    
    <ng-form>
        <umb-editor model="myProperty"></umb-editor>      
        <pre>
            Value from the RTE {{myProperty.value}}
        </pre>
    </ng-form>
</div>

This is a little bit cleaner than the approach in option 1 but we still suffer from the problem that the directive could be processed before we have loaded all our external data. For example – we would probably like to set the $scope.myProperty.value to some value that's loaded from the backend –but with this approach the directive could be processed before that data is downloaded and we’ll be left with a ugly error message.

Option 3 – Use ng-repeat and an array to “lazy load”

As far as I have seen this is the best way to load data from the backend and then render the wysiwyg-editor. In my use case I want to have a specific data type configured and when the page loads I want to get the configuration (pre values) for that data type and put that data in $scope.myProperty.config. I also want to download some content from the backend and put that in $scope.myProperty.value.

So – How do we avoid the directive from being processed before the data is loaded? A loop. Let’s put this in our view

<umb-property 
    property="property"
    ng-repeat="property in properties">
    <umb-editor model="property"></umb-editor>
</umb-property>

And then put an array of properties on the scope:

$scope.properties = [{
                        label: 'bodyText',
                        description: '',
                        view: 'rte',
                        config: {
                            editor: {}, // empty for now
                            hideLabel: true
                        }, hideLabel: true
                    }];

This would look almost the same as option 2 but. Since the ng-repeat attribute is there the directives will be reprocessed each time the $scope.properties-property change and since $scope.properties is null until after the data is downloaded the umb-editor directives will note be loaded.

The full view could look something like this:

<div ng-controller="CustomSectionEditController">    
    <ng-form>
        <umb-property 
            property="property"
            ng-repeat="property in properties">
            <umb-editor model="property"></umb-editor>
        </umb-property>
        <pre>
            Value from the RTE {{properties[0].value}}
        </pre>
    </ng-form>
</div>

And the controller like this:

<script type="text/javascript">
    function CustomSectionEditController($scope) {
        $scope.property = {
            label: 'bodyText',
            description: 'Load some stuff here',
            view: 'rte',
            config: {
                editor: {
                    toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                    stylesheets: [],
                    dimensions: { height: 400, width: 250 }
                }
            }
        };
    }
</script>

Now the last step would be to make sure that the text-value for the editor is fetched from some backend service.

<script type="text/javascript">
    function CustomSectionEditController($scope, $http) {
        $http({ method: 'GET', url: '/url/to/our/cool/service' })
            .success(function (data) {
                $scope.property = {
                    label: 'bodyText',
                    description: 'Load some stuff here',
                    view: 'rte',
                    config: {
                        editor: {
                            toolbar: ["code", "undo", "redo", "cut", "styleselect", "bold", "italic", "alignleft", "aligncenter", "alignright", "bullist", "numlist", "link", "umbmediapicker", "umbmacro", "table", "umbembeddialog"],
                            stylesheets: [],
                            dimensions: { height: 400, width: 250 }
                        }
                    },
                    value: data
                };

            })
            .error(function () {
                $scope.error = "An Error has occured while loading!";
            });
    }
</script>

As you can see we added the $http-parameter to the controller and uses it to fetch the data that we need before assigning the values to the scope. This will prevent the umb-editor directive from starting to load before all our data is loaded.

This is how I’ve solved the this issue at the moment and there may be other ways as well, please feel free to post questions or comments here below.

Cheers!