SlideShare a Scribd company logo
1 of 33
Razor Revealed
Jeavon Leopold | Twitter: @crumpled_Jeavon
We are Crumpled Dog
You are on page 222/01/2015
I have been working with Umbraco since version 3.0 (circa 2007)
• Technical Director at Crumpled Dog – Umbraco Gold Partner
in London’s TechCity/Silicon Roundabout
• Umbraco MVP – Honoured to be voted by the global
community as one of the five 2104 MVPs
• Umbraco Community Member – I am known for answering
many questions in the Razor forum and have 7,500 karma
• Umbraco Core Contributor– I have made many bug fixes and
even added a few features here and there over the years.
Most recently I worked with Per Ploug Hansen and James
South on the v7.1 Core Image Cropper API
• Umbraco Package Hacker – I have created a few packages
of my own and collaborated on many more
Who am I?
What is Razor?
You are on page 322/01/2015
It’s a ASP.NET MVC View Engine
• Created to be easy to pick up by designers, front end developers and general tinkerers
• C sharp (C#) HTML (does also support VB HTML, but we don’t talk about that)
• You add code to your script by using the @ character
• You use braces { } for code blocks and semicolons ; to break statements and all other standard
C# syntax
@{ var myCounter = 1; }
• When you display content using the @ character ASP.NET HTML encodes the output, so character
such as <, > and & are rendered without begin interpreted as HTML
• You use standard C# conditional and loop logic, such as foreach, while and if
• You can use the @: or the <text> element to combine code, text and markup
if (DateTime.Now.DayOfWeek == DayOfWeek.Thursday)
{
@:Today is Thursday the @DateTime.Now.Day
}
• Comes with some helpful helpers for converting strings to other types
var mycount = myString.AsInt();
• Razor Views should be fairly simple, if they have lots of logic in them, then you probably need to
think differently
Razor and Umbraco
You are on page 422/01/2015
Confusion!
DynamicNode Macro Scripts (Umbraco v4.7.2+)
• Do not use the legacy Macro Scripts ever!
• DynamicNode scripts inherit
@inherits umbraco.MacroEngines.DynamicNodeContext
• You access Umbraco content using Model
IPublishedContent in a View, Partial View or a Partial View Macro (Umbraco v4.10.0+)
• Generally IPublishedContent Views & Partial Views inherit
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
• IPublishedContent Partial View Macros inherit
@inherits Umbraco.Web.Macros.PartialViewMacroPage
• You access Umbraco content using CurrentPage (dynamic) or Model.Content (strongly typed)
Dynamic vs Strongly Typed
You are on page 522/01/2015
Conciseness
@CurrentPage.myProperty
vs
@Model.Content.GetPropertyValue("myProperty")
IntelliSense, pre-compilation errors in Visual Studio or WebMatrix & any errors at all
Task 1a: Children Collections
You are on page 622/01/2015
Render a list of links linking to all nodes of document type alias “umbTextPage” that are children of
the homepage on the homepage
Dynamic model has the magical pluraliser
@foreach (var page in CurrentPage.umbTextPages)
{
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<a href="@page.Url" class="image image-full">
<img src="@page.Image" alt="" />
</a>
<h3><a href="@page.Url">@page.Name</a></h3>
@Umbraco.Truncate(page.BodyText, 100)
</section>
</div>
}
Files: /Views/umbHomePage.cshtml
Task 1a (cont): Children Collections
You are on page 722/01/2015
Typed model has the OfTypes method
@foreach (var page in Model.Content.Children.OfTypes("umbTextPage"))
{
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<a href="@page.Url" class="image image-full">
<img src="@page.GetPropertyValue("Image")" alt="" />
</a>
<h3><a href="@page.Url">@page.Name</a></h3>
@Umbraco.Truncate(page.GetPropertyValue<string>("BodyText"), 100)
</section>
</div>
}
Files: /Views/umbHomePage.cshtml
What is that @Umbraco.?
You are on page 822/01/2015
Say hello to the UmbracoHelper, loads of helpful methods for your scripts
Content
.Content(int id);
.ContentAtRoot();
.ContentAtXPath(string xpath, params XPathVariable[] variables);
.ContentSingleAtXPath(string xpath, params XPathVariable[] variables);
.TypedContent(int id)
.TypedContentAtRoot()
.TypedContentAtXPath(string xpath)
.TypedContentSingleAtXPath(string xpath)
Content helpers
.Field(string field)
.NiceUrl(int nodeId)
.NiceUrlWithDomain(int id)
Working with Media
.Media(1234);
.MediaAtRoot();
.TypedMedia(int id)
.TypedMediaAtRoot();
Working with Members
.Member(1234);
.TypedMember(1234);
Member Helpers
.MemberHasAccess(int nodeId, string path);
.MemberIsLoggedOn()
.IsProtected(int pageId, string path)
Fetching misc data
.GetDictionaryValue(string key);
.GetPreValueAsString(int prevalueId)
.Search(string term, bool useWildCards, string searchProvider)
.TypedSearch(string term, bool useWildCards, string searchProvider)
Templating Helpers
.Coalesce(params object[]);
.Concatenate(params object[]);
.CreateMd5Hash(string text);
.If(bool test, string valueIfTrue, string valueIfFalse)
.Join(string seperator, parmas object[] args)
.ReplaceLineBreaksForHtml(string text)
.StripHtml(string html)
.Truncate(string html, int length, bool addElipsis)
.RenderMacro(string alias, object parameters)
.RenderTemplate(int pageId, int? altTemplateId)
Task 1b: Children Collections
You are on page 922/01/2015
Render a list of links linking to all nodes of document type alias “umbTextPage” or
“umbNewsOverview” that are children of the current page
Dynamic model has a Where method which you can pass a filter string
@foreach (var page in CurrentPage.Children.Where("DocumentTypeAlias ==
"umbTextPage" || DocumentTypeAlias == "umbNewsOverview""))
Typed model, we just add parameters to the OfTypes method
@foreach (var page in Model.Content.Children.OfTypes("umbTextPage",
"umbNewsOverview"))
Files: /Views/umbHomePage.cshtml
Task 1c: Children Collections
You are on page 1022/01/2015
What if there were more document types?
Dynamic model we can use a Where method with the ContainsAny string extension and pass in a list
object
@{
var docTypesToInclude = new List<string>() { "umbTextPage",
"umbNewsOverview" };
<ul>
@foreach (var page in CurrentPage.
Children.
Where("DocumentTypeAlias.ContainsAny(@0)",
docTypesToInclude))
{
<li><a href="@page.Url">@page.Name</a></li>
}
</ul>
}
Typed model, I think we have it covered already?
Files: /Views/umbHomePage.cshtml
Task 1d: Children Collections
You are on page 1122/01/2015
What about other filtering conditions and ordering?
Dynamic model we can add brackets and add and/or (&&/||) operators and the OrderBy method
@foreach (var page in CurrentPage.Children.Where("(DocumentTypeAlias ==
"umbTextPage" || DocumentTypeAlias == "umbNewsOverview") &&
featuredPage").OrderBy("Name desc"))
Typed model, we add the Where and OrderBy methods and pass in a lambda
@foreach (var page in Model.Content.Children.OfTypes("umbTextPage",
"umbNewsOverview")
.Where(x => x.GetPropertyValue<bool>("featuredPage"))
.OrderByDescending(x => x.Name))
Files: /Views/umbHomePage.cshtml
Reuse?
You are on page 1222/01/2015
Partial Views
• Easy to create in the Umbraco UI
• Can be strongly typed so you can pass in the model context for rendering
• Can be passed parameters using a ViewDataDictionary object
Functions & Helpers
• In-script reuse
• Both can be passed parameters
Global Functions & Helpers
• Makes functions and helpers reusable across different scripts
C# Extension Methods
• Logic can be reused between Razor and other C# logic (e.g. WebApi or Surface Controllers)
Empty attributes?
You are on page 1322/01/2015
A very useful little feature of Razor is that if you attempt to render a null value into a HTML attribute it
will not render the attribute at all!
var current = CurrentPage.Id == page.Id ? "current_page_item" : null;
<li><a class="@current" href="@page.Url">@page.Name</a></li>
umbracoNaviHide Convention
Dynamics model
@foreach (var page in CurrentPage.Children.Where("Visible").OrderBy("Name
desc"))
Typed model
@foreach (var page in Model.Content.Children.Where(x => x.IsVisible())
Tree Traversal
You are on page 1422/01/2015
IPublishedContent has XPath like axes for traversing content, returning collections or single nodes
Children()
Ancestors()
Ancestors(int level)
Ancestors(string nodeTypeAlias)
AncestorsOrSelf()
AncestorsOrSelf(int level)
AncestorsOrSelf(string nodeTypeAlias)
Descendants()
Descendants(int level)
Descendants(string nodeTypeAlias)
DescendantsOrSelf()
DescendantsOrSelf(int level)
DescendantsOrSelf(string nodeTypeAlias)
AncestorOrSelf()
AncestorOrSelf(int level)
AncestorOrSelf(string nodeTypeAlias)
AncestorOrSelf(Func<IPublishedContent, bool> func)
Up()
Up(int number)
Up(string nodeTypeAlias)
Down()
Down(int number)
Down(string nodeTypeAlias)
Next()
Next(int number)
Next(string nodeTypeAlias)
Previous()
Previous(int number)
Previous(string nodeTypeAlias)
Sibling(int number)
Sibling(string nodeTypeAlias)
Task 2a: Navigation
You are on page 1522/01/2015
Create a reusable (needs to work at all node levels) main navigation using a Partial View
Dynamics model
@inherits UmbracoTemplatePage
<nav id="nav" class="skel-panels-fixed">
<ul>
@foreach (var page in CurrentPage
.AncestorOrSelf(1)
.Children
.Where("Visible"))
{
var current = CurrentPage.Id == page.Id ? "current_page_item" : null;
<li><a class="@current" href="@page.Url">@page.Name</a></li>
}
</ul>
</nav>
Files: /Views/Partials/umbTopNavigation.cshtml
Task 2a (cont): Navigation
You are on page 1622/01/2015
Typed model
@inherits UmbracoTemplatePage
<nav id="nav" class="skel-panels-fixed">
<ul>
@foreach (var page in Model
.Content
.AncestorOrSelf(1)
.Children
.Where(x => x.IsVisible()))
{
var current = Model.Content.Id == page.Id
? "current_page_item"
: null;
<li><a class="@current" href="@page.Url">@page.Name</a></li>
}
</ul>
</nav>
Files: /Views/Partials/umbTopNavigation.cshtml
Task 2b: Navigation – homepage?
You are on page 1722/01/2015
Dynamic model – Use a Razor helper
@inherits UmbracoTemplatePage
<nav id="nav" class="skel-panels-fixed">
<ul>
@{
var home = CurrentPage.AncestorOrSelf(1);
@RenderNavForNode(home)
foreach (var page in home.Children.Where("Visible"))
{
@RenderNavForNode(page);
}
}
</ul>
</nav>
@helper RenderNavForNode(dynamic page)
{
var current = CurrentPage.Id == page.Id ? "current_page_item" : null;
<li><a class="@current" href="@page.Url">@page.Name</a></li>
}
Files: /Views/Partials/umbTopNavigation.cshtml
Task 2b (cont): Navigation – homepage?
You are on page 1822/01/2015
Typed model
@inherits UmbracoTemplatePage
<nav id="nav" class="skel-panels-fixed">
<ul>
@{
var home = Model.Content.AncestorOrSelf(1);
@RenderNavForNode(home)
foreach (var page in home.Children.Where("Visible"))
{
@RenderNavForNode(page);
}
}
</ul>
</nav>
@helper RenderNavForNode(IPublishedContent page)
{
var current = Model.Content.Id == page.Id ? "current_page_item" : null;
<li><a class="@current" href="@page.Url">@page.Name</a></li>
}
Files: /Views/Partials/umbTopNavigation.cshtml
Task 3a: strongly typed partial view
You are on page 1922/01/2015
Convert task 1 to a strongly typed partial view
Typed model
@foreach (var page in Model.Content.Children
.OfTypes("umbTextPage","umbNewsOverview")
.Where(x => x.GetPropertyValue<bool>("featuredPage"))
.OrderByDescending(x => x.Name)){
@Html.Partial("umbFeatures", page)
}
Files: /Views/umbHomePage.cshtml
Task 3b: dynamic strongly typed partial view
You are on page 2022/01/2015
What, are you sure?
Dynamic model
@foreach (var page in CurrentPage.Children
.Where("(DocumentTypeAlias == "umbTextPage" || DocumentTypeAlias ==
"umbNewsOverview") && featuredPage")
.OrderBy("Name desc"))
{
@Html.Partial("umbFeaturesDynamic", (IPublishedContent)page)
}
Files: /Views/umbHomePage.cshtml
Task 3b (cont): strongly typed partial view
You are on page 2122/01/2015
AsDynamic()
When using the dynamic model sometimes you find you need to use the typed model for something such
as a complex filter. You can switch back to dynamic for rendering by using the AsDynamic() method.
Dynamic strongly typed partial view (ish)
@inherits UmbracoViewPage<IPublishedContent>
@{
var currentPage = Model.AsDynamic();
}
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<a href="@currentPage.Url" class="image image-full"><img
src="@currentPage.Image" alt="" /></a>
<h3><a href="@currentPage.Url">@currentPage.Name</a></h3>
@Umbraco.Truncate(currentPage.BodyText, 100)
</section>
</div>
Files: /Views/Partials/umbFeatureDynamic.cshtml
Task 4a: passing parameters to a Partial View
You are on page 2222/01/2015
Pass a ViewDataDictionary object a the Partial View
@{
Html.RenderPartial("umbEventsWidget",
new ViewDataDictionary(this.ViewData)
{
{ "numberOfEvents", 5 }
});
}
Files: /Views/umbHomePage.cshtml
Task 4a (cont)
You are on page 2322/01/2015
Retrieve the ViewDataDictionary value
@{
var events = CurrentPage
.AncestorOrSelf(1)
.FirstChild("umbEventsOverview")
.Children.Take(NumberOfEvents());
}
Use a Razor function to make it tidy
@functions{
private int NumberOfEvents()
{
if (ViewData["numberOfEvents"] != null)
{
return (int)ViewData["numberOfEvents"];
}
//default 4
return 4;
}
}
Files: /Views/Partials/umbEventsWidget.cshtml
Task 5 – put it all together
You are on page 2422/01/2015
Only show events that have not yet passed, this is a job for a lambda expression and a function (convert
ToDynamic if you want to)
@{
var events = Model.Content
.AncestorOrSelf(1)
.Children
.OfTypes("umbEventsOverview")
.First()
.Children(IsCurrentEvent)
.Take(NumberOfEvents())
.Select(x => x.AsDynamic());
}
Files: /Views/Partials/umbEventsWidget.cshtml
Task 6 – use a global Razor Class
You are on page 2522/01/2015
MyHelpers.cshtml in the App_Code folder
Helper – pass Umbraco Helper
@MyHelpers.RenderFooter(Umbraco)
Function
@MyHelpers.EasyDateFormat()
public static string EasyDateFormat()
{
return DateTime.Now.ToString("F");
}
Files: /App_Code/MyHelpers.cshtml
Task 7 – use a C# class in App_Code
You are on page 2622/01/2015
MyStuff.cs in the App_Code folder
Using the Function
@using UmbOktoberFest2014.App_Code
@MyStuff.EasyDateFormat()
The C# method
namespace UmbOktoberFest2014.App_Code
{
public static class MyStuff
{
public static string EasyDateFormat()
{
return DateTime.Now.ToString("F");
}
}
}
Files: /App_Code/MyStuff.cs
Task 8 - ToContentSet method
You are on page 2722/01/2015
Items within collections relate to their tree siblings not the other items in the collection, using the
ToContentSet methods changes the below methods to be related to the items position within the
collection.
.IsFirst()
.IsNotFirst()
.IsPosition ()
.IsModZero ()
.IsNotModZero ()
.IsNotPosition ()
.IsLast ()
.IsNotLast ()
.IsEven ()
.IsOdd ()
@{
var events = Model
.Content
.AncestorOrSelf(1)
.Children
.OfTypes("umbEventsOverview").First()
.Children
.OrderBy("eventEndDate desc")
.ToContentSet();
}
<h2 class="major"><span>Upcoming events</span></h2>
<ul class="style2">
@foreach (var eventItem in events)
{
<li>
<article class="is-post-summary">
<h3><a href="@eventItem.Url">@eventItem.IsFirst()
@eventItem.Name</a></h3>
<ul class="meta">
<li class="timestamp"></li>
</ul>
</article>
</li>
}
</ul>
Files: /Views/Partials/umbEventsWidget.cshtml
Task 9 - CsvContains
You are on page 2822/01/2015
Display a list of all news articles that have picked the event - Dynamic Model
@{
var releatedNews = CurrentPage
.AncestorOrSelf(1)
.FirstChild("umbNewsOverview")
.Children
.Where("relatedEvents.CsvContains(@0)",CurrentPage.Id.ToString())
.Take(4);
foreach (var newsItem in releatedNews)
{
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<a href="@newsItem.Url" class="image image-full">
<img src="http://placehold.it/350x150" alt="" />
</a>
<h3><a href="@newsItem.Url">@newsItem.Name</a></h3>
</section>
</div>
}
}
Files: /Views/EventItem.cshtml
Task 9 (cont) - CsvContains
You are on page 2922/01/2015
Display a list of all news articles that have picked the event – Typed Model
@{
var releatedNews = Model.Content
.AncestorOrSelf(1)
.Children.OfTypes("umbNewsOverview").First()
.Children(x => x.GetPropertyValue<string>("relatedEvents")
.CsvContains(Model.Content.Id.ToString()))
.Take(4);
foreach (var newsItem in releatedNews)
{
<div class="3u">
<!-- Feature -->
<section class="is-feature">
<a href="@newsItem.Url" class="image image-full"><img
src="http://placehold.it/350x150" alt="" /></a>
<h3><a href="@newsItem.Url">@newsItem.Name</a></h3>
</section>
</div>
}
}
Files: /Views/EventItem.cshtml
Partial View Macros
You are on page 3022/01/2015
Macro’s were amazing (even XSLT ones), but we now have MVC with it’s native Partial Views so when
should we use a Partial View Macro?
• When you want your content editor to be able insert a Macro in the RTE, Sir Trevor, v7.2 Grid or Macro
picker property editor etc…
• Sites that have to use WebForms template so that they can use legacy user controls
Task 10: What about Media and Cropping?
You are on page 3122/01/2015
Lets convert the standard Image media type from “Upload” to “Image Cropper” use media pickers
together
Value Converters & other questions
You are on page 3222/01/2015
If there is time left, then install the Value Converters Package, see what breaks and then fix it.
Documentation
https://github.com/Jeavon/Umbraco-Core-Property-Value-Converters/tree/v2
Crumpled Dog
020 7739 5553 | jeavon@crumpled-dog.com | www.crumpled-dog.com

More Related Content

What's hot (9)

Fields, entities, lists, oh my!
Fields, entities, lists, oh my!Fields, entities, lists, oh my!
Fields, entities, lists, oh my!
 
Getting Started with Javascript
Getting Started with JavascriptGetting Started with Javascript
Getting Started with Javascript
 
Drupalcon cph
Drupalcon cphDrupalcon cph
Drupalcon cph
 
Introduction to nodejs
Introduction to nodejsIntroduction to nodejs
Introduction to nodejs
 
JavaScript in Object-Oriented Way
JavaScript in Object-Oriented WayJavaScript in Object-Oriented Way
JavaScript in Object-Oriented Way
 
The Xtext Grammar Language
The Xtext Grammar LanguageThe Xtext Grammar Language
The Xtext Grammar Language
 
Streamlining JSON mapping
Streamlining JSON mappingStreamlining JSON mapping
Streamlining JSON mapping
 
Javascript Best Practices
Javascript Best PracticesJavascript Best Practices
Javascript Best Practices
 
Prototype Js
Prototype JsPrototype Js
Prototype Js
 

Viewers also liked

What the heck is a Umbraco property editor value converter?
What the heck is a Umbraco property editor value converter?What the heck is a Umbraco property editor value converter?
What the heck is a Umbraco property editor value converter?
Jeavon Leopold
 
Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014
Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014
Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014
Jeavon Leopold
 
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Trieu Nguyen
 

Viewers also liked (8)

What the heck is a Umbraco property editor value converter?
What the heck is a Umbraco property editor value converter?What the heck is a Umbraco property editor value converter?
What the heck is a Umbraco property editor value converter?
 
Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014
Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014
Imaging the Past, Present and Future with Umbraco - Belgian Festival 2014
 
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond Building a Website to Scale to 100 Million Page Views Per Day and Beyond
Building a Website to Scale to 100 Million Page Views Per Day and Beyond
 
Gearman and asynchronous processing in PHP applications
Gearman and asynchronous processing in PHP applicationsGearman and asynchronous processing in PHP applications
Gearman and asynchronous processing in PHP applications
 
Selling Umbraco - CodeGarden 2015
Selling Umbraco - CodeGarden 2015Selling Umbraco - CodeGarden 2015
Selling Umbraco - CodeGarden 2015
 
[Khóa luận tốt nghiệp] - Tìm hiểu và triển khai Snort/SnortSam
[Khóa luận tốt nghiệp] - Tìm hiểu và triển khai Snort/SnortSam[Khóa luận tốt nghiệp] - Tìm hiểu và triển khai Snort/SnortSam
[Khóa luận tốt nghiệp] - Tìm hiểu và triển khai Snort/SnortSam
 
Tiki.vn - How we scale as a tech startup
Tiki.vn - How we scale as a tech startupTiki.vn - How we scale as a tech startup
Tiki.vn - How we scale as a tech startup
 
All Your IOPS Are Belong To Us - A Pinteresting Case Study in MySQL Performan...
All Your IOPS Are Belong To Us - A Pinteresting Case Study in MySQL Performan...All Your IOPS Are Belong To Us - A Pinteresting Case Study in MySQL Performan...
All Your IOPS Are Belong To Us - A Pinteresting Case Study in MySQL Performan...
 

Similar to Umbraco OktoberFest 2014

Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
lennartkats
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0
JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0
JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0
Marcel Bruch
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
Yared Ayalew
 

Similar to Umbraco OktoberFest 2014 (20)

MVC Puree - Approaches to MVC with Umbraco
MVC Puree - Approaches to MVC with UmbracoMVC Puree - Approaches to MVC with Umbraco
MVC Puree - Approaches to MVC with Umbraco
 
The advantage of developing with TypeScript
The advantage of developing with TypeScript The advantage of developing with TypeScript
The advantage of developing with TypeScript
 
AngularConf2015
AngularConf2015AngularConf2015
AngularConf2015
 
ASP.NET MVC Workshop for Women in Technology
ASP.NET MVC Workshop for Women in TechnologyASP.NET MVC Workshop for Women in Technology
ASP.NET MVC Workshop for Women in Technology
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
 
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptxUnit 1 - TypeScript & Introduction to Angular CLI.pptx
Unit 1 - TypeScript & Introduction to Angular CLI.pptx
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
MWLUG 2015 - An Introduction to MVC
MWLUG 2015 - An Introduction to MVCMWLUG 2015 - An Introduction to MVC
MWLUG 2015 - An Introduction to MVC
 
TypeScript . the JavaScript developer best friend!
TypeScript . the JavaScript developer best friend!TypeScript . the JavaScript developer best friend!
TypeScript . the JavaScript developer best friend!
 
An Introduction To Model  View  Controller In XPages
An Introduction To Model  View  Controller In XPagesAn Introduction To Model  View  Controller In XPages
An Introduction To Model  View  Controller In XPages
 
Introduction to jQuery
Introduction to jQueryIntroduction to jQuery
Introduction to jQuery
 
Web Development with Delphi and React - ITDevCon 2016
Web Development with Delphi and React - ITDevCon 2016Web Development with Delphi and React - ITDevCon 2016
Web Development with Delphi and React - ITDevCon 2016
 
Stencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrivedStencil the time for vanilla web components has arrived
Stencil the time for vanilla web components has arrived
 
Tigerstripe @ Eclipse Summit 08
Tigerstripe @ Eclipse Summit 08Tigerstripe @ Eclipse Summit 08
Tigerstripe @ Eclipse Summit 08
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
 
Front End Development for Back End Developers - Devoxx UK 2017
 Front End Development for Back End Developers - Devoxx UK 2017 Front End Development for Back End Developers - Devoxx UK 2017
Front End Development for Back End Developers - Devoxx UK 2017
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Современная архитектура Android-приложений - Archetype / Степан Гончаров (90 ...
Современная архитектура Android-приложений - Archetype / Степан Гончаров (90 ...Современная архитектура Android-приложений - Archetype / Степан Гончаров (90 ...
Современная архитектура Android-приложений - Archetype / Степан Гончаров (90 ...
 
JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0
JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0
JUG Münster 2014 - Code Recommenders & Codetrails - Wissenstransfer 2.0
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 

Recently uploaded

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 

Umbraco OktoberFest 2014

  • 1. Razor Revealed Jeavon Leopold | Twitter: @crumpled_Jeavon We are Crumpled Dog
  • 2. You are on page 222/01/2015 I have been working with Umbraco since version 3.0 (circa 2007) • Technical Director at Crumpled Dog – Umbraco Gold Partner in London’s TechCity/Silicon Roundabout • Umbraco MVP – Honoured to be voted by the global community as one of the five 2104 MVPs • Umbraco Community Member – I am known for answering many questions in the Razor forum and have 7,500 karma • Umbraco Core Contributor– I have made many bug fixes and even added a few features here and there over the years. Most recently I worked with Per Ploug Hansen and James South on the v7.1 Core Image Cropper API • Umbraco Package Hacker – I have created a few packages of my own and collaborated on many more Who am I?
  • 3. What is Razor? You are on page 322/01/2015 It’s a ASP.NET MVC View Engine • Created to be easy to pick up by designers, front end developers and general tinkerers • C sharp (C#) HTML (does also support VB HTML, but we don’t talk about that) • You add code to your script by using the @ character • You use braces { } for code blocks and semicolons ; to break statements and all other standard C# syntax @{ var myCounter = 1; } • When you display content using the @ character ASP.NET HTML encodes the output, so character such as <, > and & are rendered without begin interpreted as HTML • You use standard C# conditional and loop logic, such as foreach, while and if • You can use the @: or the <text> element to combine code, text and markup if (DateTime.Now.DayOfWeek == DayOfWeek.Thursday) { @:Today is Thursday the @DateTime.Now.Day } • Comes with some helpful helpers for converting strings to other types var mycount = myString.AsInt(); • Razor Views should be fairly simple, if they have lots of logic in them, then you probably need to think differently
  • 4. Razor and Umbraco You are on page 422/01/2015 Confusion! DynamicNode Macro Scripts (Umbraco v4.7.2+) • Do not use the legacy Macro Scripts ever! • DynamicNode scripts inherit @inherits umbraco.MacroEngines.DynamicNodeContext • You access Umbraco content using Model IPublishedContent in a View, Partial View or a Partial View Macro (Umbraco v4.10.0+) • Generally IPublishedContent Views & Partial Views inherit @inherits Umbraco.Web.Mvc.UmbracoTemplatePage • IPublishedContent Partial View Macros inherit @inherits Umbraco.Web.Macros.PartialViewMacroPage • You access Umbraco content using CurrentPage (dynamic) or Model.Content (strongly typed)
  • 5. Dynamic vs Strongly Typed You are on page 522/01/2015 Conciseness @CurrentPage.myProperty vs @Model.Content.GetPropertyValue("myProperty") IntelliSense, pre-compilation errors in Visual Studio or WebMatrix & any errors at all
  • 6. Task 1a: Children Collections You are on page 622/01/2015 Render a list of links linking to all nodes of document type alias “umbTextPage” that are children of the homepage on the homepage Dynamic model has the magical pluraliser @foreach (var page in CurrentPage.umbTextPages) { <div class="3u"> <!-- Feature --> <section class="is-feature"> <a href="@page.Url" class="image image-full"> <img src="@page.Image" alt="" /> </a> <h3><a href="@page.Url">@page.Name</a></h3> @Umbraco.Truncate(page.BodyText, 100) </section> </div> } Files: /Views/umbHomePage.cshtml
  • 7. Task 1a (cont): Children Collections You are on page 722/01/2015 Typed model has the OfTypes method @foreach (var page in Model.Content.Children.OfTypes("umbTextPage")) { <div class="3u"> <!-- Feature --> <section class="is-feature"> <a href="@page.Url" class="image image-full"> <img src="@page.GetPropertyValue("Image")" alt="" /> </a> <h3><a href="@page.Url">@page.Name</a></h3> @Umbraco.Truncate(page.GetPropertyValue<string>("BodyText"), 100) </section> </div> } Files: /Views/umbHomePage.cshtml
  • 8. What is that @Umbraco.? You are on page 822/01/2015 Say hello to the UmbracoHelper, loads of helpful methods for your scripts Content .Content(int id); .ContentAtRoot(); .ContentAtXPath(string xpath, params XPathVariable[] variables); .ContentSingleAtXPath(string xpath, params XPathVariable[] variables); .TypedContent(int id) .TypedContentAtRoot() .TypedContentAtXPath(string xpath) .TypedContentSingleAtXPath(string xpath) Content helpers .Field(string field) .NiceUrl(int nodeId) .NiceUrlWithDomain(int id) Working with Media .Media(1234); .MediaAtRoot(); .TypedMedia(int id) .TypedMediaAtRoot(); Working with Members .Member(1234); .TypedMember(1234); Member Helpers .MemberHasAccess(int nodeId, string path); .MemberIsLoggedOn() .IsProtected(int pageId, string path) Fetching misc data .GetDictionaryValue(string key); .GetPreValueAsString(int prevalueId) .Search(string term, bool useWildCards, string searchProvider) .TypedSearch(string term, bool useWildCards, string searchProvider) Templating Helpers .Coalesce(params object[]); .Concatenate(params object[]); .CreateMd5Hash(string text); .If(bool test, string valueIfTrue, string valueIfFalse) .Join(string seperator, parmas object[] args) .ReplaceLineBreaksForHtml(string text) .StripHtml(string html) .Truncate(string html, int length, bool addElipsis) .RenderMacro(string alias, object parameters) .RenderTemplate(int pageId, int? altTemplateId)
  • 9. Task 1b: Children Collections You are on page 922/01/2015 Render a list of links linking to all nodes of document type alias “umbTextPage” or “umbNewsOverview” that are children of the current page Dynamic model has a Where method which you can pass a filter string @foreach (var page in CurrentPage.Children.Where("DocumentTypeAlias == "umbTextPage" || DocumentTypeAlias == "umbNewsOverview"")) Typed model, we just add parameters to the OfTypes method @foreach (var page in Model.Content.Children.OfTypes("umbTextPage", "umbNewsOverview")) Files: /Views/umbHomePage.cshtml
  • 10. Task 1c: Children Collections You are on page 1022/01/2015 What if there were more document types? Dynamic model we can use a Where method with the ContainsAny string extension and pass in a list object @{ var docTypesToInclude = new List<string>() { "umbTextPage", "umbNewsOverview" }; <ul> @foreach (var page in CurrentPage. Children. Where("DocumentTypeAlias.ContainsAny(@0)", docTypesToInclude)) { <li><a href="@page.Url">@page.Name</a></li> } </ul> } Typed model, I think we have it covered already? Files: /Views/umbHomePage.cshtml
  • 11. Task 1d: Children Collections You are on page 1122/01/2015 What about other filtering conditions and ordering? Dynamic model we can add brackets and add and/or (&&/||) operators and the OrderBy method @foreach (var page in CurrentPage.Children.Where("(DocumentTypeAlias == "umbTextPage" || DocumentTypeAlias == "umbNewsOverview") && featuredPage").OrderBy("Name desc")) Typed model, we add the Where and OrderBy methods and pass in a lambda @foreach (var page in Model.Content.Children.OfTypes("umbTextPage", "umbNewsOverview") .Where(x => x.GetPropertyValue<bool>("featuredPage")) .OrderByDescending(x => x.Name)) Files: /Views/umbHomePage.cshtml
  • 12. Reuse? You are on page 1222/01/2015 Partial Views • Easy to create in the Umbraco UI • Can be strongly typed so you can pass in the model context for rendering • Can be passed parameters using a ViewDataDictionary object Functions & Helpers • In-script reuse • Both can be passed parameters Global Functions & Helpers • Makes functions and helpers reusable across different scripts C# Extension Methods • Logic can be reused between Razor and other C# logic (e.g. WebApi or Surface Controllers)
  • 13. Empty attributes? You are on page 1322/01/2015 A very useful little feature of Razor is that if you attempt to render a null value into a HTML attribute it will not render the attribute at all! var current = CurrentPage.Id == page.Id ? "current_page_item" : null; <li><a class="@current" href="@page.Url">@page.Name</a></li> umbracoNaviHide Convention Dynamics model @foreach (var page in CurrentPage.Children.Where("Visible").OrderBy("Name desc")) Typed model @foreach (var page in Model.Content.Children.Where(x => x.IsVisible())
  • 14. Tree Traversal You are on page 1422/01/2015 IPublishedContent has XPath like axes for traversing content, returning collections or single nodes Children() Ancestors() Ancestors(int level) Ancestors(string nodeTypeAlias) AncestorsOrSelf() AncestorsOrSelf(int level) AncestorsOrSelf(string nodeTypeAlias) Descendants() Descendants(int level) Descendants(string nodeTypeAlias) DescendantsOrSelf() DescendantsOrSelf(int level) DescendantsOrSelf(string nodeTypeAlias) AncestorOrSelf() AncestorOrSelf(int level) AncestorOrSelf(string nodeTypeAlias) AncestorOrSelf(Func<IPublishedContent, bool> func) Up() Up(int number) Up(string nodeTypeAlias) Down() Down(int number) Down(string nodeTypeAlias) Next() Next(int number) Next(string nodeTypeAlias) Previous() Previous(int number) Previous(string nodeTypeAlias) Sibling(int number) Sibling(string nodeTypeAlias)
  • 15. Task 2a: Navigation You are on page 1522/01/2015 Create a reusable (needs to work at all node levels) main navigation using a Partial View Dynamics model @inherits UmbracoTemplatePage <nav id="nav" class="skel-panels-fixed"> <ul> @foreach (var page in CurrentPage .AncestorOrSelf(1) .Children .Where("Visible")) { var current = CurrentPage.Id == page.Id ? "current_page_item" : null; <li><a class="@current" href="@page.Url">@page.Name</a></li> } </ul> </nav> Files: /Views/Partials/umbTopNavigation.cshtml
  • 16. Task 2a (cont): Navigation You are on page 1622/01/2015 Typed model @inherits UmbracoTemplatePage <nav id="nav" class="skel-panels-fixed"> <ul> @foreach (var page in Model .Content .AncestorOrSelf(1) .Children .Where(x => x.IsVisible())) { var current = Model.Content.Id == page.Id ? "current_page_item" : null; <li><a class="@current" href="@page.Url">@page.Name</a></li> } </ul> </nav> Files: /Views/Partials/umbTopNavigation.cshtml
  • 17. Task 2b: Navigation – homepage? You are on page 1722/01/2015 Dynamic model – Use a Razor helper @inherits UmbracoTemplatePage <nav id="nav" class="skel-panels-fixed"> <ul> @{ var home = CurrentPage.AncestorOrSelf(1); @RenderNavForNode(home) foreach (var page in home.Children.Where("Visible")) { @RenderNavForNode(page); } } </ul> </nav> @helper RenderNavForNode(dynamic page) { var current = CurrentPage.Id == page.Id ? "current_page_item" : null; <li><a class="@current" href="@page.Url">@page.Name</a></li> } Files: /Views/Partials/umbTopNavigation.cshtml
  • 18. Task 2b (cont): Navigation – homepage? You are on page 1822/01/2015 Typed model @inherits UmbracoTemplatePage <nav id="nav" class="skel-panels-fixed"> <ul> @{ var home = Model.Content.AncestorOrSelf(1); @RenderNavForNode(home) foreach (var page in home.Children.Where("Visible")) { @RenderNavForNode(page); } } </ul> </nav> @helper RenderNavForNode(IPublishedContent page) { var current = Model.Content.Id == page.Id ? "current_page_item" : null; <li><a class="@current" href="@page.Url">@page.Name</a></li> } Files: /Views/Partials/umbTopNavigation.cshtml
  • 19. Task 3a: strongly typed partial view You are on page 1922/01/2015 Convert task 1 to a strongly typed partial view Typed model @foreach (var page in Model.Content.Children .OfTypes("umbTextPage","umbNewsOverview") .Where(x => x.GetPropertyValue<bool>("featuredPage")) .OrderByDescending(x => x.Name)){ @Html.Partial("umbFeatures", page) } Files: /Views/umbHomePage.cshtml
  • 20. Task 3b: dynamic strongly typed partial view You are on page 2022/01/2015 What, are you sure? Dynamic model @foreach (var page in CurrentPage.Children .Where("(DocumentTypeAlias == "umbTextPage" || DocumentTypeAlias == "umbNewsOverview") && featuredPage") .OrderBy("Name desc")) { @Html.Partial("umbFeaturesDynamic", (IPublishedContent)page) } Files: /Views/umbHomePage.cshtml
  • 21. Task 3b (cont): strongly typed partial view You are on page 2122/01/2015 AsDynamic() When using the dynamic model sometimes you find you need to use the typed model for something such as a complex filter. You can switch back to dynamic for rendering by using the AsDynamic() method. Dynamic strongly typed partial view (ish) @inherits UmbracoViewPage<IPublishedContent> @{ var currentPage = Model.AsDynamic(); } <div class="3u"> <!-- Feature --> <section class="is-feature"> <a href="@currentPage.Url" class="image image-full"><img src="@currentPage.Image" alt="" /></a> <h3><a href="@currentPage.Url">@currentPage.Name</a></h3> @Umbraco.Truncate(currentPage.BodyText, 100) </section> </div> Files: /Views/Partials/umbFeatureDynamic.cshtml
  • 22. Task 4a: passing parameters to a Partial View You are on page 2222/01/2015 Pass a ViewDataDictionary object a the Partial View @{ Html.RenderPartial("umbEventsWidget", new ViewDataDictionary(this.ViewData) { { "numberOfEvents", 5 } }); } Files: /Views/umbHomePage.cshtml
  • 23. Task 4a (cont) You are on page 2322/01/2015 Retrieve the ViewDataDictionary value @{ var events = CurrentPage .AncestorOrSelf(1) .FirstChild("umbEventsOverview") .Children.Take(NumberOfEvents()); } Use a Razor function to make it tidy @functions{ private int NumberOfEvents() { if (ViewData["numberOfEvents"] != null) { return (int)ViewData["numberOfEvents"]; } //default 4 return 4; } } Files: /Views/Partials/umbEventsWidget.cshtml
  • 24. Task 5 – put it all together You are on page 2422/01/2015 Only show events that have not yet passed, this is a job for a lambda expression and a function (convert ToDynamic if you want to) @{ var events = Model.Content .AncestorOrSelf(1) .Children .OfTypes("umbEventsOverview") .First() .Children(IsCurrentEvent) .Take(NumberOfEvents()) .Select(x => x.AsDynamic()); } Files: /Views/Partials/umbEventsWidget.cshtml
  • 25. Task 6 – use a global Razor Class You are on page 2522/01/2015 MyHelpers.cshtml in the App_Code folder Helper – pass Umbraco Helper @MyHelpers.RenderFooter(Umbraco) Function @MyHelpers.EasyDateFormat() public static string EasyDateFormat() { return DateTime.Now.ToString("F"); } Files: /App_Code/MyHelpers.cshtml
  • 26. Task 7 – use a C# class in App_Code You are on page 2622/01/2015 MyStuff.cs in the App_Code folder Using the Function @using UmbOktoberFest2014.App_Code @MyStuff.EasyDateFormat() The C# method namespace UmbOktoberFest2014.App_Code { public static class MyStuff { public static string EasyDateFormat() { return DateTime.Now.ToString("F"); } } } Files: /App_Code/MyStuff.cs
  • 27. Task 8 - ToContentSet method You are on page 2722/01/2015 Items within collections relate to their tree siblings not the other items in the collection, using the ToContentSet methods changes the below methods to be related to the items position within the collection. .IsFirst() .IsNotFirst() .IsPosition () .IsModZero () .IsNotModZero () .IsNotPosition () .IsLast () .IsNotLast () .IsEven () .IsOdd () @{ var events = Model .Content .AncestorOrSelf(1) .Children .OfTypes("umbEventsOverview").First() .Children .OrderBy("eventEndDate desc") .ToContentSet(); } <h2 class="major"><span>Upcoming events</span></h2> <ul class="style2"> @foreach (var eventItem in events) { <li> <article class="is-post-summary"> <h3><a href="@eventItem.Url">@eventItem.IsFirst() @eventItem.Name</a></h3> <ul class="meta"> <li class="timestamp"></li> </ul> </article> </li> } </ul> Files: /Views/Partials/umbEventsWidget.cshtml
  • 28. Task 9 - CsvContains You are on page 2822/01/2015 Display a list of all news articles that have picked the event - Dynamic Model @{ var releatedNews = CurrentPage .AncestorOrSelf(1) .FirstChild("umbNewsOverview") .Children .Where("relatedEvents.CsvContains(@0)",CurrentPage.Id.ToString()) .Take(4); foreach (var newsItem in releatedNews) { <div class="3u"> <!-- Feature --> <section class="is-feature"> <a href="@newsItem.Url" class="image image-full"> <img src="http://placehold.it/350x150" alt="" /> </a> <h3><a href="@newsItem.Url">@newsItem.Name</a></h3> </section> </div> } } Files: /Views/EventItem.cshtml
  • 29. Task 9 (cont) - CsvContains You are on page 2922/01/2015 Display a list of all news articles that have picked the event – Typed Model @{ var releatedNews = Model.Content .AncestorOrSelf(1) .Children.OfTypes("umbNewsOverview").First() .Children(x => x.GetPropertyValue<string>("relatedEvents") .CsvContains(Model.Content.Id.ToString())) .Take(4); foreach (var newsItem in releatedNews) { <div class="3u"> <!-- Feature --> <section class="is-feature"> <a href="@newsItem.Url" class="image image-full"><img src="http://placehold.it/350x150" alt="" /></a> <h3><a href="@newsItem.Url">@newsItem.Name</a></h3> </section> </div> } } Files: /Views/EventItem.cshtml
  • 30. Partial View Macros You are on page 3022/01/2015 Macro’s were amazing (even XSLT ones), but we now have MVC with it’s native Partial Views so when should we use a Partial View Macro? • When you want your content editor to be able insert a Macro in the RTE, Sir Trevor, v7.2 Grid or Macro picker property editor etc… • Sites that have to use WebForms template so that they can use legacy user controls
  • 31. Task 10: What about Media and Cropping? You are on page 3122/01/2015 Lets convert the standard Image media type from “Upload” to “Image Cropper” use media pickers together
  • 32. Value Converters & other questions You are on page 3222/01/2015 If there is time left, then install the Value Converters Package, see what breaks and then fix it. Documentation https://github.com/Jeavon/Umbraco-Core-Property-Value-Converters/tree/v2
  • 33. Crumpled Dog 020 7739 5553 | jeavon@crumpled-dog.com | www.crumpled-dog.com

Editor's Notes

  1. Typed only? Dynamics by default?