Nov 04, 2014
Sitefinity 5
by the Falafel Sitefinity Team
Welcome to Sitefinity 5
We hope you enjoy the book as much as we, at
Falafel Software, enjoyed creating it.
All rights reserved. No parts of this work may be reproduced in any form or by any means - graphic,
electronic, or mechanical, including photocopying, recording, taping, or information storage and retrieval
systems - without the written permission of the publisher.
Products that are referred to in this document may be either trademarks and/or registered trademarks of
the respective owners. The publisher and the author make no claim to these trademarks.
While every precaution has been taken in the preparation of this document, the publisher and the author
assume no responsibility for errors or omissions, or for damages resulting from the use of information
contained in this document or from the use of programs and source code that may accompany it. In no
event shall the publisher and the author be liable for any loss of profit or any other commercial damage
caused or alleged to have been caused directly or indirectly by this document.
Printed: April 2012
Sitefinity 5
© 2012 Falafel Software
PublisherSpecial thanks to:
All the team members at Telerik worldwide for creating a magnificant piece of
software in Sitefinity. The authors also would like to thank the Falafel team
members in Colorado, Texas, Michigan, N. Carolina, Canada, Lebanon and
California for their feedback and recommendations on the subjects of the
manual.
Also the team would like to thank the following members of the Telerik
Sitefinity team for their hard work and continuous support:
Gabe Sumner
Ivan Dimitrov
Georgi Chokov
Steve Miller
Ivan Osmak
Boyan Rabchev
Anton Hristov
Josh Morales
Hristo Borisov
Radoslav Georgiev
Lidiya Petkova
Slavo Ingilizov
Stanislav Velikov
Vassil Terziev
Falafel Sitefinity Team
Technical Editors
Cover Designer
Falafel Software Inc.
Basem Emara
Alain "Lino" Tadros
Matt Kurvin
Production
Falafel Software Inc.
Team Coordinator
Alain "Lino" Tadros
Noel RiceBasem Emara
Alain "Lino" TadrosBary NuszGary Campbell
Scott Frolich
Matt Kurvin
Administration
Sean Samuel
George Saddeh
Sitefinity 54
© 2012 Falafel Software
Table of Contents
1 Introduction 2
.......................................................................................... 2What You Need to Know Before Reading This Courseware
.......................................................................................... 3
What Do You Need to Have Before Reading This
Courseware
.......................................................................................... 4How This Courseware is Organized
.......................................................................................... 7What is a CMS and why do you need one?
.......................................................................................... 8Sitefinity 3.7 vs. 5.x
2 Setting Up Your Environment 10
.......................................................................................... 10Objectives
.......................................................................................... 11Installing Sitefinity 5
.......................................................................................... 14Installing the SDK
.......................................................................................... 17Summary
3 Getting Started 19
.......................................................................................... 19Objectives
.......................................................................................... 20Sitefinity Project Manager
.......................................................................................... 22Dashboard
.......................................................................................... 23About Pages and Content
.......................................................................................... 24Front End vs. Back End
.......................................................................................... 25Creating Projects
.......................................................................................... 40Summary
4 Pages 42
.......................................................................................... 43Objectives
.......................................................................................... 44Page Settings
5Contents
© 2012 Falafel Software
.......................................................................................... 51Editing the Page
.......................................................................................... 77Tour of Page Administration
.......................................................................................... 82Summary
5 Content 84
.......................................................................................... 85Objectives
.......................................................................................... 86Tour of the Content Menu
.......................................................................................... 87Content Block
.......................................................................................... 94News
.......................................................................................... 101Events
.......................................................................................... 106Images and Albums
.......................................................................................... 118Video
.......................................................................................... 127Lists
.......................................................................................... 132Blogs
.......................................................................................... 145Documents
.......................................................................................... 153Forms
.......................................................................................... 162Social Sharing Options
.......................................................................................... 164Summary
6 Permissions 166
.......................................................................................... 167Objectives
.......................................................................................... 168Built-In Roles
.......................................................................................... 169Creating a Role
.......................................................................................... 171Creating a User
.......................................................................................... 173Test the New User
.......................................................................................... 174Summary
7 Workflow 176
.......................................................................................... 177Objectives
.......................................................................................... 178Defining a Workflow
Sitefinity 56
© 2012 Falafel Software
.......................................................................................... 183Testing the Workflow
.......................................................................................... 184Summary
8 Analytics 186
.......................................................................................... 187Objectives
.......................................................................................... 188Setup
.......................................................................................... 191Using Analytics in the Administrator
.......................................................................................... 194Summary
9 Widget Templates 196
.......................................................................................... 197Objectives
.......................................................................................... 198Accessing Widget Templates
.......................................................................................... 199Changing a Template
.......................................................................................... 202Creating a New Template
.......................................................................................... 204Managing Widget Templates
.......................................................................................... 205Summary
10 Page Templates 207
.......................................................................................... 208Objectives
.......................................................................................... 209Creating and Using a Page Template
.......................................................................................... 221Stying
.......................................................................................... 225Debugging CSS
.......................................................................................... 229Summary
11 Responsive Web Design 231
.......................................................................................... 232Objectives
.......................................................................................... 233Creating Rules
.......................................................................................... 236Previewing the Results
.......................................................................................... 237Device Characteristics
.......................................................................................... 239Adding New Behaviors
7Contents
© 2012 Falafel Software
.......................................................................................... 242Summary
12 Working with Master Pages 244
.......................................................................................... 245Objectives
.......................................................................................... 246Masterpage Overview
.......................................................................................... 247Using a MasterPage from the Marketplace
.......................................................................................... 256Editing 3rd Party Templates
.......................................................................................... 265Master Page Surgery Tips
.......................................................................................... 269Summary
13 Developing in Sitefinity 271
.......................................................................................... 272Objectives
.......................................................................................... 273What Flavor API?
.......................................................................................... 274Getting Started with Sitefinity Development
.......................................................................................... 278Sitefinity Projects in Visual Studio
.......................................................................................... 280Developing with Thunder
.......................................................................................... 281Summary
14 Using the Sitefinity API 283
.......................................................................................... 284Objectives
.......................................................................................... 285Working with Pages
.......................................................................................... 291Working with Content Items
.......................................................................................... 297Publishing
.......................................................................................... 298Summary
15 Authentication and Security 300
.......................................................................................... 301Objectives
.......................................................................................... 302Claims vs Forms Authentication
.......................................................................................... 303Setting the Authentication Type
.......................................................................................... 304Login Programmatically
Sitefinity 58
© 2012 Falafel Software
.......................................................................................... 306Logout Programmatically
.......................................................................................... 307Create a User
.......................................................................................... 308Roles and Permissions
.......................................................................................... 311Summary
16 Using the Fluent API 313
.......................................................................................... 314Objectives
.......................................................................................... 315Fluent API Facades
.......................................................................................... 316Working with Pages
.......................................................................................... 319Working with Content Items
.......................................................................................... 337Summary
17 Working with Forms 339
.......................................................................................... 340Objectives
.......................................................................................... 341Getting a List of All Forms
.......................................................................................... 343Retrieve a Single Form
.......................................................................................... 344Retrieving Form Entry Values
.......................................................................................... 349Summary
18 Localization 351
.......................................................................................... 352Objectives
.......................................................................................... 353Localizing Front End Pages
.......................................................................................... 360User Language Selection
.......................................................................................... 362Localizing In Code
.......................................................................................... 363Localizable Strings
.......................................................................................... 364Localizing Back End Pages
.......................................................................................... 367Summary
19 Working with Widgets 369
.......................................................................................... 370Objectives
9Contents
© 2012 Falafel Software
.......................................................................................... 371User Controls
.......................................................................................... 382Custom Controls
.......................................................................................... 394Custom Control Designers
.......................................................................................... 408Using RadControls for ASP.NET AJAX with Sitefinity
.......................................................................................... 410Silverlight Controls
.......................................................................................... 418Communication between Custom Control and Silverlight
.......................................................................................... 427Custom Form Controls
.......................................................................................... 439Summary
20 Working with Modules 441
.......................................................................................... 442Objectives
.......................................................................................... 443Create a Custom Module
.......................................................................................... 450Add Module Content
.......................................................................................... 452Customizing the Backend Grid
.......................................................................................... 455Add the Module to a Page
.......................................................................................... 458Working with the Module in Code
.......................................................................................... 462Summary
21 Sitefinity Web Services 464
.......................................................................................... 465Objectives
.......................................................................................... 466Getting Available Services and Methods
.......................................................................................... 470Anatomy of a Web Service Call
.......................................................................................... 471Using Claims Authentication
.......................................................................................... 486Using Forms Authentication
.......................................................................................... 495What Next?
.......................................................................................... 496Summary
22 Content Classification - Taxonomy 498
.......................................................................................... 499Objectives
.......................................................................................... 500Terminology
Sitefinity 510
© 2012 Falafel Software
.......................................................................................... 501Getting Started
.......................................................................................... 502Listing Taxonomies
.......................................................................................... 503Listing Taxa
.......................................................................................... 504Finding Frequently Used Categories and Tags
.......................................................................................... 506Get Items by Category or Tag
.......................................................................................... 509Adding Categories and Tags
.......................................................................................... 510Summary
23 Dynamic Data 512
.......................................................................................... 513Objectives
.......................................................................................... 514Adding Custom Fields
.......................................................................................... 520Using the DynamicData Facade
.......................................................................................... 521Programmatically Listing Types
.......................................................................................... 523Programmatically Listing Fields
.......................................................................................... 528Reading and Writing Custom Field Values
.......................................................................................... 529Summary
24 About Falafel 531
.......................................................................................... 532Support and Services
Index 537
1Introduction
Sitefinity 52
© 2012 Falafel Software
1 Introduction
What You Need to Know Before Reading This Courseware
This Courseware first demonstrates how to be productive right away using Sitefinity in a
business environment, progresses to administrative and designer tasks and finishes up
with details on developing for Sitefinity. Depending on your use of Sitefinity, different
parts of the book will be useful to you.
Business Users: If you want to create web content but have no interest in web siteadministration or fiddling with technical details.
Designers and Administrators: If you are responsible for the installation and setup of newweb site projects, configuration and management of users.
Developers: If you need to programmatic control over Sitefinity websites or widgets, need to
adapt Sitefinity to include features that don’t exist out-of-the-box or need to access datacontained in your Sitefinity website or feed data to your website.
Introduction 3
© 2012 Falafel Software
What Do You Need to Have Before Reading This Courseware
Server Side
Microsoft® Windows Server 2003, 2008, Windows XP [1]
Windows Vista, Windows 7 Internet Information Services 6+[2]
Microsoft® .NET Framework 4.0
Database
Microsoft® SQL Express 2005
2008 Microsoft® SQL Server 2005, 2008
Supported Browsers
Internet Explorer 7+
Firefox 3.6 +
JavaScript must be enabled on all browsers
Silverlight 4 plug-in must be installed on all users' browsers
Tip!
In practice, Chrome, Opera and Safari also work well with Sitefinity. Business users
may want to use Chrome, currently the fastest browser on the market. Firefox can
be used for any testing and debugging by web designers and developers. You may
need to use Internet Explorer based on business needs.
*http://www.sitefinity.com/asp-net-cms-features/systems-requirements.aspx
NOTE 1: You can run Sitefinity with Windows XP, only when using the Sitefinity integrated web server.
NOTE 2: It is not required to use IIS. If you want to use IIS, you must configure it for Silverlight Application. For more information,
see Configuring IIS for Silverlight application below.
NOTE 3: If you are using Windows XP or Windows Server 2003 make sure you have updated your Windows Installer to version
4.5.
Sitefinity 54
© 2012 Falafel Software
How This Courseware is Organized
Setting Up Your Environment
This Chapter covers the basic installation of Sitefinity.
Getting Started
In this Chapter you will create a minimal, simple Sitefinity website. The website will
contain a single "Welcome" page populated with text.
Pages
This chapter explains the options for creating and configuring a page. Then you'll learn
how to edit page content and layout, paying particular attention to working with the
HTML Editor. A tour of the page administration explores the list of pages and the possible
Actions you can take, filtering and managing pages.
Content
This chapter tours the Content Menu and demonstrates how to work with each type of
content. You'll learn how to create content, how to use widgets to display content in a page
and how to configure the widget to fine-tune the layout and behavior of the content.
Permissions
This chapter explains how the built-in roles are used, how to create a role, how to create a
user and how to assign roles to users.
Workflow
In this chapter you'll learn how to define and test a workflow.
Analytics
In this chapter you will learn how to setup Analytics. A brief survey of the Analytics
interface will show you the kinds of web traffic information you can generate and analyze.
Widget Templates
This chapter demonstrates where you can access widget templates, how to edit the
template markup, how to create your own custom templates and how to work with the
Administration menu Widget Templates option.
Introduction 5
© 2012 Falafel Software
Page Templates
In this chapter you'll learn use page templates to establish a basic layout and content across
multiple pages. You will add styles to the page template using both the CSS widget and
using ASP.NET Themes. Finally, you'll learn how to debug CSS issues.
Responsive Web Design
In this chapter you'll learn how Responsive Web Design helps your application react to
device sizes ranging from full-sized desktop or notebook screens to the smallest of hand-
held devices. You'll learn how to define rules that react to different screen configurations,
how to make basic layout changes based on those configurations and how to fine tune all
aspects of the page using styles.
Working with Master Pages
In this chapter you'll learn how Master pages work together with the page template and
theme. You'll see how to use a Master page from the marketplace and how to "slice-and-
dice" third party templates to integrate them in your web site.
Developing in Sitefinity
In this chapter you will learn the basics for getting started with Sitefinity development.
You'll learn what basic flavors of the API are available to you and how to work with the
API in Visual Studio.
Using the Sitefinity API
This chapter explains how to work with the Sitefinity API. First you'll learn how to create a
Sitefinity page programmatically and then how to display the hierarchy of pages in a tree
view. You'll also create content programmatically and perform CRUD (Create Read
Update Delete) operations against content items. Finally, you will add a programmatically
created content item to a page, on-the-fly.
Using the Fluent API
This chapter demonstrates how the Fluent API works with pages and content items. You
will learn how to upload images and documents. In particular, you will use a web service
to load images to an Album en-masse. Finally, you will use the Fluent API to return lists of
content items, filter, sort and select content items into useful subsets and then bind your
results to ASP.NET controls.
Sitefinity 56
© 2012 Falafel Software
Working with Forms
This chapter explains how to programmatically retrieve forms and form items. This
chapter will also discuss how to get at the form entry column names and captions.
Localization
In this chapter you will learn how to localize front end pages using Sitefinity
Administration, how to localize strings in code, how to localize back end pages and how to
use the Interface Labels & Messages page.
Working with Widgets
This chapter steps you through how to create user and custom controls available from the
toolbox and usable within the page. You will also learn how to create designers for custom
controls to assist your users in configuring the control. You will use a RadControls
"RadComboBox" and "RadGrid" inside your page as well as perform CRUD operations
against live data. You will see how to integrate a Silverlight control and how to make the
Silverlight control and page communicate. Finally, you will create a custom form control.
Working with Modules
In this chapter you will work with modules to handle custom data. You will learn how to
create a custom module, add content to the module and add the module widget to a page
to view the data. You will also learn how to customize the backend table of module data.
Sitefinity Web Services
This chapter demonstrates how to work with both Forms Authentication and, the new
default, Claims Authentication. This chapter first shows how to get all the available web
services and method calls. You will learn the basic steps in common with all web service
method calls, how to log in and log out of Sitefinity from a web service and how to
retrieve and parse information from a web service call.
Content Classification - Taxonomy
This chapter introduces the basic terminology for Taxonomies and shows how to traverse
hierarchies of taxonomies and taxa. You'll learn about how to get statistics for a taxon,
retrieve items by a category or tag and how to programmatically add categories and tags.
Dynamic Data
In this chapter you'll learn how to add a new custom field to a content item from the
Sitefinity back end. Then you'll use the DynamicData facade to programmatically list
types and fields. Finally, you'll learn how to read and write custom field values.
Introduction 7
© 2012 Falafel Software
What is a CMS and why do you need one?
A Content Management System (CMS) allows multiple people to contribute website
content from any location. Before CMS, one person received email with web change
requests, managed all the code and recompiled the entire site for each change. Even the
graphic web designer, who made changes continually, had to send email to that one
person. That one person was the bottleneck.
What about business users? Each business group (marketing, accounting, sales, etc.) wants
to own their particular area without the bother of sending a ticket to an IT department and
waiting for the ticket to be received and processed.
CMS lets you split up the work for the web site and store the results in a single database or
file system. Web designers can completely change website look-and-feel without having to
know anything about content. Business users can create news, events and blogs and
completely ignore how their content is presented. CMS "workflow" allows documents to
be approved or rejected before being published, e.g. accounting makes their own changes
and submits for approval while a manager verifies that numbers being published to the
outside world do not conflict with company policies.
While Sitefinity makes it easy to set up the initial website, you must think about
maintaining and extending the website later for new capabilities. You can maintain
Sitefinity content in one place and reuse the content everywhere. Maintenance is largely a
matter of point-and-click, drag-and-drop. Sitefinity is completely extensible so that
developers can integrate with 3rd party packages (e.g. Salesforce), add new custom
widgets and modules.
Sitefinity 58
© 2012 Falafel Software
Sitefinity 3.7 vs. 5.x
Sitefinity was created based on Telerik's internal need for content management of their
own website. Now thousands of companies use the product. Along the way, Telerik
learned about the real world needs for the product. Sitefinity 5 is very different from
Sitefinity 3.7. In fact, you might consider Sitefinity 5 a brand new product with a new
background database and excellent new architectural underpinnings.
One key Sitefinity 5 architecture change is the extensive use of AJAX technology to speed
up administration page refreshes. In Sitefinity 3.7 , you had to wait for the entire page to
refresh. In Sitefinity 5.0, AJAX technology allows a small request to the server and only a
small part of the page is refreshed.
2Setting Up Your Environment
Sitefinity 510
© 2012 Falafel Software
2 Setting Up Your Environment
Objectives
This Chapter covers the basic installation of Sitefinity.
Setting Up Your Environment 11
© 2012 Falafel Software
Installing Sitefinity 5
Once you have downloaded the installation for Sitefinity from www.sitefinity.com, follow
the steps below to install the product.
1. Run the installation. The Welcome page will display. Click the Read License Agreement
button to reviewing the license terms. If you accept the license conditions Click the I
Agree - Continue button to continue.
Figure 1 --The Welcome Screen
2. The Summary page will list the features to be installed. If you want to install the
product in a custom location or specify the features to install, click the Customize
button. Click the Install button to continue.
Figure 2 --Summary
Sitefinity 512
© 2012 Falafel Software
3. The Installing Sitefinity page displays status. No action is required on this page.
Figure 3 --Installation
4. In the Completed Successfully Installation page, leave the Launch Sitefinity Project
Manager option checked and click the Finish button to close the installation wizard and
display the Sitefinity Project Manager.
Figure 4 --Completed Page
Setting Up Your Environment 13
© 2012 Falafel Software
5. The Sitefinity Project Manager provides quick access to creating and configuring
Sitefinity projects.
Figure 5 --Sitefinity Project Manager
Sitefinity 514
© 2012 Falafel Software
Installing the SDK
The Sitefinity SDK includes important resources for development not included directly
with the core Sitefinity install. Once you have downloaded the installation for the Sitefinity
SDK from www.sitefinity.com > Developer Network > SDK, follow the steps below to
install the product.
1. Run the installation. The Welcome page will display. Click the Read License Agreement
button to reviewing the license terms. If you accept the license conditions Click the I
Agree - Continue button to continue.
Figure 6 --The Welcome Screen
2. The Summary page will list the features to be installed. If you want to install the
product in a custom location or specify the features to install, click the Customize
button. Click the Install button to continue.
Figure 7 --Summary
Setting Up Your Environment 15
© 2012 Falafel Software
3. The Installing Sitefinity page displays status. No action is required on this page. The
Installation will also install other Telerik products including RadControls for ASP.NET
AJAX, RadControls for Silverlight and OpenAccess ORM.
Figure 8 --Installation
4. In the Completed Successfully Installation page, leave the Launch Sitefinity SDK Browser
option checked and click the Finish button to close the installation wizard.
Figure 9 --Completed Page
Sitefinity 516
© 2012 Falafel Software
5. The SDK Browser includes a rich set of resources for getting started with Sitefinity,
starter kits, code samples, widgets, blogs, documentation and links.
Figure 10 --SDK Browser
Setting Up Your Environment 17
© 2012 Falafel Software
Summary
In this Chapter you learned how to install Sitefinity.
3Getting Started
Getting Started 19
© 2012 Falafel Software
3 Getting Started
Objectives
In this Chapter you will create a minimal, simple Sitefinity website. The website will
contain a single "Welcome" page populated with text.
Sitefinity 520
© 2012 Falafel Software
Sitefinity Project Manager
The Sitefinity Project Manager is the starting point for creating, managing and browsing
your Sitefinity website. The Sitefinity Project Manager is available from the Start menu
under All Programs | Telerik | Sitefinity <version> | Sitefinity Sitefinity Project Manager.
Use this application to:
Create a New Project brings up the New Project Wizard where you can create a Sitefinity
project on your local file system, in an IIS (Internet Information Services) website on
your machine, a remote web site or using FTP to a remote web site.
Import a Project prompts so you can add an existing project.
The Actions menu and the right-click, context menu contain similar options to perform
against any of the selected projects.
Figure 11 --Sitefinity Sitefinity Project Manager
Getting Started 21
© 2012 Falafel Software
From the Actions menu you can:
Go to the Administration backend of the site.
Browse to display the live site.
Explore the Sitefinity project in the file system.
Upgrade a project to the latest version.
Edit the project in Visual Studio opens the Sitefinity project in Visual Studio.
Show the License Information to see the license constraints such as the product version,
number of concurrent users allowed, number of published pages allowed, etc.
Show Cassini Info displays the Sitefinity Integrated ASP.NET server dialog along with the
Url of the project, physical path, port, and virtual path. You can also start and stop the
server from this dialog.
Remove eliminates the project from the Project Manager and optionally, will delete the
actual files that make up the project.
Set SF3.7 for migration prompts for the location of an existing 3.7 website and migrates
the project to the current version.
Figure 12 --Actions Menu
Sitefinity 522
© 2012 Falafel Software
Dashboard
The Dashboard is the first visible Page when you navigate to Administration. The
Dashboard has the main menu across the top, links to videos and documentation to help
you get started and a "Full Documentation" link at the bottom of the page.
Figure 13 --Sitefinity Administration
Getting Started 23
© 2012 Falafel Software
About Pages and Content
Sitefinity websites are built from two major pieces: Pages and Content. Pages are
containers of data. Content is the data that will be placed in the containers. Once you
create a page, it goes straight into the database. Likewise, any content you create is saved
immediately into the database. You can backup and restore the database and automatically
recreate your entire website.
Sitefinity 524
© 2012 Falafel Software
Front End vs. Back End
Pages and content can be placed in either front-end or back-end locations. “Front-end”
refers to the live published site that the end user will see, while “back-end” refers to the
administration (Dashboard) portion that is used to create sites in Sitefinity but is hidden
from the user.
Getting Started 25
© 2012 Falafel Software
Creating Projects
Sitefinity projects can be created using major technology platforms for websites including:
Right in your own local file system
Using IIS (Internet Information Services)
Remotely, through a FTP (File Transfer Protocol) or HTTP (Hypertext Transfer
Protocol).
The Sitefinity Sitefinity Project Manager makes it easy to get started building your own
websites. You don't have to use IIS (Internet Information Services) or spend days making
sure the web site will work. The Sitefinity installation includes everything you need to get
started building your website.
Lab: Creating a Minimal Sitefinity Website
This Lab demonstrates creating a minimal Sitefinity website stored in your local file
system. In this example we're not going to go into the details, but simply walk through
creating the web site on your local file system. This project will be launched using the
built-in web server.
Sitefinity 526
© 2012 Falafel Software
Creating the Project
1. From the Sitefinity Project Manager click the Create a New Project button from the
toolbar at the top of the window.
Figure 14 --New Project
2. The Create New Project Wizard displays. Enter the Project Name "CarConduit". Click
the Next button to continue.
Figure 15 --Creating a New Project
Getting Started 27
© 2012 Falafel Software
3. The Activate a License page of the wizard displays. Enter your Email address and
Password from your Sitefinity.com account. If you have a license file downloaded, select
the Use a License File You Have Downloaded option and choose the file using the Browse
button.
Figure 16 --Activating a License
Notes
If you have already created a project, then you will be able to select from existing
licenses.
Sitefinity 528
© 2012 Falafel Software
4. Select the Sitefinity edition that fits the requirements of your project.
Figure 17 --Selecting Sitefinity Edition
Notes
Click the Compare All Editions link that navigates to http://www.sitefinity.com/
purchase/license-comparison.aspx where a matrix displays product capabilities,
licensing and pricing.
Getting Started 29
© 2012 Falafel Software
5. Select the Free Trial or Licensed options button. Subsequent steps will verify your
Sitefinity.com login against your licenses. Click the Next button to continue.
Figure 18 --Selecting the Type of Installation
6. The Confirm License page will display the status of your license. Check the Open the
Administration of this Project... option. Click the Finish button to close the wizard.
Figure 19 --Confirming the License
Sitefinity 530
© 2012 Falafel Software
7. The new project will be added to the list in the Sitefinity Project Manager. At this point
Sitefinity has created everything needed for the website except for the database.
8. The Status column for the project will update briefly, then a browser window will open
to display the Project Startup. The first step of the project startup is to Set the Database.
This example assumes you have Microsoft SQL Server Express installed on your
machine with the default instance name of "SQLExpress". Click the Continue button.
Figure 20 --Setting the Database
Getting Started 31
© 2012 Falafel Software
Notes
If you have a full version of SQL Server installed, click the Microsoft SQL Server
option. You will need to provide authentication information, the Server and Database
names before clicking the continue button.
If you don't have SQL Server Express, you can download it from www.microsoft.com/
express/database/.
Each database type will have its own set of authentication entry requirements for the
particular database. The screenshot below shows the entries required for each.
Sitefinity 532
© 2012 Falafel Software
9. The second project setup step is to Register the Administrator for the site. Enter the First
Name, Last Name, Username and Password that will be used to login to your new website
and finally, an Email address. Click the I'm Done button.
The Administrator will be granted all possible rights for the project, including the ability
to add content, pages and new users.
Figure 21 --Registering the Administrator
Getting Started 33
© 2012 Falafel Software
10.Next, you will be prompted to login to the new site. Enter the Username and Password
from the previous step and click the Login button.
Figure 22 --Logging In
11.After logging in, the site administration Dashboard page will display. From here you
can use the menu to navigate between administration tasks.
Figure 23 --The Administration Site
Sitefinity 534
© 2012 Falafel Software
Creating a Page
Now you will create a "Welcome" page for your website.
1. From the administration site, click the Pages menu option.
Figure 24 --The Pages Menu Option
2. Click the Create a Page link.
Figure 25 --The Create a Page Link
Getting Started 35
© 2012 Falafel Software
3. The Create a Page entry form will display. Enter "Welcome" in the Name field.
Figure 26 --Entering the Page Name
4. Scroll further down the form and enter "Welcome to CarConduit" in the Title for
Search Engines field.
Figure 27 --Entering the Page Title
Sitefinity 536
© 2012 Falafel Software
5. Scroll to the bottom of the form, leave the remaining entry fields at their defaults and
click the Create and Go to Add Content button.
Figure 28 --Creating the Page
6. The editor for your new "Welcome" page has a set of content boxes surrounded by
dotted lines. The right site of the page is titled Drag Widgets and contains a number of
widgets that can be dragged into the content areas. Drag a Content Block widget over to
the top box and drop it there.
Figure 29 --Adding the Content Block Widget
Getting Started 37
© 2012 Falafel Software
7. Click the Enter Content link.
Figure 30 --Clicking the Enter Content Link
8. In the Edit dialog that displays, enter the text "Welcome to CarConduit!". Click the Save
button to close the Edit dialog.
Figure 31 --Editing the Content Block
Sitefinity 538
© 2012 Falafel Software
9. At this point we have a minimal page that is working and retrieving data from the
database, but is still in draft mode. The page can't be accessed from the outside world
yet. At this point you have the option to click the Save as Draft button and continue to
work on the page without publishing it. Instead, click the Publish button to make the
new page visible in your new website. This step will return you to Pages administration.
Figure 32 --Publishing the Page
10.In Pages administration locate the Welcome page in the list and click the View link.
Figure 33 --Viewing the New Page
11.The new page will display in the browser. Notice that the address bar shows a
"localhost" address, followed by the project name, then the page name, i.e. "/
CarConduit/welcome". Also notice that the title "Welcome to CarConduit" appears at
the top of the page. Finally, the content "Welcome to CarConduit!" displays in the page
body. The steps for creating rich, complex pages are essentially the same and involve
additional widgets and content.
Figure 34 --The Finished Page
Getting Started 39
© 2012 Falafel Software
Setting the Default "Home" Page
How do you set the default, "home" page?
1. In the Administration list of pages, click the Actions drop down list and select the Set as
Homepage link.
Figure 35 --Setting the Homepage
2. Notice that the "Home" icon appears in the icon next to the page name.
Figure 36 --Home Icon
3. Navigate to the site and the default page is displayed automatically without having to
write out the complete URL in the browser address bar.
Sitefinity 540
© 2012 Falafel Software
Summary
In this Chapter you created a simple Sitefinity website. The website contains a single
"Welcome" page populated with text.
4Pages
Sitefinity 542
© 2012 Falafel Software
4 Pages
Clicking the Pages menu item brings you to Pages administration where you can create
new pages, rework the layout of the page and set the content of the page. Pages
administration has tools to perform all possible actions in Sitefinity.
Figure 37 --Pages
Pages 43
© 2012 Falafel Software
Objectives
This chapter explains the options for creating and configuring a page. Then you'll learn
how to edit page content and layout, paying particular attention to working with the
HTML Editor. A tour of the page administration explores the list of pages and the possible
Actions you can take, filtering and managing pages.
Sitefinity 544
© 2012 Falafel Software
Page Settings
In the Chapter "Getting Started", we did a quick walk-through of building a page without
paying much attention to the detail. As a business user, do you care about any of these
other settings for creating pages? Absolutely! The page settings help get your page noticed
by search engines like Google, Bing and Yahoo (the major three). Other settings determine
how your entire page is arranged. Let's create another page and look at the settings:
1) From the administration site, click the Pages menu option.
2) Click the Create a Page link.
3) The first section of Create a Page is used to name the page and set its location. See the
screenshot below for an example of how to fill this section.
The Name will display in the navigation. The Name "Contact Us" will appear in menus
and other widgets to show the list of pages in the site.
Put this page... places the page at the top, "root" level of the site, or Under parent page...
to select a parent. In the screenshot below, the "Contact Us" page is placed under the
"Welcome" page.
Url is a powerful component of Sitefinity that can specify the how the page will be
accessed in the browser and by internet search engines. Notice that Url does not end
in a suffix like".aspx" as in past versions of Sitefinity. Sitefinity "Navigation rerouting"
allows the Url to be completely different from the Name of the page and does not have
to match up with any technical naming convention. By default, the Url will be the
Name of the page, using dashes in place of spaces. In the screenshot below, clicking
the Change button, renames the Url "contact-us" to "contact-carconduit".
The Show in Navigation checkbox by default makes the "Contact Us" page visible in all
navigation widgets. Uncheck this option if you want the page available but not
immediately visible from navigation menus.
Pages 45
© 2012 Falafel Software
Select the Use this page only to group other pages checkbox to have the page become a
holder for other pages. If you select this option, the remaining sections that come
below (e.g. Title and Description) are eliminated.
Figure 38 --Setting the Page Name and Location
Sitefinity 546
© 2012 Falafel Software
4) Title for Search Engines appears in the page title and is also important for Search Engine
Optimization (SEO). Be sure to enter something here so that Google or Bing will not
ignore your page. Remember, no Title means your page will have a lower search engine
ranking.
Figure 39 --Assigning the Title
Tip!
Google robots look for the dash symbol. Google responds best when the web site
name is followed by a dash "-", then a short description. For example, "Falafel
Software - Home Page".
Pages 47
© 2012 Falafel Software
5) The Template section lets you control the layout of the page, e.g. the header, footer,
toolbars and content areas, how many columns, and how many rows are on the page.
Templates create areas that are ready for you to add content to. Click the Select another
Template button to choose from a list of predefined template layouts.
If you're feeling adventurous you could select the Don't use Template option to start the
page completely from scratch.
Figure 40 --Assigning a Template
Notes
Other templates with custom layouts can be created, but this is not a business
user task. Developers or designers can create templates using drag and drop in
Visual Studio.
Sitefinity 548
© 2012 Falafel Software
6) The Description and Keywords section is another section that's important to define for the
best ranking by search engines. Make the Description short and sweet (two sentences
max). In the Keywords entry, add the most important words first.
Figure 41 --Entering Description and Keywords
Tip!
The key information for the search engines are Title, Description and Keywords. Each
search engine has a slightly different priority for these. Some search engines will go
up to using eleven keywords while some don't use more than eight. If there are too
many keywords, the engine may drop your keywords altogether or just use the first
few. So keep the most important keywords first and don't use too many.
Pages 49
© 2012 Falafel Software
7) The options on the Advanced Options page only need to be changed if a designer or
developer has a specific need. In particular, leave the Allow search engines to index this
page option enabled so the page will be automatically indexed for searching. The other
options fill specific needs:
Check the Require SSL to make the page use the HTTPS protocol. HTTPS is used to
provide secure communication for sensitive information, e.g. credit card numbers.
Enable ViewState is unchecked by default. ViewState is what appears to be garbage
characters inside of HTML and is used by the browser to know how to reload the page
when the browser Back button is clicked. You should only check this option if you
need ViewState and know why you need it. As a business user, you will not need to
use this setting, unless your designer requires it.
Include RadScriptManager is enabled when required by certain AJAX controls. Set this
checkbox if your designer or developer requires AJAX support.
Allow Parameter Validation needs to be checked if you're passing parameters to your
page.
Allow Multiple Urls for this Page
Caching Options should be "As set for the whole site". Later you can set caching for
the entire site at one time from Administration > Settings > Advanced Settings > System >
Output Cache Settings.
Sitefinity 550
© 2012 Falafel Software
Use the HTML included in the <head> tag entry to add script links, style sheet links and
"meta" tags. This text box is used to add certain HTML tags that aren't built into
Sitefinity already. The screenshot below shows an example of a Meta tag used to
refresh the content every 15 seconds from the server. "Expires" is another important
Meta tag used to let search engines know that a particular page or document is no
longer valid after a certain date. You can look up more Meta tag examples online that
you can cut-and-paste into the text box.
Figure 42 --Advanced Options
8) Click the Create and go to add content button to create and edit the page.
Pages 51
© 2012 Falafel Software
Editing the Page
After clicking the Create and Add Content button, the new page will display. If you want
to navigate back to change any of the page information, click the Title & Properties link.
The title of the page shows at the top along with the current page status (should show as
"Draft"). The page is not published and will not be visible to users from the browser. The
page designer shows on the left and widgets on the right. Notice the buttons Content and
Layout at the top right that toggle between the two main views of the designer. Layout
shows where the content will go while Content shows the widgets that will display in the
page.
Figure 43 --Designing the Page
Sitefinity 552
© 2012 Falafel Software
Editing Content
In this walk-through, we will add some generic HTML content with our contact
information, and an image that represents the company and dresses up the page.
1) Click the Content button found at the top of the "Contact Us" page,
2) The right side, labeled Drag widgets, has a list of all the controls that can be dragged to
the box areas on the left side. Sitefinity comes with a set of basic widgets for Content,
Navigation, RadControls, Data , Scripts and Styles, Login, Search, Classification and
Newsletters. We'll start out working with the widgets under the Content title.
3) From the Drag Widgets area on the right side of the page, drag the Content block to the
upper right box area.
Figure 44 --Adding a Content Block
4) Click the Enter Content link. to edit the content block. Note that you can also click the
Edit link at the top right of the widget. Both actions display a RadEditor control.
Figure 45 --Clicking the Enter Content Link
Pages 53
© 2012 Falafel Software
5) The RadEditor is an advanced editor for the web that will allow you work with text or
directly with HTML, insert links, add images, media or Flash. Click the HTML button
located just below the editor window. Paste the following into the editor window:
<p>CarConduit is headquartered in Capitola, California. For more information, please contact us at:</p><p>Toll Free:<br />888 CAR-CONDUIT <br />Phone:<br />555-462-0457 <br />Fax:<br />555-480-4902 <br />email:<br /><a href="mailto:[email protected]">[email protected]</a> </p>
6) Click the Design button, also located at the bottom of the editor window.
7) Click the More formatting options button, located in the upper right hand side of the
editor. Additional insertion and formatting options will show up on the editor toolbar,
and the button will now read Basic options only.
Figure 46 --Enter Text to the RadEditor
Sitefinity 554
© 2012 Falafel Software
8) The screenshot below shows some of the options you may not recognize. In particular,
notice the Image Manager used to insert *.gif, *.jpg and *.png directly from your
computer or out of the Sitefinity database. The Paste Word button is used to get
material from Word documents without the usual large amount of formatting. The
Format Stripper is a related button that has a drop down selection of options where you
can strip out all the css formatting, Word, Span or Font elements from the content.
Pages 55
© 2012 Falafel Software
9) Select the word "CarConduit" with the mouse and click the Hyperlink Manager button.
Enter a web address, complete with the "http://" prefix, click the More options link and
enter a Tooltip. Click the Insert this Link button.
Figure 47 --Inserting a Link
Notes
You can use the LinkTo options to link to an external website,
Sitefinity 556
© 2012 Falafel Software
10)Rest the mouse over the CarConduit link to see the tool tip for the link.
11)The editor can automatically detect web and email addresses. Click the
"[email protected]", then click the Hyperlink Manager. Notice that the LinkTo:
Email option is already selected and the email address is already filled in.
12)Select the text "Toll Free:" and select a blue foreground color. Repeat this for the text
"Phone:", "Fax:" and "email:".
Figure 48 --Selecting Foreground Color
Pages 57
© 2012 Falafel Software
13)Click the HTML tab. Notice the "<a>" tag for the CarConduit hyperlink, the "mailto"
link for the contact email and the span with color styles.
Figure 49 --The HTML View
14)Click the Save button to close the editor. The content block should now look
something like the screenshot below.
Figure 50 --The Complete Content Block
Sitefinity 558
© 2012 Falafel Software
15)Drag the Image widget to the top left box area. Click the Select an image link. In the
Insert an image dialog that displays, notice that you can upload images From your
computer and From already uploaded (images already stored in the Sitefinity database).
From your computer, click the Select... button and locate an image. "BlackTruck.jpg" is
being used in the example here. Enter "Black Truck" for the Alternative text. Leave the
other values at their defaults. Click the Save button to close the dialog.
Figure 51 --Inserting an Image
Pages 59
© 2012 Falafel Software
16)The truck image is too large and has bled into the space for the content block. Click
the Image widget Edit button to begin fixing this.
Figure 52 --Image Widget With Oversize Image
Sitefinity 560
© 2012 Falafel Software
17)Click the From already uploaded link. Select the black truck image. Then click the
Resizing options to open that area. Select the Resize the image width to... option and select
"Small: 240 px width" from the drop down list. Click the Save button to close the
dialog.
Figure 53 --Fixing the Image Size
18)Now the image shows at a reasonable size and is proportionate to the content block.
Figure 54 --Image Widget With Appropriate Size Image
Pages 61
© 2012 Falafel Software
19)Click the Publish button.
20)From the page list, click the View link next to the "Contact Us" page. The page should
look something like the screenshot below.
Q & A...
Q: Is content within the content block indexed?
A: Yes, once indexing is turned on, the content block is included in the search
indexing automatically. News, blogs, etc. are all included in the search.
Sitefinity 562
© 2012 Falafel Software
Editing Layout
Arrange where content will go on the page by editing the layout. You can drag layout
items around quickly in the page without writing any code.
1) Click the Layout button
2) The left side of the page shows the layout designer and predefined areas that will hold
content. Each box in the designer has a hint to "Drag layout elements" to divide the area
into columns.
The Layout Designer
3) From the right side, titled Drag layout elements, drag the 25% + 75% layout element into
the top box.
Figure 55 -- Dragging a Layout Element
Pages 63
© 2012 Falafel Software
4) Now the top box is sub-divided into two areas, one with 25% width and the other with
75%. Click the Edit button.
Figure 56 -- New Layout
5) Move the mouse between the two columns and drag the resize handles to reportion the
column widths. Set the left column to around 20% and the right column to around
80%.
Figure 57 --Changing Column Proportions
Sitefinity 564
© 2012 Falafel Software
6) On the right side of the designer, the Edit Layout Element area allows you to fine tune
the box sizes in either percentages (the default) or pixels. Enter the value "30" in the
space for Column 1. Column 2 is marked as auto-sized and will automatically change to
"70%".
Figure 58 --Changing Sizes
Pages 65
© 2012 Falafel Software
7) Click the Spaces link. The amounts below increase the space between the outside edge
of the content and the area surrounding the content. Change the first column spacing to
have "5" pixels on each side. Change the second column to have "5" pixels on the top,
right and bottom, and "20" pixels to the left. As you edit the amounts, notice the
changes to the columns displayed to the left.
Figure 59 --Editing a Layout Element Spaces
Sitefinity 566
© 2012 Falafel Software
8) Click the Classes link. Each column in the screenshot below is using a predefined CSS
(Cascading Style Sheet) class that's built into the system. You can also use Wrapper to
add styles to the entire box area. If your designer supplies styles for the project, you can
apply those styles here.
Figure 60 --Editing a Layout Element Classes
9) Click the Done button.
10)Click the Save as Draft button.
Pages 67
© 2012 Falafel Software
Tour of the HTML Editor
Initially, the buttons for the HTML Editor show only a minimal set of options. You can
toggle this using the More Formatting Options button located on the right hand side of the
button bar. The screenshot below shows key editor features:
Sitefinity 568
© 2012 Falafel Software
Hyperlink/Remove Link: The Insert a link dialog that displays in response to this button
allows you to create links for web addresses, pages from your Sitefinity site or email. Use
the dialog to set the Web address and Text to display. Options in the dialog allow you to
set the Tooltip, the CSS class and if the link should be opened in a new window.
Figure 61 --Inserting a Hyperlink
Pages 69
© 2012 Falafel Software
Image Manager: The Insert an image dialog that displays in response to this button allows
you to load images from your local computer to your website or use images that have
already been loaded to the Sitefinity database. You can load the image to an Album,
assign Alternative text (to satisfy accessibility requirements) and resize the image
automatically to predefined dimensions (e.g. "thumbnail", "large", etc.) or set custom
dimensions.
Figure 62 --Inserting an Image
Sitefinity 570
© 2012 Falafel Software
Spell Check is performed directly in the HTML editor. A message at the top of the editor
notifies that the editor is in Spell checking mode. Buttons to the right allow you to Finish
spellchecking and Cancel. The list that drops down under each misspelled word contains
alternative correct spellings and options to Ignore, Change Manually or Add the
highlighted word to the dictionary.
Figure 63 --Spell Checking
Pages 71
© 2012 Falafel Software
Paste From Word inserts content without losing the Word formatting. For example, if you
have a heading, subheading and some paragraph text, a standard paste will pick up on
the fact that there's a heading and display it as such, but will lose the detailed font style
formatting. The Paste From Word option retains the detailed font formatting. The next
few screenshots show content in Word, then the same content pasted to the editor
window, then finally the same content Pasted as Word to the editor window.
Figure 64 --The Content in Word
Figure 65 --Using Control-V to Paste Word Content
Sitefinity 572
© 2012 Falafel Software
Figure 66 --Using Paste from Word
The Tables button drops down a list where you can define a table by dragging the mouse
graphically, or use the buttons below to invoke the Table Wizard, add/merge/delete rows
and columns and to set table properties.
Figure 67 --Creating Tables
Pages 73
© 2012 Falafel Software
The Symbols button drops down a list of characters that would otherwise be unavailable
from the keyboard. For example, when you need to paste the Copyright symbol in a
document, you can select it from this list. Select a symbol with the mouse to insert it
into the HTML Editor.
Figure 68 --Inserting Symbols
The Format Stripper button allows you to remove all excess formatting, or just certain
aspects, such as Css formatting. Word formatting is famous for being verbose, so Strip
Word Formatting will remove all that extra HTML.
Figure 69 --Removing Formatting
Sitefinity 574
© 2012 Falafel Software
The Find & Replace button displays a dialog that can search for a given word or replace a
found word with another. The search is performed from the current cursor position
with the search Direction traveling either Up or Down. The dialog includes industry
standard Search Options, Match case and Match whole words.
Figure 70 --Find & Replace Dialog
Pages 75
© 2012 Falafel Software
The Media Manager button displays a dialog that works exactly like Insert an Image
except that the Insert a Video dialog accepts *.wmv files.
Figure 71 --Inserting a Video
Sitefinity 576
© 2012 Falafel Software
The Document Manager dialog allows you to insert any document file. Clicking the Insert
the document or other file button inserts a link to the file in the HTML Editor using the
text in What title to display.
Figure 72 --Inserting a File
Pages 77
© 2012 Falafel Software
Tour of Page Administration
As your own website builds in size and complexity, you will need to work on all your
pages in one place. For example, you may want to search for a certain set of pages, then
publish them all. Page Administration allows you to work on all your pages. The top left of
Page Administration contains the Function Bar, below that the list of pages and to the
right, the Manage Pages area.
Figure 73 -- Page Administration
Page List
Pages are listed in a tree structure. The screenshot below shows our home "Welcome"
page, with the "Contact Us" underneath it. Notice the "House" icon that lets us know that
Welcome page is the default home page. Also notice the green check marks that indicate
these pages are published. Click the name of the page to edit the page or click the View
link to preview the page at any time in a separate browser. The Actions menu provides the
full set of options possible for the page, such as deleting, editing, etc. The Date/Owner
column shows the creation date of the page and the person that created it.
Figure 74 --Page List
Sitefinity 578
© 2012 Falafel Software
Actions
The Actions drop down menu is available for every page. With
the Actions menu you can Delete the entire page, or Unpublish to
make the page invisible to the outside world.
If you want to create a page that's almost the same as an existing
page, you can use the Duplicate option to make a copy. The
duplicated page will have all the same SEO settings, along with
Title, Keyword, Description and content. Before you duplicate a
page, consider using a template for aspects of the page that don't
change. Also be aware that duplicated pages must have a unique
Url.
Click the Set as Homepage option if the page should be the
default when navigating to the site. Only one page can be the
Homepage.
Create a child page adds a new page underneath the current page in the tree hierarchy.
The Edit... section of the Actions menu allows you to go back and edit the Content or Title
and Properties. Permissions determines who can see and perform other actions on the
page. See the upcoming section on Permissions for a thorough discussion on controlling
access to your pages. Revision History allows you to see each of the changes made to the
page, who made these changes and when. If a later version has serious mistakes, you can
also revert to any earlier version.
The Change section of the Actions menu allows you to change the Template for the page.
For example, if I want the page that has a single column and header and footer to use the
Apple style "Promo" layout with three columns, then I can change the template for the
entire page. Be aware that, as of this writing, the content will be removed. You can also
change the Owner for the page so that you can pass off certain pages to other members of
your team so that they can search for pages that they have responsibility for.
Use the Move... section Up and Down options to move the page in the tree hierarchy.
More options may show up on this menu depending on the state of the page. For
example, if the page is locked, the Unlock option will display here.
Pages 79
© 2012 Falafel Software
Notes
All items in the menu will only show up if you have the appropriate permissions.
For example, you might not see the Change Owner option if you don't have the
correct permissions.
Saving Drafts and Publishing
When you click the Save button, the content is recorded in the revision history (shown on
the right of the screenshot below). The revision history allows you to compare versions,
roll back to earlier versions and add notes to particular versions.
Sitefinity 580
© 2012 Falafel Software
Manage Pages
The example site only has a couple of pages right now, but
as you build your own production website, it will become
harder to locate certain pages when you want to maintain
them.
The Manage Pages area to the right of the page list allows
you to Filter pages quickly. The filters shown here are not
random, but reflect Telerik's experience working with
Sitefinity customers in real-world situations. For example,
lack of Descriptions or Keywords are not best practice for
Search Engine Optimization.
Clicking a filter performs an AJAX based search, that is, the page does not refresh and the
search returns more quickly.
You can use the "With No Keywords" filter for example to get the pages where keywords
were left out. You can, of course, just filter to show only your own pages. Using the by
Date modified... filter you can look at the most recent changes, or use a custom date and
time range.
The Manage also > Templates option is a shortcut for Design > Page Templates.
The Permissions for all pages option allows you to change the access to all pages at one time,
controlling what roles can view, edit, modify, change permissions and so forth.
Pages 81
© 2012 Falafel Software
Function Bar
The Function Bar works against all selected pages at one time. The checkboxes to the left
of each page indicate which pages are affected. You can Create a child of the selected page to
extend the hierarchy of pages. The More actions drop down menu includes the ability to
change the page Template (i.e. the predefined overall layout of the page). You can also
restructure your page by dragging and dropping pages.
Figure 75 --Using the Function Bar
To narrow down a long list of items, click the Search... button, enter the text to search for
and click the Search button. The search is not case sensitive and looks for Titles that
contain the search text. Click the Close Search button to return to the unfiltered list of
items.
Figure 76 --Searching for Items
Sitefinity 582
© 2012 Falafel Software
Summary
This chapter explained the options for creating and configuring a page. You learned how
to edit page content and layout, paying particular attention to working with the HTML
Editor. A tour of the page administration explored the list of pages, the possible actions,
filtering and managing pages.
5Content
Sitefinity 584
© 2012 Falafel Software
5 Content
While you can add page content on-the-fly in Sitefinity, the content is kept separately and
can be managed from the Content menu items.
Why is content managed separately in Sitefinity? Imagine you have a company logo, or a
document (say, a legal disclaimer) and you need to change the content. Then, your
organization changes logo images or the legal department has new wording that must be
implemented. If the logo or document is used in hundreds of places on your site, you
would need to update each.
Not only would that be time consuming, forgetting to change the wording on a legal
document on a single page could cause problems for your organization. If the image or
document is kept in a single place, you can make changes once and know that the change
will show up everywhere it is used. Not only that, as you build up libraries of content, you
can mix-and-match existing material to build new pages more easily.
Content 85
© 2012 Falafel Software
Objectives
This chapter tours the Content Menu and demonstrates how to work with each type of
content. You'll learn how to create content, how to use widgets to display content in a page
and how to configure the widget to fine-tune the layout and behavior of the content.
Sitefinity 586
© 2012 Falafel Software
Tour of the Content Menu
The Content menu item lets you add standard subject matter like Blogs, Images and
Events. The initial page for each type of Content will display a message that "no items have
been created yet" and a link to create the first item. The screenshot below shows a
representative example from the News page.
Figure 77 --Link to Create a New Item
When at least one item has been created, the page displays the items in a list. The
screenshot below shows an example of News items. Above the list is a Function Bar
containing Create and Delete buttons, a drop down list of More actions and a Search...
button. To the right of the list is a Manage column with additional actions. The
presentation of buttons and list will vary according to the type of content shown.
Figure 78 --Content List
Content 87
© 2012 Falafel Software
Content Block
News, Events and Content Block are similar to one another with only minor variations.
The simplest item, Content Block, has a title and some HTML. To create a Content Block:
1. Drop down the Content menu and select Content Blocks.
2. This is the first time to visit the Create a Content Block page, so you will see the "No
Content Blocks have been created yet" message. Click the Create a Content Block link.
This will display the Create a Content Block page.
Figure 79 --Creating a Content Item
Sitefinity 588
© 2012 Falafel Software
3. Enter a Title. Below the title area, enter any text or HTML content in the HTML Editor.
Figure 80 --Content Block Title and Content
Content 89
© 2012 Falafel Software
4. Categories and Tags help you organize content and allow search engines to locate and
rank your content. Categories are used when searching the website while Tags are used
by external search engines. In the Categories and Tags area of the page, select the
Categories Change button to add categories. You may also enter a comma-separated list
of Tags.
Figure 81 --Entering Categories and Tags
Q & A...
Question: Do categories have to do with Search Engine Optimization (SEO)?
Answer : Categories are used for searching the site within Sitefinity. SEO is
driven by title, description and keywords.
5. Click the Create this content block button.
6. In place of the "No Content Blocks have been created yet", the items will display in a list
that shows the item Title, a drop down list of Actions, the Owner and the Date.
Figure 82 --The Content Block Page
Sitefinity 590
© 2012 Falafel Software
7. Click the Pages menu item, then click the "Welcome" page link to edit the content.
Alternatively, you can also click the Actions > Edit... > Content.
8. Drag the Content Block widget to the second row, right side column of the "Welcome"
page.
Figure 83 --Adding the Generic Content List Widget
9. Click the Edit link of the Content Block widget.
Figure 84 --Editing Content
Content 91
© 2012 Falafel Software
10.In the Edit dialog that displays, click the Select from existing shared content button.
Figure 85 --Selecting from Existing Shared Content
11.You will see a list of shared content items. Select the "Classic Car Appraisal" item you
created earlier, then click the Done selecting button to return to the Edit dialog.
Figure 86 --Selecting Existing Content
Sitefinity 592
© 2012 Falafel Software
12.Back in the Edit dialog, click the Save Changes button.
Figure 87 --Saving the Shared Content
Notes
The Edit dialog notifies you that the content is shared among any pages that reuse
this particular Content Block. You can edit the content and the changes will ripple
out to all pages where its used.
Content 93
© 2012 Falafel Software
13.Click the Publish button to make the content available to a page on the website.
Notes
If you decide to Save a Draft, the content item is saved in the database, but is not
available to use in a page. Only after the content item is published can you use it and
have it visible in a page.
14.View the "Welcome" page and view the new Content Block.
Figure 88 --Viewing the Content Block
Sitefinity 594
© 2012 Falafel Software
News
News is almost identical to Content Block except that News includes a Summary section
below the HTML Editor and a Additional info section that records the Author of the news
article, the Source name that supplied the news and a Source URL.
Figure 89 --Additional Info
Content 95
© 2012 Falafel Software
1) From the administration menu, click Content > News.
2) Click the Create a news item button.
3) Enter a Title and add content text for your news article.
Tip!
If you're at a loss for words and simply want sample text so you can see how
Sitefinity handles it, you can use "Lorem Ipsum". "Lorem Ipsum" is dummy text
used by designers to simulate content when they're more interested in how the
content will be arranged on the page. For example:
"Duis rutrum nunc mauris, a molestie sem. Morbi semper dictum nulla, ut volutpat
diam luctus in. Aliquam commodo varius lacus non interdum."
Try the Lorem Ipsum generator at http://www.lipsum.com/ to create paragraphs,
words or lists of text. Cut and paste the text into your news article content area or
use one of the browser plug-ins.
4) Click the Click to add summary link. The Summary is important because we can display
this in a list of news without reproducing the entire news item.
5) Click the Publish button.
6) Create and publish a second News item
7) Navigate to the "Welcome" page.
8) Drag the News widget to the left side of the second row.
9) Notice that all news items you have created show up in the list along with the one line
Summary and a link to the full news story.
Sitefinity 596
© 2012 Falafel Software
10)Click the Edit link at the top of the News widget. Notice the three different sections you
can use to tailor the presentation of the news: Content, List Settings and Single Item
Settings. Content lets you show all of the published news, a single news item or filter new
by a combination of Categories, Tags and Dates. Use the One particular news item only...
option if you want the entire news article displayed directly on the page. Leave the
default settings with the All published news option selected.
Figure 90 --Editing News
Content 97
© 2012 Falafel Software
11)Click the List Settings option to configure how multiple news items will be displayed by
the News widget on a page.
Figure 91 --List Settings
Use paging limits the news items that show
at one time and provide links for overflow
news items. This option lets you control the
amount of real estate that gets used on the
page, particularly if you have other material
to fit in.
Use limit shows only X number of items.
You can use this option along with the Sort
news drop down to show a few of the
newest items.
No limit and paging just dumps all your
news items out on the page in a list.
The Sort news drop down list allows you to
order news items by Last published on top,
Last Modified on top, By Title (A-Z), by Title
(Z-A) or As set in Advanced Mode.
List template determines how the news
content will be arranged on the page.
Typically you will choose one of the
predefined templates on the left, e.g. Titles
and Dates. Telerik has presented you with
the usual industry standard layouts, but if
you need a specific layout, you will not hit
the wall. Clicking the Edit selected template
button allows you to change the layout and
content of the template.
Note: Tweaking the template does involve
working in HTML, but you're supplied
with all the fields that Sitefinity has access
to, and Sitefinity creates the HTML you
need so you can cut and paste to your
template.
Sitefinity 598
© 2012 Falafel Software
12)Click the Single Item Settings of the News dialog.
13)The Single Item Settings let you choose to use the Auto-generated page or select an
existing page. Typically, you will use the Auto-generated page option. If you have a
custom page built to display the news, use the Select existing page... option to include
this custom page instead. Leave the default settings here and click the Save button to
close the dialog.
Figure 92 --SIngle Item Settings
Content 99
© 2012 Falafel Software
Q & A...
Question: What does the Advanced button do?
Answer : Advanced shows a list of all possible properties for the widget. For
example, if your organization's designer adds a CSS (Cascading Style Sheet) file
to the Sitefinity project, you could enter the name of a style in the CssClass
property. Clicking the Simple button returns you to the original settings view.
Sitefinity 5100
© 2012 Falafel Software
14)Click the Publish button for the "Welcome" page.
15)Click the View button for the "Welcome" page.
Figure 93 --News List
16)Click the Full story link under one of the news items. This automatically generated
page displays the full news article along with a comment section.
Figure 94 --News Detail
Content 101
© 2012 Falafel Software
Events
Events are similar to Content Blocks but with additional sections to record the event
summary, event start/end dates, location and contact information.
1) From the administration menu, click Content > Events.
2) Click the Create an event button.
3) Enter a Title and add content text into the HTML Editor.
4) Below the HTML Editor, enter a Summary, Event start and Event end. Click the Event
start and event end text boxes to pop up date and time picker widgets automatically.
Figure 95 --The Event Summary
Sitefinity 5102
© 2012 Falafel Software
5) In the Location section, enter the event Street, City, Country and State.
Figure 96 --Event Location
6) In the Contact information section, enter details for the person acting as the main contact
for the event.
Figure 97 --Event Contact Information.
7) Click the Publish button.
Content 103
© 2012 Falafel Software
Tip!
In this example we want to see the event right away. But in a production website
you may want the event to expire after the event has started or expire when the
event is over. You can use the Schedule action from the menu to set start and stop
dates and times for the event. Once the event becomes automatically unpublished,
the event will not be visible on the page.
8) Navigate to the "Welcome" page.
9) Drag the Events widget to the left side of the second row.
Figure 98 --The Events List
Sitefinity 5104
© 2012 Falafel Software
10)Click the Edit link at the top right of the Events widget. Notice that the arrangement of
the Events dialog is very similar to the News dialog. The Content tab allows you to filter
which events to display. The List Settings and Single Item Settings are almost identical
to News except that Events displays Titles, Cities, Dates and Summaries.
Figure 99 --Editing Events
11)Click the Publish button for the "Welcome" page.
12)Click the View button for the "Welcome" page.
Content 105
© 2012 Falafel Software
13)Click the event title link to see the detail. Like news articles, the event detail has a
predefined format that includes all the date, location and contact information. The
format also includes a comments area.
Figure 100 --Event Detail
Sitefinity 5106
© 2012 Falafel Software
Images and Albums
Images are stored in Albums. You can use the default album or create your own. Here are
the steps to create an album and upload images to the new album.
1. From the Administration page, click the Content > Images menu item.
2. In the Images page, click the Create an image library link.
3. Enter an Album name, click the Click to add a description link and describe the album
contents.
Figure 101 --Defining the Album Name and
Description
4. In the Default image size section, click the Resize images... option and select "Small: 240
px width" from the drop down list.
Figure 102 --Defining Default Image Size
Content 107
© 2012 Falafel Software
Notes
If you choose to "Resize images...", you can select from the predefined dimensions
Thumbnail, Small, Medium, Large, or Extra Large.
Figure 103 --Selecting a Maximum Size
Sitefinity 5108
© 2012 Falafel Software
5. In the Advanced section, enter Max album size in megabytes, Max image size in kilobytes
and customize the URL. You don't want to allow people to upload files that are huge
and take over the hard disk on the server. The default is "anything goes", but you
should make a decision on the maximum image size allowed. You can also change the
URL of the image library, the Storage provider can be Database or File System, and you
can also set caching options for both the Server caching and Browser caching.
Figure 104 --Setting Advanced Properties
Content 109
© 2012 Falafel Software
Notes
Caching is set to As set for the whole site as the default. Click the Details link to see
what the current settings consist of. The Details popup shows the caching options,
the HTTP Header equivalent, and the path to reconfigure these settings.
6. Click the Create and go to upload images button.
7. In the Images Page, click the Upload Images link.
8. In the Upload images page, click the Select images link.
Figure 105 --Selecting Images
Sitefinity 5110
© 2012 Falafel Software
9. In the Windows Open file dialog that displays, navigate to image file location. Select and
open one or more image files.
Figure 106 --Selecting Images
10.In the Upload images Page, open the select an album drop down, select the new "Cars"
album.
Figure 107 --Selecting an Album
11.Click the Upload and publish button to store the images. Wait a moment as all the
images are uploaded. When the "images have been successfully uploaded" message
displays, click the View all images button to return to the Images Page.
Figure 108 --Successfully Uploaded Message
Content 111
© 2012 Falafel Software
12. Review the uploaded images.
Figure 109 --Images Page
Sitefinity 5112
© 2012 Falafel Software
Displaying Image Content
You can display a single image using the Image widget, as demonstrated in the "Editing
Content" section. The Image Gallery widget can display a series of images in a number of
formats. To demonstrate, let's create a new page called "Marketplace".
1) From the Pages administration, locate the "Welcome" page, click the Actions menu and
select the Create as child page option.
2) Name the new page "Marketplace", In the Template section, select the "1 Column,
Header, Footer" template. Click the Create and go to add content button.
3) Drag the Image gallery widget to the top box area. All of your uploaded images should
display. Remember that the "Black truck" image was loaded into the default gallery. The
other images have been loaded to the new "Cars" gallery. Both sets of images should be
displayed.
4) Click the Image gallery widget Edit link.
5) The Image Gallery dialog has two links, Images and Settings. The Images link lets you
fine tune which images will be shown and sort the order the images will be displayed in.
Figure 110 --Image Gallery Images Tab
Content 113
© 2012 Falafel Software
6) In the Images tab, under the section title Which images to display?, click the From Selected
Image Library... option. Click the Choose button to display the Choose Image Library
dialog. You can type into the text box at the top to filter the list. The list will update
automatically when you finish typing. Select the "Cars" album and click the Done
selecting button.
Figure 111 --Choosing an Album
7) The Images Gallery dialog should now look like the screenshot below.
Figure 112 --Image Gallery Using Selected Album
Sitefinity 5114
© 2012 Falafel Software
8) Click the Settings link. Settings is a powerful feature that arranges the images and
describes the behavior of the gallery. The two sections in Settings are, 1) Select image
gallery type and 2) Fine tune the selected type.
Figure 113 --Selecting the Gallery Type
Thumbnails + Detail page lists the image left
to right, top to bottom. When you click on
an image, the image is displayed in an
entirely new detail page. Depending on the
"Fine Tuning" settings, the detail page may
also have links to previous and next images
or previous and next thumbnails.
Thumbnails + Overlay improves the user
experience by displaying a selected image
over the top of the gallery images. The user
can click the X button in the upper right
corner of the detail image to close it. From
there, the user can navigate through the
other images.
Content 115
© 2012 Falafel Software
Thumbnail strip also improves the user
experience by display the images in a strip at
the bottom of the widget and the selected
image above the strip, on the same page.
This also allows easy navigation between
images.
Simple List displays all the images vertically but the images are not clickable and
there is no detail view.
Sitefinity 5116
© 2012 Falafel Software
9) The Fine tune the selected type section varies, depending on which gallery types is
selected.
· For all types but the Thumbnail strip, there are three common options. The first two
limit the number of images displayed. These two options are the recommended way
to go. The first option, Use paging, limits the number of thumbnails displayed at any
one time. The second option, Use limit, puts an absolute limit on the number of
images shown. The No limit and paging option could be slow if there are a lot of
images and could be difficult for the user to navigate.
· If you select Thumbnails + Detail, the Fine tune... section includes a checkbox to Show
links to the previous and next image.
Figure 114 --Fine Tuning the Image Gallery
Tip!
The lightbox option resizes the detail image automatically. You may need to get
larger, higher quality images to display in the lightbox. It's also a good idea to make
sure the images that display together in the lightbox are a similar size.
Content 117
© 2012 Falafel Software
10)Try each of the gallery types, save your settings for the Image Gallery, Publish the page
and view the results.
Sitefinity 5118
© 2012 Falafel Software
Video
Video Size and Behavior
Before you start uploading lots of videos to Sitefinity, you need to know how videos are
stored, retrieved and played back.
Be aware that when a video is uploaded to Sitefinity, the video is uploaded to the
database, not as a separate file. So if you upload a 7mg video, the Sitefinity database
grows by 7mg.
When the user starts a video that is stored in a file, the video is "buffered" on the client
machine, where after the first 20% or so of the video is read, the video starts to display. If
the video is coming from a database, then the entire video must be read before it can
start to play.
The implication is that large files, 5mg plus as a general rule, should be left as files. The
tradeoff is that loading everything into the database is good for deployment and the
uploaded data is accessible throughout the site using the built-in widgets.
Content 119
© 2012 Falafel Software
Uploading and Configuring Video
Videos are handled very much like Images and are uploaded to Libraries.
1) From the administration menu select Content > Videos.
2) Click the Upload videos link.
3) Click the Select videos link.
4) Select the a sample video that ships with Windows, or any *.wmv file you have
available.
5) Click the Upload button. Depending on the size of your video and the speed of the
machine, the upload can take some time.
6) Click the View all videos button.
Figure 115 --The Uploaded Video
7) Click the Embed this video link.
Figure 116 --Embedding a Video
Sitefinity 5120
© 2012 Falafel Software
8) The Link or embed dialog provides a Link that can be placed in email or Instant
Messenger. The Embed tag can be pasted into an HTML page for Mozilla and IE based
browsers. Close this dialog.
Figure 117 --Getting a Video Link or Embed Tag
9) Drop down the video's Actions menu (just below the video thumbnail) and notice that
you can Play the video directly without having to view the page.
Figure 118 --Playing the Video
Content 121
© 2012 Falafel Software
10)Select the video's Actions > Edit Properties. This displays the Edit Video page where you
can change the video Title, Thumbnail, Author and Description. Click the Thumbnail
Change button.
Figure 119 --Changing the Thumbnail
Sitefinity 5122
© 2012 Falafel Software
11)The Generate Thumbnails dialog pops up and lets you take snapshots of the video as it
plays. Just click the Get the currently displayed frame button to save off a thumbnail
image. You can save off multiple thumbnails to the thumbnail strip below the playing
video. Select the thumbnail that you want displayed in the page and click the Done
button.
Figure 120 --Generating Thumbnails
12)Click the Publish button for the video. The published video now displays the new
thumbnail.
Content 123
© 2012 Falafel Software
Using Video Widgets
1) Click the Pages menu option.
2) Create a new child page under the home "Welcome" page named "Featured Videos".
3) Click the Create and go to add content button.
4) Drag a Video widget to the top row of the page. Notice that, in place of an image from
the video, a message tells us that the page must be published before the video can be
displayed.
5) Click the Video widget's Edit link.
6) In the Insert a video dialog, click the From already uploaded link. Select the video that
you previously uploaded and click the Save button.
Figure 121 --Inserting a Video
7) Click the Publish button for the page.
Sitefinity 5124
© 2012 Falafel Software
8) Click the View link for the "Featured Videos" page. The Video widget displays with a
"Play" button arrow. Click the arrow to view the video. The video player displays with
all the industry standard controls like play, pause, a time line, volume controls and a full
screen button.
Figure 122 --Viewing the Video
9) Navigate back to editing the "Featured Videos" page.
10)Remove the Video widget and drag the Video gallery widget to replace it.
Content 125
© 2012 Falafel Software
11)Click the Video gallery Edit link. The Video Gallery edit dialog is very similar to the
Image Gallery. There is a link for Videos, where you can limit the display to All published
videos, From selected library and Upload new videos.
Figure 123 --Video Gallery Settings
12)Click the Settings link. Like the Image Settings dialog, this dialog is split up between
two sections, 1)Select video gallery type and 2) Fine tune the selected type.
· In the Select video gallery type section, you can choose Thumbnails + Detail page or
Thumbnails + Overlay. These work the same as their Image counterparts.
Sitefinity 5126
© 2012 Falafel Software
· In the Fine tune the selected type section, you can limit both the number of items the
gallery shows and the size of the thumbnails. To get the best control over your page
real estate, select either the Use paging or Use limit options.
Figure 124 --Fine Tuning the Gallery
13)Select the Thumbnails + Overlay (lightbox) option.
14)Click the Save button.
15)Publish and view the page.
Q & A...
Question: What player is being used to play the video, Flash?
Answer: Sitefinity uses the Silverlight player . The Silverlight player is able to
use the video hardware acceleration on your computer and can produce a
smooth playback.
Content 127
© 2012 Falafel Software
Lists
Use the Lists content to display a series of values and descriptions. Lists can be useful to
show relatively small collections of codes, categories or other designations, for example
priorities, color coding or quality flags. These can be displayed in the page as simple lists,
expandable lists, anchors, etc. Each List has a title for the list as a whole, e.g. "Priority".
Each list has a number of ListItems, each with their own Title and Content, e.g. "High",
"Medium" and "Low".
Sitefinity 5128
© 2012 Falafel Software
Creating Lists
The walk-through demonstrates creating a simple "Priority" list.
1) From the administration menu, click Content > Lists.
2) Click the Create a List button.
3) Enter a Title for the list. In this example we will create a "Priority" list.
4) Click the Create this list button.
Figure 125 --Creating the List
5) Click the Create a list item button.
Figure 126 --Creating the List Item
Content 129
© 2012 Falafel Software
6) Enter the Title as "High", and content in the HTML editor as "High Priority". Click the
Publish button.
Figure 127 --Populating the List Item
Tip!
Using the HTML editor, you can insert images from Albums that will display in the
list. Click the Image Manager button to select images already in your albums or
upload new images on your local disk.
7) Click the Create a list item button. Enter the Title "Medium" and HTML content
"Medium Priority". Click the Publish button.
Sitefinity 5130
© 2012 Falafel Software
8) Click the Create a list item button. Enter the Title "Low" and HTML content "Low
Priority". Click the Publish button.
9) The list should now look something like the screenshot below.
Figure 128 --The Finished Priority List
Content 131
© 2012 Falafel Software
Using Lists in Pages
The walk-through demonstrates adding a simple "Priority" list to a page.
1) Navigate to a page that will contain the list.
2) From the Widgets on the right side, drag the List widget to the page.
Figure 129 --Adding the List Widget
3) Click the Set which list to display link to display the Edit dialog.
4) In the Content tab of the Edit dialog, click the Select lists button. Check the "Priority"
list and click the Done selecting button.
5) Click the Settings link.
6) Select the Expandable list radio button.
7) Click the Save button to complete the Edit dialog and view the changes.
Figure 130 --List Displayed in Page
Sitefinity 5132
© 2012 Falafel Software
Blogs
Blogs are used to publish recent news and allow commentary by readers to form an online
conversation. A successful blog can also be "syndicated" to other websites over various
standards such as RSS (Really Simple Syndication). Sitefinity makes it easy to create blogs
for as many groups or subjects as needed. For example, you could have a blog for each
subject your site covers (e.g. "Deserts", "Main Course" for a cooking site), or a blog for
each department in your organization, or even a blog for each person in smaller
organizations. The blog will contain blog posts, i.e. articles that relate to the blog content.
Content 133
© 2012 Falafel Software
Blog Engine
When someone says "I wrote a blog", they are usually talking about a "blog post". The blog
itself is the blog engine that contains blog posts. Your first step will be to create the blog
engine.
1) Drop down the Content menu and select Blogs.
2) Click the Create a Blog link. This will display the Create a Blog page.
3) Set the Title to "Classic Cars Blog".
· Allow Comments: Some medical, government or other public organizations may not
want comments. If possible, you should allow comments to create a lively discussion
and a sense of community. You can limit comments so that only registered users can
contribute. You can also moderate comments so that comments have to be approved
before appearing on the site. By default, comments are allowed by anyone and are not
moderated.
· Alternative Publishing: By default, blogs are published as RSS (Really Simple
Syndication) to be read by GoogleReader or other news readers that accept RSS or
ATOM feeds. This allows your news to be syndicated, that is, your blogs are made
available to multiple other websites.
Figure 131 --Creating a Blog
Sitefinity 5134
© 2012 Falafel Software
4) Open the Alternative publishing (Rss) section.
5) Click the Change button. This will display the RSS feed page so that you can fine-tune
the settings. Enter the Url name "classics" and click the Done button.
Figure 132 --RSS feed Settings
RSS or Atom to generate?: This set of
options adjusts the standard used to
publish the feed. Both standards are widely
used and can be handled by most popular
feed readers.
Url name: This must be entered to create
the full url used to access the blog. Most
browsers will recognize and format the
blog automatically. This support is built
into recent versions of Internet Explorer,
FireFox and Safari. Google Chrome
currently requires an extension to format
blogs.
Limit the items in the feed: To keep the
material fresh, limit the number of posts
shown in the blog to the newest items.
An item in the feed contains: By default, each
post shows both the title and content. You
can cut this down to the title and a certain
number of characters of the post or even
show the title only.
Content 135
© 2012 Falafel Software
6) Based on the Url name that you entered, the Alternative publishing section now includes
a link to the blog. Make a note of this link for later use.
Figure 133 --RSS Feed Link
7) Click the Create this blog button. This will bring you to the Blog Posts page.
Sitefinity 5136
© 2012 Falafel Software
Blog Posts
You have created a Blog, i.e. the container for posts. Now you can create the actual blog
posts.
1) From the Blog posts page, click the Create a Post link.
Figure 134 --Creating a Blog Post
2) In the Create a post page, enter a Title, then text to the HTML editor.
Figure 135 --Entering Title and Content
Content 137
© 2012 Falafel Software
Tip!
Insert images to the HTML editor using the Image Manager button located on
the HTML editor toolbar. You can load images from your local hard drive or use
images that are already uploaded to Sitefinity.
3) Click the Summary > Click to add summary link and add a line or two of text that sums
up the post.
Figure 136 --Adding a Summary
Sitefinity 5138
© 2012 Falafel Software
4) From the More actions button at the bottom of the page select Schedule Publish/
Unpublish. Using the date and time pickers for the Publish on field, set a date in the
future that lands on a Monday at 6am.
Figure 137 --Scheduling Publication
Content 139
© 2012 Falafel Software
Tip!
When it comes to blogging, all days of the week are not created equal. You should
publish your blog early on Monday, around 5-6am. Later in the week, blog posts get
lost in the shuffle and won't be read. The worst days to blog are Friday, Saturday
and Sunday. Early Monday, the new blog posts come in and bury the weekend
posts. The scheduling feature makes it easy to write your blogs at any time of the
week and schedule them to show up at the optimum time.
5) The Blog posts page shows the new post with the "Clock" icon and the scheduled
publish date and time.
Figure 138 --Scheduled Post
6) We will want to see this blog immediately, so click Publish from the Actions menu.
7) Click the All blogs link.
Figure 139 --Navigating to All Blogs
Sitefinity 5140
© 2012 Falafel Software
8) From the Blogs page you can see the new blog has a single post. From here you can
Create a post, use the Edit posts link to list all the posts for this blog or use the Actions
drop down to Delete, edit the Title & Properties or edit the Permissions.
Figure 140 --Blogs Page
Content 141
© 2012 Falafel Software
Using RSS Feeds
Using the link to the RSS feed, plug this link into the address bar of your browser. If you
don't have the link, the general format is:
http://<base website url>/Feeds/<feed name>
In the example, the link was:
http://localhost:47632/CarConduit/Feeds/classics
Viewing the example in Internet Explorer produces the result in the screenshot below. The
blog will be formatted something like this example using Internet Explorer, FireFox and
Safari. Google Chrome requires that an RSS Reader extension be configured for the
browser.
Figure 141 --RSS Reading
Sitefinity 5142
© 2012 Falafel Software
Using Blog Widgets
In this example, we only have a single blog post, but you can have as many blogs and blog
posts as you like. You can also use as many Blog Widgets on the page as you need to
display listings of multiple blog posts or smaller groups of blog posts.
1) Click the Pages menu item.
2) Create a new child page under the "Welcome" page titled "Blogs", then click the Create
and go to add content button.
3) Drag a Blog Posts widget to one of the boxes on the page. Notice that the blog post
shows up immediately. This is ok when you only have a single post, but you will need a
way to select the blog posts that show.
4) Click the Blog posts widget Edit link. Click the From selected blogs only... option.
The Blogs dialog will look similar to the News and Events versions where you have a
Content link, a List Settings and Single Item Settings. The Content link lets you show all
blogs or only selected blogs. You can narrow down the blogs to a single post or select
posts by a combination of categories, tags and dates.
Figure 142 --Blogs Settings
Content 143
© 2012 Falafel Software
5) Click the Select a blog button. Select the blog you created earlier and then click the Done
selecting button.
Figure 143 --Selecting a Blog
6) Click the List Settings link. Click Titles, dates and full content from the List template
section.
Like News and Events, you can limit the
number of items in the list to an exact amount,
"page" the items to a certain number of items
per page or simply dump out everything on
the page at once (not recommended).
Use the Sort blog posts drop down to sort by
Last published, Last modified, alphabetically or
As Set in Advanced mode.
List template controls the format of the list so
that you can see the entire post at one time or
just a "teaser".
7) Click the Save button to close the dialog.
Sitefinity 5144
© 2012 Falafel Software
8) Publish and view the page.
Figure 144 --The Finished Blog Post
Content 145
© 2012 Falafel Software
Documents
Use Documents when you want to include a link to a PDF, Word or other file. These are
contained in Libraries. You can also display links to a single document or all documents in
a library.
Sitefinity 5146
© 2012 Falafel Software
Create Libraries and Documents
1) From the administration menu Content, select the Documents & Files option.
2) Click the Create a library link.
3) Enter the Library name. Click the Click to add a description link and enter some text
there.
Figure 145 --Defining the Library
4) Open the Advanced area. You don't want huge file uploaded to the server hard drive.
Pick a maximum size, for example 2 MG, per file and enter it as the Max document/file
size.
Figure 146 --Limiting the File Size
Content 147
© 2012 Falafel Software
5) Click the Create this library button.
6) Click the Upload documents or other files link.
7) Click the Select documents or other files link.
8) Navigate to a Word file and select the file.
9) Click the Add more button and select another type of file.
10)Drop down the Where to store the uploaded documents or other files? list and select the
library created in previous steps.
11)Click the Upload and Publish button.
Figure 147 --Starting the Upload
Sitefinity 5148
© 2012 Falafel Software
12)Click the View all items button. Sitefinity detects the type of files that are uploaded and
places the matching icon.
Figure 148 --Document Items
13)Click Embed link to this file of the first file in the list. This link can be used to paste into
an email or Instant Messenger.
Figure 149 --Retrieving the File Link.
14)Close the window.
Content 149
© 2012 Falafel Software
Add Document Links to Pages
How do you add a link to a document or show a list of documents on the page?
1) Click the Pages menu item.
2) Open the "Welcome" page for editing.
3) Drag a Document Link widget to the bottom of the page, below any of the other widgets
or boxes on the page. This will automatically create a new area on the page.
4) Click the Document Link widget Edit button. This brings up the Insert a document or other
file dialog. Click the From already uploaded link. Select one of the files and click the Save
button.
Figure 150 --Inserting a Document
5) Click the Preview button. The link displays along with an appropriate icon. Click the
document link. Depending on the default behavior and configuration of your browser,
the document may display in the browser or prompt to download.
6) Close the preview.
7) Delete the Document Link from the page using the widget's More > Delete link.
Sitefinity 5150
© 2012 Falafel Software
8) Drag a Download list widget to the bottom of the page. By default, the list will show all
the documents from all libraries.
9) Click the Download List widget Edit button. The layout of this dialog closely matches the
dialogs for New, Events or Blogs. You can include all documents, from a selected library
or upload new documents. The documents can be sorted Last published, Last Modified,
As they are ordered in library and As set in Advanced mode.
Figure 151 --Download List Dialog
10)Click the Settings link to manage the layout details of the widget. There are two areas,
1) Select type and 2) Fine tune the selected type.
Content 151
© 2012 Falafel Software
The type of layout display as a List with the link at
the top of each file.
The Table type arranges the document information
in a grid with the link to the right side of each entry.
The last two options display the list or table with a
link to a detail page where you can download the
file. The screenshot here shows the detail page.
The Fine tune... part of the dialog changes slightly
based on the selected type.
The section at the top controls the number of files
shown at one time.
The lower part of the dialog controls whether icons
are shown on the page and their size.
The two Detail page options have check boxes that
place the Download link above or below the
description.
Sitefinity 5152
© 2012 Falafel Software
11)Click the Save button to close the Download list dialog.
12)Publish and view the "Welcome" page.
Content 153
© 2012 Falafel Software
Forms
If you want to get information from users, you certainly don't want to wait for a developer
to create a form. Using Sitefinity you can create your own form easily, without any
programming. The user fills out the form online, clicks the submit button, and the
information is stored in the Sitefinity database. How do you access the information sent by
hundreds of people? The responses are all visible in the administration Responses list
where you can view or export to Excel.
Sitefinity 5154
© 2012 Falafel Software
Creating a Form
1) Click the administration menu Content > Forms item.
2) Click the Create a form link.
3) Assign a Title for the form. You can also assign a Name if developers will be using the
form. The Name will be filled in automatically based on the Title or you can click the
change button and use your own organizations naming convention. Click the Create
and go to add content button.
Figure 152 --Form Title
4) The form designer looks very much like the designer for pages, except with a different
set of widgets.
5) Drag a Textbox widget to the box area on the form. Sitefinity knows that you will need
a submit button to collect the information, so the submit button is added automatically
along with the Textbox widget.
Figure 153 --Adding a Textbox Widget
Content 155
© 2012 Falafel Software
6) Click the Textbox widget Edit link. The Textbox dialog that displays has links for Label
and texts for the content and instructional text, Limitations to validate the Textbox input
and Appearance to manage the Textbox size and CSS class. In Label and text, enter the
following:
· Label: "Email"
· Instructional text: "Please enter your email address"
· Make required: check this box. This will prevent the form from being submitted until
this field is filled in.
Figure 154 --Textbox Label and Text
Sitefinity 5156
© 2012 Falafel Software
Notes
The Advanced > Name for developers is the ID that a developer can use to access a
particular widget in code. For example, if you wanted to send an email when the
user clicks the submit button, the email address could be extracted from the
Textbox widget and an email sent automatically.
7) In Limitations > Range, enter a Min of "5". In the Error message displayed... enter "Email
must be at least 5 characters long".
8) In Appearance > Text box size, drop down the list and select Large.
9) Click the Save button to close the dialog. The form now looks something like the
screenshot below.
Figure 155 --The Form In-Progress
10)Drag a Multiple choice widget below the Textbox. Click the Edit link.
· In Label, enter "Your question is about..."
· The Choices section will have three choices predefined. Change the text for the First
Choice to "Classic Cars" and the Second Choice to "Performance Cars". Click the
minus "-" button next to the Third Choice to remove it.
· Select the Add 'Other' as a last choice check box.
· Select the Appearance link. In the Text box size options, select Inline (side by side).
Content 157
© 2012 Falafel Software
· Click the Save button. The Multiple choice widget on the page should now look
something like the example below.
Figure 156 --Multiple Choice Widget
11)Drag a Paragraph text box widget below the Multiple choice widget. Click the Edit link.
In Label and text, enter the following:
· Label: "Question".
· Instructional text: "Please enter your question and include specific details".
· Make required: This checkbox should be selected.
· Click the Save button. The form should now look like the screenshot below.
Figure 157 --The Completed Form
Sitefinity 5158
© 2012 Falafel Software
12)On the upper right side of the form, above the widgets, locate the Settings button and
click it. This will display the Settings area to the right of the form.
Restrictions can be tailored to the particulars of a form. For
example, for an informal poll you could restrict to only One
entry per IP, that is, each computer would only be able to
submit the form one time. Attempting to submit the form a
second time displays an error message to the user. The One
entry per username option would be useful if the form
collected user registration information. The No Restrictions
option makes sense for things like general questions or
trouble tickets to a support group.
Confirmation options control what the page does when the
page is submitted. By default a "success" messaged is
displayed on the page. The Redirect to a page... option
requires the full Url of the page in the form of:
http://mydomain.com/mypage
The Label placement drop down places widget labels to Top
aligned, Right aligned or Left aligned. The screenshot below
shows labels left aligned.
13)Click the Publish button.
Content 159
© 2012 Falafel Software
Adding a Form to a Page
1) Click the Pages menu item.
2) Create a new child page under the "Welcome" page and name it "Q & A".
3) Drag a Form widget to one of the box areas on the page.
4) Click the Select a form link on the Form widget.
5) Select the "Ask CarConduit a Question" form.
6) Click the Done Selecting button.
7) View the "Q & A" form.
8) Click the Submit button without filling out the form. Error messages appears below the
Email field to indicate that the field is required and that it must be at least 5 characters
long. These errors are in response to the Make Required checkbox and the Limitations
Range > Min length setting.
Figure 158 --Validation for the Textbox
9) Fill out the form and submit it.
Figure 159 --Filling out the Form
Sitefinity 5160
© 2012 Falafel Software
Viewing Reponses
1) Click the administration menu Content > Forms. Notice the link to 1 responses.
Figure 160 --The Forms List
2) Click the 1 responses link. This takes us to the Responses for... page where we can see the
key information about each response. One column shows for every field you added to
the form.
Figure 161 --Responses List
3) If you click one of the response items, the detail shows up to the right. This detail
includes the date and time the response was submitted and the IP address origin where
the response was sent from.
Figure 162 --Responses Detail
Content 161
© 2012 Falafel Software
4) Click the Export as Excel button. This will prompt for a location on your hard drive
where you can save the CSV file for use within Excel. Displaying responses in Excel
shows very detailed information that also includes all the form fields.
Figure 163 --CSV Output in Excel
Sitefinity 5162
© 2012 Falafel Software
Social Sharing Options
Buttons for sharing most content types can be added automatically simply by selecting a
checkbox Enable social share buttons in the content editing dialog.
Figure 164 --Enabling Social Sharing
The screenshot below shows a Content Block with the social share buttons included.
Figure 165 --Content w ith Social Share Buttons
Content 163
© 2012 Falafel Software
You can configure the buttons that will show up from Administration > Settings > Social
Sharing. Select the sharing sites you want included, select the icons style for small icons or
Icons with text and finally, click the Save Changes button.
Figure 166 --Configure Social Sharing
Sitefinity 5164
© 2012 Falafel Software
Summary
This chapter toured the Content Menu and demonstrated how to work with each type of
content. You learned how to create content, how to use widgets to display content in a
page and how to configure the widget to fine-tune the layout and behavior of the content.
6Permissions
Sitefinity 5166
© 2012 Falafel Software
6 Permissions
Use permissions to get fine-grain control over all your Sitefinity assets. A Permission allows
a user to perform some action, e.g. edit a page, delete a blog post or make a comment. A
Role is a collection of permissions. A User can be assigned one or more roles to obtain the
permissions for those roles.
Permissions 167
© 2012 Falafel Software
Objectives
This chapter explains how the built-in roles are used, how to create a role, how to create a
user and how to assign roles to users.
Sitefinity 5168
© 2012 Falafel Software
Built-In Roles
Lets first look at the built-in roles that come with Sitefinity. Click the Administration >
Roles menu item. These roles cover the major tasks performed in Sitefinity.
· Administrators can perform any action, anywhere in the system.
· BackendUsers can login to the Administration "backend" section of the web site.
· Editors have less privileges than Administrators or BackendUsers but still have wide
authority over content.
· Designers can't do anything with content directly, but have control over pages and
templates.
· With the least amount of privileges, Authors can create content but can't set
permissions or perform deletes.
Figure 167 --Built-In Roles
Permissions 169
© 2012 Falafel Software
Creating a Role
1. Click the Create a role button. In the Role text box that appears, enter "Bloggers" and
click the Create button.
Figure 168 --Creating a Role
2. Click the Permissions link for the "Blogger" role.
Figure 169 --Setting Permissions
3. The extensive list of permissions covers all possible capabilities of a user in Sitefinity.
Scroll through the list and notice that, by default, the role has no permissions. Without
enabling some permissions, users with this role will not be able view, create, modify or
delete anything in the system.
Figure 170 --List of Permissions for a Role
Sitefinity 5170
© 2012 Falafel Software
4. Locate Blogs > BlogPost section of the list.
5. Click the Change button.
6. Enable the View blog post and Modify blog and manage posts check boxes.
Figure 171 --Enabling View and Modify
7. Click the Done button to close the dialog.
8. Click the Back to all items link.
Permissions 171
© 2012 Falafel Software
Creating a User
1. Select the Administration > Users menu item.
2. Click the Create a user button. This will display the Create a user page.
3. All fields in the first section of the Create a user page are required except for Photo and
Nickname.
Figure 172 --Entering Required Information
Sitefinity 5172
© 2012 Falafel Software
4. By default, the This user can access site backend option is checked. This actually includes
the Backenduser role for this user automatically. Leave this option checked. Also select
the new "Bloggers" role.
Figure 173 --Configuring Roles and Access
5. Click the Create this user button.
6. The new user shows up in the Users list.
Figure 174 --New User In List
Permissions 173
© 2012 Falafel Software
Test the New User
1. Click the Logout link found in the upper right corner of the page.
2. Login as the new user.
Figure 175 --Logging in as the new user
3. Logout and log back in as the new "Blogger" user. Now the administration menu
should include both the Dashboard and Content menu items. You should be able to
select the Content > Blogs menu item, open the existing blog you created earlier, add
blog posts and edit blog posts.
Figure 176 --New User w ith Permissions
Sitefinity 5174
© 2012 Falafel Software
Summary
This chapter explained how the built-in roles are used, how to create a role, how to create a
user and how to assign roles to users.
7Workflow
Sitefinity 5176
© 2012 Falafel Software
7 Workflow
A Workflow is an approval process for publishing documents. By default there are no
workflows, so you can publish a document directly without any additional steps. A simple
workflow might have just two steps, one to approve the document (perhaps a manager
must review before the document is published) and the publishing step itself. For some
medical, government or other organization that has a strict hierarchy or protocol for
publishing may have many steps in their workflows.
Workflows also include notification so that a manager will receive an email that there is
something waiting for approval and that the content will not be available without
approval.
Workflow 177
© 2012 Falafel Software
Objectives
In this chapter you'll learn how to define and test a workflow.
Sitefinity 5178
© 2012 Falafel Software
Defining a Workflow
To define a workflow:
1) In the Administration menu, click the Settings & configurations > Workflow item.
2) No workflow has been created, so click the Define a workflow link. The Select a type
page shows. Leave the default Approval before publishing.
Approval before publishing is a single level of approval before the content is published
and available on the website.
2 levels of approval before publishing is for organizations that need multiple levels of
approval. If you select this option, you need to define the two roles that need to
approve the content.
Figure 177 --Selecting a Workflow Type
Workflow 179
© 2012 Falafel Software
3) Now the Properties page of the workflow definition displays.
Enter a Name for the workflow.
Figure 178 --Entering the Workflow Title
Sitefinity 5180
© 2012 Falafel Software
In the Set approvers area, select the role that will approve items. Click the Add roles or
users button. In the Select roles or users dialog, select the check box next to one or more
roles. In this example we check the "Editors" role. Click the Done selecting button to
close the dialog.
Figure 179 --Selecting the Roles to Approve the Workflow
Workflow 181
© 2012 Falafel Software
Back in the Set approvers area, the "Editors" role is included. Also select the Notify users
by email when an item is waiting for their approval checkbox. Now, whenever an item
has to be approved, everyone who has the "Editors" role will automatically be sent an
email. Note that the email format is built-in, but can be changed by a designer.
Figure 180 --The Approvers and Email Notification
The Scope section defines where the workflow will apply. Leave the default All content
and pages selected. This means that the workflow will be triggered anytime the Save
button is clicked for any pages or content.
Figure 181 --Setting the Scope
The last two options for the workflow can be left with their default values. The Allow
administrators to skip the workflow is recommended so that you don't have to slog
through the approval process when you're making a lot of changes to the backend.
Click the Save workflow button.
Sitefinity 5182
© 2012 Falafel Software
Notes
For the Notify users by email when an item is waiting for their approval option to work
properly, you must set up an SMTP email server at Administration > Advanced >
System > SMTP (Email Settings).
Workflow 183
© 2012 Falafel Software
Testing the Workflow
1. Log out and log back in as the user you created for the previous Permissions example.
2. Edit one of the existing blog posts.
3. Notice there is no Publish button. Instead, click the Save Draft button.
4. Click the new Send for Approval button. Now the list of blog posts shows a new status
indicating the content is waiting on approval. A user with an Editor role (or an
administrator) can publish the content.
Figure 182 --Blog Waiting for Approval
Sitefinity 5184
© 2012 Falafel Software
Summary
In this chapter you learned how to define and test a workflow.
8Analytics
Sitefinity 5186
© 2012 Falafel Software
8 Analytics
Google Analytics can be run directly in a dashboard without having to leave Sitefinity to
study website activity. This dashboard displays using Silverlight, so its highly interactive.
You can run the mouse over individual data points for detailed data or use mapping
features to locate website activity and drill down for more detail in the Bing map.
Q & A...
Q. Where do I add the tracking code for Google Analytics?
A. Register for Analytics and get the Javascript at www.google.com/analytics.
You can drag and drop a Scripts and Styles Google Analytics widget onto your
page or template. Edit the widget and paste the Javascript snippet.
Analytics 187
© 2012 Falafel Software
Objectives
In this chapter you will learn how to setup Analytics. A brief survey of the Analytics
interface will show you the kinds of web traffic information you can generate and analyze.
Sitefinity 5188
© 2012 Falafel Software
Setup
When you first click the Sitefinity Administration Analytics menu item, the First Time
Setup and Configuration wizard will display.
1) Select the user that will administer Analytics. Click the Next step button to continue.
Figure 183 --Selecting Administrators
2) Enter your Google Analytics user name and password and click the Get Analytics
Accounts button.
Figure 184 --Entering Google Analytics Information
Analytics 189
© 2012 Falafel Software
3) Select an available Google Analytics account from the drop down list and then click the
Save Settings button.
Figure 185 --Selecting an Account
4) Click the Copy in clipboard button to get the JavaScript to be used in the Google
Analytics widget.
Figure 186 --Copying the Google Analytics Tracking Code
Sitefinity 5190
© 2012 Falafel Software
5) The "How to use" page of the wizard provides a reminder of the next steps you can take,
i.e. navigate to Analytics using the Go to Analytics button or clicking the Configuring the
Google Analytics widget link for more information.
Figure 187 --How to use Google Analytics
Analytics 191
© 2012 Falafel Software
Using Analytics in the Administrator
The dashboard provides a high-level overview of all your traffic, including:
Number of daily visits
Page views
Average pages per visit
Bounce Rate
Average time on site
New visits rate
Traffic origin, i.e. direct traffic, from search engines, from referring sites.
Figure 188 --Analytics Dashboard
Move the mouse cursor over the data
points to get fly-over tooltips with more
detail information.
Sitefinity 5192
© 2012 Falafel Software
The toolbar on the left holds high-level
navigation to the Dashboard, Visitors,
Traffic sources and Content. You can
drill down into the tree for each of these
high-level areas to display more detail.
For example, the Visitors > Devices node
includes detailed views that focus on
Browsers, operating system, Screen
colors and resolutions, Flash versions,
Java support or mobile devices and
carriers.
The Dashboard button bar groups and
displays data in multiple views. Use the
Map button to see web traffic data
presented as geographic data.
Analytics 193
© 2012 Falafel Software
The map shows web traffic by location, color coded to indicate concentration. Use the
Total Map Points buttons to quickly filter based on concentration of map points. A grid
below the map (not shown here) lists locations, visits and percentage totals.
Figure 189 --Viewing the Map
Sitefinity 5194
© 2012 Falafel Software
Summary
In this chapter you learned how to setup Analytics. A brief survey of the Analytics
interface demonstrated the kinds of web traffic information that could be generated and
analyzed.
9Widget Templates
Sitefinity 5196
© 2012 Falafel Software
9 Widget Templates
What if you don't like the way a widget is arranged or the content it contains? Widgets
Template allow you to tailor a widget to a particular arrangement with custom content.
Widget Templates 197
© 2012 Falafel Software
Objectives
This chapter demonstrates where you can access widget templates, how to edit the
template markup, how to create your own custom templates and how to work with the
Administration menu Widget Templates option.
Sitefinity 5198
© 2012 Falafel Software
Accessing Widget Templates
There are two places you can access widget templates:
From the Administration menu Design > Widget Templates option. The shows the name
of the template and where the template is used. For example, the Titles and dates
template is used or Applied To the blog post lists. This route allows you to delete widget
templates and to change the widgets a template is applied to. Click the Name link to edit
the template.
Figure 190 --Administrative Widget Templates List
From the Edit link of a widget. Many of the widgets display content in a list will allow
you to change either the list or detail layout.
Figure 191 --List Template
Widget Templates 199
© 2012 Falafel Software
Changing a Template
This next walk-through assumes you already have one or more blog posts created. The
blogs should have Tags defined. See Blogs topic for directions on creating Blog content.
1) Drag a Blog Posts widget to a page.
2) Click the Blog Posts widget Edit button.
3) Click the List Settings link.
4) Click the Titles and dates List Template, then click the Edit button.
Figure 192 --Editing a Template
5) The Edit template dialog displays. The dialog has three areas, the HTML markup, the
Blogs Insert... menu to the right of the HTML and the Template name below.
The HTML markup uses ASP.NET syntax and has special tags that reference Sitefinity
data fields. In the screenshot below, data is being brought into the widget for "Title",
"Description" and "PublicationDate".
The Blogs Insert... menu lists the data that can be dropped right into your widget. To
make it easier to use, the list is divided into Common data fields you're likely to use
and Other data that lists all possible fields.
Sitefinity 5200
© 2012 Falafel Software
The Template name not displayed on the page, but used by Sitefinity to identify the
template.
Figure 193 --Editing the Template
6) Place your cursor in the HTML just below the "PublicationDate" field, on line 23 shown
in the screenshot below.
Figure 194 --Placing the Cursor
Widget Templates 201
© 2012 Falafel Software
7) From the Blogs Insert... menu, click the Tags item. Sitefinity creates the markup needed
to retrieve the "Tags" field. Click the Insert button to place the markup at the cursor
position.
Figure 195 --Inserting the Tags Field
8) Click the Save changes button.
9) Click the Save button.
10)Now the "Tags" are listed below the "Title" and "Publication date'.
Figure 196 --The Updated Widget
Sitefinity 5202
© 2012 Falafel Software
Creating a New Template
What happens to your changed template when a new version of Sitefinity is installed? The
template may be overwritten by the new installation. The recommended approach is to
create a new template that will not conflict with built-in templates. You can copy all the
HTML from another template and then add any fields that you want.
1) Click the Blog Posts widget Edit button.
2) Click the List Settings link.
3) Click the Titles and dates List Template, then click the Edit selected template button.
4) Click the Restore template to default button. This rolls back any changes you have made
to the original definition stored in the database.
Figure 197 --Restoring the Template
5) Click the confirmation Yes, restore the default version... button.
6) Select all the HTML in the editing window, right-click and select Copy from the context
menu.
7) Click the Save changes button.
8) Click the Create New Template button.
Figure 198 --Creating a New Template
Widget Templates 203
© 2012 Falafel Software
9) Enter a unique, descriptive Template name.
Figure 199 --Assigning Template Name
10)Place your cursor in the editing window and paste the HTML from the clipboard.
11)Again, place your cursor in the HTML just below the "PublicationDate" field.
12)From the Blogs Insert menu on the right side, open the Other data section and select
the LastModified field.
13)Click the Insert button to paste the generated code into the HTML window.
14)Click the Create this template button. The new template should appear in the list of
templates where it can be assigned or edited.
15)Select the new template.
Figure 200 --Selecting a Template
16)Click the Save button.
17)The widget with the new template shows the modified date.
Figure 201 --Using The Widget
Template
Sitefinity 5204
© 2012 Falafel Software
Managing Widget Templates
Widget templates are managed from the Administration menu Design > Widget Templates
option. You should be able to see your new widget in this list, with your login name listed
as the Owner. The widgets are grouped into Area and can be sorted by this column. Also
notice the Applied To column that indicates where this template should be used.
Figure 202 --Widget Templates List
Use the link in the Name column to edit the template. The view of the widget is the same
as that for editing a widget on a page, except for one important difference. The template
Applied To can be changed from this dialog.
Figure 203 --Changing Where the
Template is Applied
Widget Templates 205
© 2012 Falafel Software
Summary
This chapter demonstrated where to access widget templates, how to edit the template
markup, how to create your own custom templates and how to work with the
Administration menu Widget Templates option.
10Page Templates
Page Templates 207
© 2012 Falafel Software
10 Page Templates
Page templates allow you to have the same basic layout and content across multiple page.
For example, you may want every page to have the organization logo in the upper left
hand corner and a copyright notice centered at the bottom of the page. You can build all
of your page templates entirely in Sitefinity, using drag and drop, without having to use
any other tool.
Notes
You can still use Master Pages, but you're not forced to. See the upcoming Master
Pages section for more information.
Sitefinity 5208
© 2012 Falafel Software
Objectives
In this chapter you'll learn use page templates to establish a basic layout and content across
multiple pages. You will add styles to the page template using both the CSS widget and
using ASP.NET Themes. Finally, you'll learn how to debug CSS issues.
Page Templates 209
© 2012 Falafel Software
Creating and Using a Page Template
In this walk-through, we will create a new page template and use the new template to
build a page. The template will include content for an organization logo, a drop down list
to select languages, a navigation menu widget and a footer with a copyright.
Sitefinity 5210
© 2012 Falafel Software
Creating a New Template
1) Access page templates from the Administration menu Design > Page Templates option.
The list will show all the built-in templates that you can start with or use as-is.
The Title column is a link to edit the template directly without having to use the
Actions menu.
The Actions menu has options to Delete the template, change the Title, change the
Content (edit the template), change Permissions and Base Template (choose a template as
a starting point).
The Based On column shows if a base template was used as a starting point.
To the right of Based On, a column shows the number of pages that use this particular
template. You can click this link to see a list of pages that use the template and to
preview those pages.
Figure 204 --Templates Page
2) Click the Create a template button and enter information about the template
Enter the Name of the template. The name should be descriptive of how the template
can be used.
Page Templates 211
© 2012 Falafel Software
Select the Use template option. Click the Select another Template button to choose the
"1 Column, Header, Footer" template.
Figure 205 --Create a Template Page
3) Click the Create and return to Templates button. The new template shows up in the list
and the Based On column shows that we're using the "1 Column Header, Footer"
template as a starting point.
Figure 206 --New Template in Templates List
Sitefinity 5212
© 2012 Falafel Software
Editing the Template Layout
1) Click the Actions > Content option (or click the title) to edit the template.
2) Click the Layout button. You should see the layout elements from the "Based on"
template, i.e. the "1 Column, Header, Footer" template.
Figure 207 --Template Layout
3) From the Drag layout elements area on the right, drag the 25% + 75% element onto the
top row of the layout. This should land right on top of the existing layout element.
Figure 208 --Dragging a Layout Element
Page Templates 213
© 2012 Falafel Software
4) Now the layout should look something like the screenshot below, where the top row is
divided into proportions of 25% and 75%.
Figure 209 --Modified Layout
5) Drag the 100% layout element to a point just between the top and second rows. This
will create a new row in the layout.
Figure 210 --Adding a Layout Element
Sitefinity 5214
© 2012 Falafel Software
6) Now the layout has a top row of 25% x 75% followed by three full rows.
Figure 211 --New Layout
Page Templates 215
© 2012 Falafel Software
Editing the Template Content
1) Click the Content button.
2) Drag an Image widget to the top row, leftmost element.
Figure 212 --Adding an Image Widget
3) Click the Edit link.
4) In the Insert an Image entry:
Click the Select... button and select a logo image for the upper left corner. Upload the
image. In the screenshots that follow, the original image happens to be 300 x 53
pixels.
Select Image Size drop down and select "Small: 240px width" from the list.
Click the Save button.
Figure 213 --Insert an Image Dialog
Sitefinity 5216
© 2012 Falafel Software
5) Open the Drag widgets Login section and drag the Login name widget to the top row,
right side.
Figure 214 --Adding a Login Name Widget
6) Click the Edit link of the Login name widget.
Scroll down to the FormatString property and change it to "You're logged in as
{FirstName} {LastName}".
Click the Save button.
The page now displays something like the screenshot below.
Figure 215 --Image and Login Name Widgets
Notes
The Login name should float to the right in this layout. See the upcoming Styling
section for directions on how to use CSS styling.
7) From Drag widgets > Navigation, drag a Navigation widget to the second row layout
element.
Page Templates 217
© 2012 Falafel Software
8) Click the Edit button of the Navigation widget.
In the What type of navigation to use? section, select the Horizontal with drop down
menus option.
In the Fine tune the selected type section, locate Open drop down menu on and select
Mouse over.
Click the Save button to close the dialog.
Notes
What if you don't want to display the "Home" page in the navigation, but only
the pages that come under home? The "Fine tune" section has an option to
display All pages under particular page, where you can use the Select button to
choose the "Home" page. If your website is many levels deep, use the Levels to
include option to limit the display to only a few levels deep.
9) Drag a Content block widget to the last row of the template.
10)Click the Edit link.
Add a Copyright notice for your organization, e.g. "Copyright 2012 Falafel Software".
Click the More formatting options button.
Place your text cursor just after the word "Copyright", drop down the Insert Symbol
list and select the copyright symbol.
Sitefinity 5218
© 2012 Falafel Software
Select the text in the editor window, then click the Align Center button.
· Click the Save button.
11)Click the Preview button to see the current state of the template.
Figure 216 --Template Preview
Using the New Page Template
1) Select the Pages menu option from the Administration page.
2) From the "Home" page Actions menu, select Change > Template.
Gotcha!
Be aware that changing the template will "pull the rug from underneath" any
current page design you already have in place. Changing the template will typically
break the layout and you will be starting over for that page. If you want to retain
changes, you should create a new page and use the new template there.
Page Templates 219
© 2012 Falafel Software
3) Select the new custom template. Notice the warning that the template change may
break the existing layout for the page.
Figure 217 --Selecting the Custom Template
Tip!
If this template will be used for most of your pages going forward, select the Use the
selected template as a default template... option.
4) Click the Done button to close the dialog.
Notes
You can return to an earlier version of the page, before the template was changed,
using the Actions menu Revision History item.
Sitefinity 5220
© 2012 Falafel Software
5) From the Actions menu, select Content. The home page appears with the template layout
and items already showing. Notice that the logo, login name, navigation menu and
copyright notice all come from the template and cannot be changed here. You can drag
new layout items around the template items, but you can't delete the template items,
drag widgets on top of these areas or sub-divide the layout elements.
Figure 218 --The Templated Page
Page Templates 221
© 2012 Falafel Software
Stying
Custom changes to fonts, alignment, background and other appearance changes needs to
be applied using styles. Styles can be added:
Using the CSS (Cascading Style Sheet) widget. Styles can be added to the widget
directly as text or you can link to a CSS file.
Using Themes. Themes are collections of CSS that are referenced from Sitefinity
administration.
Sitefinity 5222
© 2012 Falafel Software
Adding Styles Using the CSS Widget
You can use the CSS widget for quick, ad-hoc styling. You can have as many CSS widgets
on the page as you like. The styles defined in the CSS widget are added automatically to
the <head> tag of the page. The last example shows the Login name widget text aligned
left, much too close to the logo graphic. The following walk-through demonstrates adding
a "text-align" style to the page and using the style in a Content block widget.
1) From the Administration menu, select Design > Page Templates.
2) Open the "CarConduit One Column" template created in the previous "Page Templates"
section of this courseware.
3) Drag a CSS widget to the page.
Figure 219 --Adding a CSS Widget
Page Templates 223
© 2012 Falafel Software
Notes
Where you place the CSS widget is not critical to the functioning of the page. The
styles in the CSS widget are always added to the page <head> tag. Multiple CSS
widgets appear in the <head> tag in the order they're placed on the page.
4) Click the CSS widget Edit link.
5) Take a moment to explore the CSS dialog.
If you choose the Link to a CSS file option, use the Select... button to browse to a *.css
file within your project. In the Media section, you can select one or more media types
that the styles will apply to. CSS files should be located in the \App_Themes folder.
The Write CSS option allows you to add styles directly to the page. Styles can be added
to the editor window, but be sure to leave out the "<style>" tag.
6) Select the Write CSS option and enter the style below to the window:
.ccLogin{ text-align:right;}
7) Click the Save button.
8) Click the Layout button to move into layout mode.
9) Click the Edit link of the layout element that contains the login name.
10)In the Edit layout element section on the right side of the page, click the Classes link.
Sitefinity 5224
© 2012 Falafel Software
11)You will see two classes for the already defined for the first and second column of the
row. In the Column 2 edit, add a space and then add a new class "ccLogin".
Figure 220 --Adding a Class
Notes
You can also add a class to the entry labeled "Wrapper". "Wrapper" applies to the
entire row.
12)Click the Done button.
13)Click the Preview button. The top row, right column text will be aligned to the right
side.
Figure 221 --The Style Applied to the Content
Page Templates 225
© 2012 Falafel Software
Debugging CSS
One of your principal issues will be to find out what CSS classes apply to a particular
element on the page. Firebug is a plug-in to the Firefox browser that debugs CSS, HTML,
JavaScript and a whole lot more. You can download Firebug from http://getfirebug.com.
After installing it, the firebug icon in the lower right hand corner of the browser can be
pressed at any time.
1) Paste the URL of a Sitefinity page into the Firefox browser.
2) Click the Firebug icon found in the lower right hand of the browser.
Figure 222 --Starting Firebug
3) The Firebug environment opens up below the web page you're debugging. The HTML
tab contains the key tools you'll want to use with Sitefinity. The HTML tab makes it
easy to find elements on the page, see the cascading Styles for a given element, the
Computed style that's left when the styles have been evaluated, visually work with the
Layout for margins/padding and the underlying DOM (Document Object Model)
properties for all the elements.
Figure 223 --Firebug and a Sitefinity Page
Sitefinity 5226
© 2012 Falafel Software
4) The HTML tab highlights parts of the web page as your mouse hovers above the HTML
elements.
Figure 224 --Automatic Element Highlighting
5) Likewise, you can turn on the element inspector so that as your mouse passes over the
HTML markup, the corresponding elements on the page are highlighted. If you're
having trouble styling a particular element, this tool will allow you to find the element
visually and view the styles that apply to it.
Figure 225 --Turning on the Element Inspector
Page Templates 227
© 2012 Falafel Software
6) When you find the element you're looking for the Style window shows the styles that
apply along with the style sheet file and the line numbers where each style is defined.
Styles that are overridden elsewhere in the file are crossed out.
Figure 226 --Viewing Element Styles
Tip!
When you pass the mouse over a color or image path, Firebug automatically displays
the color or image.
Sitefinity 5228
© 2012 Falafel Software
7) You can click any of the values and change them temporarily to "audition" the effect on
the page. For example, you could click the color "#EEEEEE" and change it to Red
"#FF0000". These changes aren't retained, but you can try them out and copy the
changes to the style sheet later.
Figure 227 --Changing the Color Attribute
That should get you started with Firebug as it applies to Sitefinity. For more information,
see the getfirebug.com website for documentation and tutorials.
Page Templates 229
© 2012 Falafel Software
Summary
In this chapter you learned how to use page templates to establish a basic layout and
content across multiple pages. You added styles to the page template using both the CSS
widget and using ASP.NET Themes. Finally, you learned how to debug CSS issues.
11Responsive Web Design
Responsive Web Design 231
© 2012 Falafel Software
11 Responsive Web Design
Your web design is expected to look good on standard desktop displays, iPhones,
Androids, tablets or any device used during the life of your website. Sitefinity
automatically arranges the layout of the screen based on the current screen characteristics
(i.e. screen size, device to pixel ratio, orientation, etc). If your large, browser-based layout
takes up three columns from side to side, the iPhone can view the same content running
in a single column. You can even customize font properties or swap images based on the
current screen characteristics.
Sitefinity implements Responsive Web Design automatically, using rules to define the
characteristics to look for (e.g. 240-320 pixels in width like the HTC Wildfire) and how
your site should react (e.g. transform the layout, redirect to another site, load a special css).
Notes
Under the hood, Sitefinity uses CSS media queries to get information about the
screen minimum width and orientation. For more background information, check
out Ethan Marcotte's seminal blog Responsive Web Design.
Sitefinity 5232
© 2012 Falafel Software
Objectives
In this chapter you'll learn how Responsive Web Design helps your application react to
device sizes ranging from full-sized desktop or notebook screens to the smallest of hand-
held devices. You'll learn how to define rules that react to different screen configurations,
how to make basic layout changes based on those configurations and how to fine tune all
aspects of the page using styles.
Responsive Web Design 233
© 2012 Falafel Software
Creating Rules
The first step is to create rules for the scenarios you expect to encounter. In our example,
we'll create "Small" and "Large" versions of a simple website, but you can make rules for
as many detailed cases as you want. Typically you'll want to cover small "Smart phone"
screens, tablets and large notebook/desktop screens (1024px or higher).
This next example starts with a simple set of three columns filled with images and text.
Figure 228 --The Initial Web Design
Sitefinity 5234
© 2012 Falafel Software
To begin making this a responsive web site:
1. From the Sitefinity menu, select Design > Responsive and Mobile design.
2. Click the Create a group of rules button.
3. Enter a Name for the group of rules.
Figure 229 --Entering the Rule Name
4. Select device characteristics using the presets from the drop down list. For this example
step, choose the "Smartphones" option.
Figure 230 --Setting the Device Characteristics
5. Leave the defaults for Apply behavior to... and Specific CSS file options.
Responsive Web Design 235
© 2012 Falafel Software
6. In the System settings: Fine tune default layout elements section, select the vertical
arrangement of rows for each option. For example, where the default is "2 columns",
select "2 rows".
Figure 231 --Tuning Layout
7. Leave the This group of rules is active checkbox selected and click the Done button.
Sitefinity 5236
© 2012 Falafel Software
Previewing the Results
You can preview the results by simply resizing the browser to see the results. To get a
better feel for how your site will look in a phone or tablet, click the More actions > Preview
for Smartphones and Tablets option.
Figure 232 --Previewing the Layout
Figure 233 --iPhone Portrait View
From here you can look at the site as it will
appear in iPhone 4, HTC HD2, HTC Incredible,
iPad 2 and Samsung Galaxy Tab in Portrait or
Landscape orientations. The iPhone Portrait view
shows the content for the three columns stacked
vertically.
Responsive Web Design 237
© 2012 Falafel Software
Device Characteristics
Sitefinity predefines a set of device characteristics that will trigger layout changes. The
likely suspects are listed there, but you can add your own rules to help "future proof" your
site.
Figure 234 --Device Characteristics
Sitefinity 5238
© 2012 Falafel Software
Click the Details button next to the "iPhone 4s" entry to configure the specifics that make
up a rule. You can trigger rules based on the Size or Size range, the Orientation, Aspect
ratio and Resolution. You can even trigger rules if the device is an old-school monochrome
or grid-based device, e.g. teletypes, terminals or portable devices with limited display
capabilities. As you change the settings, a media query is built dynamically in the Result
area at the base of the dialog.
Figure 235 --Defining a Custom Rule
Responsive Web Design 239
© 2012 Falafel Software
Adding New Behaviors
Changing layout gets you part way there, but you may need to perform detailed styling of
fonts, hide or show images, change margins or obscure elements that don't work with a
particular device. There are two ways to handle these detailed changes:
Apply behavior to Open a specially prepared site (e.g. a mobile version of your site). This is
less flexible than using style sheets and may result in multiple sites being created as new
device types come online. The advantage is that you can customize the site very
specifically for each device type. To go this route, select the Open a specially prepared site
option, then select the Root page of the specially prepared site.
Figure 236 --Routing to a Specially Prepared Site
If you select Apply Behavior to Transform the layout, you can choose a CSS file that will
come into play when certain devices are detected.
Figure 237 --Transforming the Layout
Sitefinity 5240
© 2012 Falafel Software
Using a CSS file option, the page is still single source, but styles are applied to customize
the page for each situation. The example below uses a stylesheet to control the look of the
full sized web page. The screenshot shows a full size banner graphic that stretches across
all three columns.
Figure 238 --Full Sized Page
Figure 239 --Smart Phone Layout
When the browser size is reduced
to trigger the "Small" set of rules,
the "small.css" file kicks in and a
reduced sized graphic displays at
the top of the page. Notice that
the small "smart phone" version
of the page also uses a different
font and font color than the larger
version.
Responsive Web Design 241
© 2012 Falafel Software
Here's an example of the small.css file.
.banner_small { display:block !important; }.banner_large { display:none !important; }.threeImage { margin-top:30px; !important; margin-bottom:0px !important; margin-left:0px !important;}h3 { margin-top:0px; !important; margin-bottom:0px !important;}.blurb { color:#3060A0 !important; font-weight:bold !important; margin-top:0px !important; margin-bottom:0px !important;}
...and the large.css file:
.banner_small { display:none !important; }.banner_large { display:block !important; margin-bottom:20px !important;}.threeImage { margin-top:0px; !important; margin-bottom:0px !important; margin-left:0px !important;}h3 { margin-top:0px; !important; margin-bottom:0px !important;}.blurb { font-family: Arial !important; margin-top:0px !important; margin-bottom:0px !important;}
Sitefinity 5242
© 2012 Falafel Software
Summary
In this chapter you learned how Responsive Web Design helps your application react to
device sizes ranging from full-sized desktop or notebook screens to the smallest of hand-
held devices. You learned how to define rules that react to different screen configurations,
how to make basic layout changes based on those configurations and how to fine tune all
aspects of the page using styles.
12Working with Master Pages
Sitefinity 5244
© 2012 Falafel Software
12 Working with Master Pages
Master pages are the file-based standard that ASP.NET uses for templating. Master pages
also have C# or VB.NET code behind unlike the Sitefinity template counterpart. If you
want to use custom .NET coding, Master pages are the way to go.
Whenever possible, use the built-in Sitefinity tools to sculpt the page layout look-and-feel.
The only time you really need to use an external ASP.NET Master Page is to allow code-
behind. For example, if you need to access an external web service.
Working with Master Pages 245
© 2012 Falafel Software
Objectives
In this chapter you'll learn how Master pages work together with the page template and
theme. You'll see how to use a Master page from the marketplace and how to "slice-and-
dice" third party templates to integrate them in your web site.
Sitefinity 5246
© 2012 Falafel Software
Masterpage Overview
Using Master pages inside a Sitefinity website involves three main pieces:
The Master Page itself. The Master page file and its associated code-behind live in the
Visual Studio project.
The Theme contains styles and is stored in the Sitefinity database.
The Sitefinity Template is also stored in the Sitefinity database. The template ties
together the Master page and the Theme. The template is "based on" the Master page
and the theme is applied to the template.
Working with Master Pages 247
© 2012 Falafel Software
Using a MasterPage from the Marketplace
The predefined themes on the Sitefinity Marketplace web site give you a jump on
development by providing both the theme and the master page layout, all in one place.
The walk-through that follows demonstrates how to integrate the "SolarFlare" master page
and theme into your web site.
Figure 240 --The Sitefinity Marketplace
The Game Plan
The steps to using an existing themed master page from the Sitefinity Marketplace are:
1) Download the Theme
2) Add the Theme to the Solution
3) Define the Theme Setting
4) Create the Sitefinity Template
5) Use the Theme
Sitefinity 5248
© 2012 Falafel Software
Downloading the Theme
1) In a browser, navigate to http://www.sitefinity.com/marketplace/themes.aspx.
2) Locate the SolarFlare link and click it.
3) Click the Download from Publisher button.
Figure 241 --Downloading SolarFlare
4) Save the "SolarFlare.zip" file to a location on your local drive.
5) Unzip the "SolarFlare.zip" file.
Working with Master Pages 249
© 2012 Falafel Software
Adding the Theme to the Solution
The recommended directory structure for master pages, themes and widget templates is
shown in this outline:
\App_Data\Sitefinity\WebsiteTemplates
\App_Master
\App_Themes
\<my theme>
\Global
\Images
\Styles
1) In the Solution Explorer, open the \App_Data folder.
2) Right-click the \Sitefinity folder, and select Add > New Folder from the context menu.
Name the new folder "WebsiteTemplates".
Sitefinity 5250
© 2012 Falafel Software
3) In the Windows File Explorer, locate your unzipped "SolarFlare" folder and drag it
onto \WebsiteTemplates. The resulting folder structure should look exactly like the
screenshot below.
Figure 242 --Directory Structure
Gotcha!
Make sure you're in the \App_Data\Sitefinity folder, not the \Sitefinity folder in
the root of the project.
4) Save the solution.
Working with Master Pages 251
© 2012 Falafel Software
Defining the Theme Setting
1) In the Sitefinity Administration menu, navigate to Administration > Settings > Advanced
> Appearance > Frontend Themes.
2) Click the Create New button.
3) Enter a Name for the theme and the exact Path, as shown in the screenshot below. This
path must exactly match the directory structure in the Solution Explorer, starting with
the "~" to indicate the project root. The actual theme folder is named "Green" in this
example.
Figure 243 --The Frontend Theme Setting
4) Click the Save Changes button.
Sitefinity 5252
© 2012 Falafel Software
Creating the Sitefinity Template
1) In the Sitefinity Administration menu, select Design > Page Templates.
2) Click the Create a Template button.
3) Set the Name to be "SolarFlare".
4) Click the Use Template radio button.
5) Click the Select another Template button.
6) In the Select a Template dialog, click the Use your own .master file button.
7) In the Select a masterpage dialog, click the Browse other folders button.
8) Select the SolarFlare.master file in the directory tree, then click the Use Selected button.
Figure 244 --Selecting the Master File
9) Back in the Create a template screen, click the Create and go to add content button.
Working with Master Pages 253
© 2012 Falafel Software
10)Click the Theme button.
11)Select the SolarFlare theme from the drop down list.
12)The SolarFlare theme graphics should display in the template. Click the Publish
button.
Figure 245 --The SolarFlare in the Template
Sitefinity 5254
© 2012 Falafel Software
Using the Theme
1) Select Pages from the Sitefinity Administration menu.
2) Create a new page and go to editing content.
3) Click the Layout button.
4) Click the Select another template... button.
5) In the Select a template dialog, select the SolarFlare template and click the Done button.
Figure 246 --Selecting the Template
6) Click the Create and go to add content button.
7) The SolarFlare graphics should now display in the page.
Figure 247 --The Page Using SolarFlare Template
Working with Master Pages 255
© 2012 Falafel Software
8) Publish the page.
Sitefinity 5256
© 2012 Falafel Software
Editing 3rd Party Templates
While the Marketplace themes are constructed specifically for Sitefinity consumption, you
can also download hundreds of CSS templates from various sites on the web such as
http://www.freecsstemplates.org. You will need to perform some "surgery" to make the
theme useful in Sitefinity. For this example we will use the "index.html" file from the
CarConduit Template as raw material for a master page. "CarConduit Template" is
included along with the projects for this Courseware.
Using Master pages inside a Sitefinity website involves three main pieces:
The Master Page itself. The Master page file and its associated code-behind live in the
App_Master folder of the Visual Studio project.
The Theme contains style related files, i.e. css, JavaScript and images.
The Sitefinity Template is stored in the Sitefinity database. The template ties together the
Master page and the Theme. The template is "based on" the Master page and the theme
is applied to the template.
Prepare the Project
1) In Visual Studio, create the following folder structure:
\App_Data\Sitefinity\WebsiteTemplates
\App_Master
\App_Themes
2) In the Visual Studio, right-click the App_Master folder and select Add > New Item >
Master Page.
3) Name the file CarConduit.Master and click the Add button.
4) Copy the contents of "index.html" from the CarConduitTheme folder and paste the
HTML into "CarConduit.Master", completely overwriting the existing html.
5) In the Visual Studio, right-click the App_Themes folder and select Add > New Folder.
Name the folder "CarConduit".
6) Copy the "css", "images", "js" directories and the "home.png" file to
the \App_themes\CarConduit folder. Rename the "css" folder to "global".
Working with Master Pages 257
© 2012 Falafel Software
Notes
Sitefinity is looking for the "global" name specifically, to find the css files.
7) Now the directory structure should look like the screenshot below.
Figure 248 --Final Folder Structure
Sitefinity 5258
© 2012 Falafel Software
Perform Masterpage "Surgery"
In Visual Studio, edit CarConduit.Master to work with Sitefinity.
1) Remove everything from the inside of the <head> tag. Sitefinity will take care of meta
tags and style sheet references for us, so the <head> tag elements are not needed. You
will need the <head> tag itself, so do not remove it.
2) Add the attribute runat="server" to the <head> tag. Sitefinity needs to access the head
tag at the server and failing to do this will cause a "yellow screen of death" error.
3) In Visual Studio, press Ctrl-F and search for "<form". This will bring you to a <form>
used to contain the search for the page. Remove the <form...>, </form> tags and the
contents within the form tags.
4) Add a <form> tag inside the <body>. Be sure to add the runat="Server" attribute. It's
also good practice to include an ID attribute for the <form> tag. The markup in
CarConduit.Master should now look something like the screenshot below.
Figure 249 --Masterpage Markup
5) Replace the hard-coded copyright notice at the base of the page with a placeholder.
· In Visual Studio, press Ctrl-F and search for "footercredits". This will bring you to a
<div> tag.
· Remove the copyright text from inside the tag.
· From the Toolbox, Standard section, drag a ContentPlaceHolder control to a point
inside the "footercredits" <div> tag.
· Change the ID of the tag to "MyCopyright".
· The html markup should look something like the example below:
<div id="footercredits"> <asp:ContentPlaceHolder ID="MyCopyright" runat="server"> </asp:ContentPlaceHolder></div>
Working with Master Pages 259
© 2012 Falafel Software
Gotcha!
Be sure to use ContentPlaceHolder, not Placeholder.
6) Build the project.
Defining the Theme Setting
1) In the Sitefinity Administration menu, navigate to Administration > Settings > Advanced
> Appearance > Frontend Themes.
2) Click the Create New button.
3) Enter the Name "CarConduit".
4) Enter the Path "~/App_Data/Sitefinity/WebsiteTemplates/CarConduit/App_Themes/
CarConduit".
Figure 250 --CarConduit Theme Settings
5) Click the Save Changes button.
Sitefinity 5260
© 2012 Falafel Software
Create Template and Apply Theme
The next step is to create a template that is based off the masterpage.
1) From the Sitefinity administration, select Design > Page Templates from the Sitefinity
menu.
2) Click the Create a Template button.
3) In the Name section enter CarConduit Using Master .
4) In the Template section select Use template. Click the Select another Template button.
5) The Select a template dialog displays. Click the Use your own .master file button.
6) Click the Browse other folders link.
7) Navigate to \App_data\Sitefinity\WebsiteTemplates\App_Master and select
CarConduit.Master. Click the Use Selected button.
Figure 251 --Selecting the Master
8) Click the Use Selected button to close the dialog and return to the Create a template
page.
Working with Master Pages 261
© 2012 Falafel Software
9) Click the Create and return to templates button. The new template will show up in the
list with the Based On column showing the masterpage in use.
Figure 252 --New Template Using Master
10)Open the new template by selecting Actions > Content. The HTML from the masterpage
displays but the effect is ugly because styles have not been applied.
Figure 253 --Template With Masterpage But No Theme
11)Click the Theme button.
Sitefinity 5262
© 2012 Falafel Software
12)Select CarConduit from the drop-down list found under the Set theme section on the
right hand side. The styles now merge with the masterpage used in the template.
Several images are broken because the paths were hard-coded. We could repair these,
but we will be replacing most of the images with ContentPlaceHolder controls.
Figure 254 --Using the Theme
13)Scroll to the bottom of the template to where the copyright notice should be. Where
the ContentPlaceHolder was added, a new layout element area is ready to accept
widgets.
Figure 255 --Template, Masterpage and ContentPlaceholder
14)Click the Publish button to make the template available for use in pages.
Working with Master Pages 263
© 2012 Falafel Software
Use the Template
The area created by adding a ContentPlaceHolder looks and acts the same as any layout
area in a template. In this next walk-through, we will create a page that uses the new
template and adds content to the copyright notice layout area at the bottom of the page.
1) Select Pages from the Sitefinity menu.
2) Click the Create a Page button.
3) In the Name section enter Welcome.
4) In the Template section, click the Use template radio button. Click the Select another
Template button.
5) Select the CarConduit Using Master custom template, then click the Done button.
Figure 256 --Selecting the Template
6) Click the Create and go to add content button.
7) Scroll to the bottom of the page.
8) Drag a Content block widget to the layout area at the bottom of the page.
9) Click the Edit link.
10)Enter a copyright notice.
In the editor window enter Copyright <your organization><current year>.
Sitefinity 5264
© 2012 Falafel Software
Click the More formatting options button.
Place the text cursor just to the right of "Copyright".
Drop down the list of symbols and select the copyright symbol.
Click the align-center button.
11)Click the Save button.
Figure 257 --Testing the Template
Working with Master Pages 265
© 2012 Falafel Software
Master Page Surgery Tips
To make the template general-purpose, add ContentPlaceHolder controls to any area of
the masterpage you'll want to customize later. Try to remove any formatting markup that
might limit you in the future. When you get done replacing various areas of the page, the
master page becomes much smaller, only consisting of structural markup. You can also
remove Javascript from the masterpage because the widgets will supply script for things
like menu hover behavior.
Once the general areas are setup in the masterpage, use the template in Sitefinity to
further subdivide layout elements and to add common content. Develop the layout to fit
your requirements, then create areas for customization using the ContentPlaceHolder
control.
The example below is a simplified version of the CarConduit masterpage. Several rows
have been removed for the sake of example.
Sitefinity 5266
© 2012 Falafel Software
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"></head><body> <form runat="server" id="MyForm"> <div id="wrapper"> <div id="header"> <a class="logo" href="#">Site Home</a> <div id="navContainer"> <asp:ContentPlaceHolder ID="MyNavigation" runat="server" /> </div> </div> <div id="content"> <asp:ContentPlaceHolder ID="MyContent" runat="server" /> </div> <div id="footer"> <div class="one-fourth"> <div class="footer-widget"> <h3>Testimonials</h3> <div class="testimonial-widget"> <asp:ContentPlaceHolder ID="MyTestimonials" runat="server" /> </div> </div> </div> <div class="one-fourth"> <div class="footer-widget"> <h3>Recent Comments</h3> <asp:ContentPlaceHolder ID="MyComments" runat="server" /> </div> </div> <div class="one-fourth"> <div class="footer-widget"> <h3>Recent Posts</h3> <asp:ContentPlaceHolder ID="MyPosts" runat="server" /> </div> </div> <div class="one-fourth last"> <div class="footer-widget"> <h3>Categories</h3> <asp:ContentPlaceHolder ID="MyCategories" runat="server" /> </div> </div> <br class="break" /> <div id="footercredits"> <asp:ContentPlaceHolder ID="MyCopyright" runat="server" /> </div> </div> </div> </form></body></html>
Working with Master Pages 267
© 2012 Falafel Software
The compiled template looks like the screenshot below. The masterpage
ContentPlaceHolder controls supply areas for the upper right hand side navigation menu,
a content area below that and sections for "Testimonials", "Recent Comments", "Recent
Posts" and "Categories". The area at the bottom of the page is intended as a space for the
copyright notice but could hold other page footer content.
Figure 258 --The Template
Sitefinity 5268
© 2012 Falafel Software
Tip!
The titles in the footer for "Testimonials", "Recent Comments", etc., have been hard-
coded to make it easier for this exercise. Just the same, you could swap out all those
titles with more ContentPlaceHolder controls. Later, if "Categories" had to be
changed to "Tags", someone without Visual Studio experience could still change the
content using Sitefinity alone.
Now that your template holds your masterpage and theme, you can simply drop widgets
into any page that uses the template. Here is an example of the "Welcome" page created
earlier with additional content. To show something of interest in the navigation menu, the
"About Us", "Blogs" and "News" pages have been copied underneath the new "Welcome"
page. The logo image is directly from the masterpage markup, while the menu is a
Navigation widget dropped into the page. Below those two items, the Image Gallery
widget displays a list of images along with detail for one image. Below the Image Gallery,
"Testimonials" and "Recent Comments" are placed using a simple Content widget. "Recent
Posts" uses a News widget and the "Popular Tags" area holds a Classification > Tags
widget.
Figure 259 --Page Using Template With Masterpage
Working with Master Pages 269
© 2012 Falafel Software
Summary
In this chapter you learned how Master pages work together with the page template and
theme. You saw how to use a Master page from the marketplace and how to "slice-and-
dice" third party templates to integrate them in your web site.
13Developing in Sitefinity
Developing in Sitefinity 271
© 2012 Falafel Software
13 Developing in Sitefinity
Using only the Sitefinity Administrator you can do many things, but what if you need to
work with your Sitefinity data programmatically? For example, convert records in an
Oracle database to a set of blog posts, or create pages in a user interface you build in a
Windows form or WPF? The Sitefinity API can help with one-time migration tasks,
building interfaces to consume Sitefinity, custom content entry interfaces or just about
anything you can visualize.
Sitefinity 5272
© 2012 Falafel Software
Objectives
In this chapter you will learn the basics for getting started with Sitefinity development.
You'll learn what basic flavors of the API are available to you and how to work with the
API in Visual Studio.
Developing in Sitefinity 273
© 2012 Falafel Software
What Flavor API?
There are three ways of working with Sitefinity programmatically:
Using the Sitefinity API. This is the full-featured API that provides the deepest set of
features for controlling Sitefinity functionality. Use the Sitefinity API to access
everything that Sitefinity has to offer. Here is an example of the Sitefinity API that
returns all blog posts:
BlogsManager manager = BlogsManager.GetManager(); IQueryable<BlogPost> blogs = manager.GetBlogPosts();
The Fluent API: this is a wrapper around Sitefinity API that surfaces the most
commonly used features in an elegant, LINQ friendly syntax. Use this language feature
to be productive quickly.
var blogs = App.WorkWith().BlogPosts().Get().ToList();
Using Sitefinity REST services opens the door to any client platform that can hit a URL
including Linux, Windows, Mac, IWhatever (iPad, iPhone), Silverlight, WPF, Flash,
Android, etc. REST services allow you to list any information on the site and perform
CRUD (Create, Read, Update, Delete) operations on the data you find there. Sitefinity
REST services can communicate in XML or JSON (for easy access in JavaScript client
code). The example below brings back a list of all blog posts in XML format from "<my
site>".
http://localhost:12345/<my site>/sitefinity/services/Content/BlogPostService.svc/xml
Sitefinity 5274
© 2012 Falafel Software
Getting Started with Sitefinity Development
Now that you've seen a few basic examples of the Sitefinity API and the Fluent API, you
may wonder "Where do I put this code?". You can code directly against your Sitefinity
web site simply by adding a standard ASP.NET page and adding API code to the page.
Prepare the Sitefinity Project
In this example we will use the Sitefinity API to provide a list of pages in the site. This
walk-through assumes you already have a Sitefinity web site created.
1) Open a Sitefinity web site in Visual Studio, from the Sitefinity Project Manager by
clicking the Edit in Visual Studio button.
Figure 260 --Editing the Sitefinity Project in Visual Studio
Developing in Sitefinity 275
© 2012 Falafel Software
2) In the Visual Studio Solution Explorer, right-click the SitefinityWebApp project and
select Add > New Folder from the context menu. Rename the folder to "My Pages".
Figure 261 --Adding the New "My
Pages" Folder
3) Right-click the "My Pages" folder and select Add > New Item... from the context menu.
In the Add New Item dialog, select the Web > Web Form item and set the Name to
"MyPagesList.aspx". Click the Add button to create the page and close the dialog.
Figure 262 --Adding an ASP.NET Page
Sitefinity 5276
© 2012 Falafel Software
Use the API to List Pages
1) In the aspx markup for the page, add a standard ASP.NET ListBox.
<asp:ListBox ID="ListBox1" runat="server" Height="300px" Width="200px"></asp:ListBox>
2) In the code behind for the page, add the code below to the Page_Load event handler.
protected void Page_Load(object sender, EventArgs e){ PageManager manager = PageManager.GetManager(); var list = manager.GetPageDataList().ToList();
ListBox1.DataSource = list; ListBox1.DataTextField = "Title"; ListBox1.DataBind();}
The first step is always to get the "manager" object for the part of the API we're
working with. The static GetManager() returns a single instance of the PageManager .
From there, you can call any of the many methods of the manager object to
accomplish your task. In this example, the GetPageDataList() method returns a list of
PageData objects containing header and page level information. You can iterate this
information or use it to bind directly to a control.
3) In the Solution Explorer, right "MyPageList.aspx" and select Set as Start Page from the
context menu. The running application will display the list box with whatever pages
you have published in your site. Notice that the list contains pages with blank titles,
front end pages and back end pages.
Figure 263 --Unfiltered List of Pages
Developing in Sitefinity 277
© 2012 Falafel Software
4) To show only for the backend pages you can use LINQ statements to filter the list before
binding to the list box. Add the Where() statement to the end of your GetPageDataList()
method call. This will check that the PageData IsBackendPage is false for every
PageData in the list.
var list = manager.GetPageDataList().ToList() .Where(p => p.IsBackendPage == false); // <-- add this statement
5) Re-run the project. Notice that only your front end pages are listed.
Figure 264 --Filtered List of Pages
Sitefinity 5278
© 2012 Falafel Software
Sitefinity Projects in Visual Studio
A Sitefinity web site is really an ASP.NET web site at its heart and can be worked with just
like any other ASP.NET web site. The major difference is that page creation is performed
automatically using information from the database.
You can open a Sitefinity web site in Visual Studio, from the Sitefinity Project Manager.
Figure 265 --Editing the Sitefinity Project in Visual Studio
The first thing to notice is that we have opened a web application project, not a web site. A
web site is a loose collection of files, but a project is managed as a whole and compiled into
a single DLL assembly. There is one default.aspx page in the project to keep IIS happy, but
all the pages actually used in the project are stored in the database. As a result of page
storage in the database, the project structure will not change much as the content grows.
Figure 266 --The Sitefinity Web Project
Developing in Sitefinity 279
© 2012 Falafel Software
Configuration
In past versions of Sitefinity, the "web.config" file was huge, but the Sitefinity architecture
has moved all of the Sitefinity-specific configuration to separate XML files for easier
handling. Only ASP.NET related configuration is left in the web.config. This architecture is
easier to maintain and also handles updates better, even if the web.config is overwritten.
All these files are written to from the Sitefinity back end administration, but you can find
the XML files in \App_Data\Sitefinity\Configuration. To make the Configuration folder
visible in the Visual Studio Solution Explorer, you will need to select the project folder,
then click the Show All Files button.
Figure 267 --Sitefinity Configuration Files
Sitefinity 5280
© 2012 Falafel Software
Developing with Thunder
Sitefinity Thunder is a Visual Studio plug-in that helps organize and build Sitefinity
applications. The Thunder plug-in includes an explorer that navigates Sitefinity items in
the project, new Sitefinity project items (widgets, designers and themes) and the ability to
register existing widgets automatically. At the time of this writing, you can install the
Thunder beta from the Visual Studio Gallery or use the Visual Studio Tools > Extension
Manager menu option to download and install the Thunder plug-in.
Developing in Sitefinity 281
© 2012 Falafel Software
Summary
In this chapter you learned the basics for getting started with Sitefinity development. You
learned about the basic flavors of the API that are available to you and how to work with
the API in Visual Studio.
14Using the Sitefinity API
Using the Sitefinity API 283
© 2012 Falafel Software
14 Using the Sitefinity API
The Sitefinity API provides a full set of services over Sitefinity web sites. Later, you'll learn
about Using the Fluent API, where the Fluent API is a subset of the Sitefinity API.
Sitefinity 5284
© 2012 Falafel Software
Objectives
This chapter explains how to work with the Sitefinity API. First you'll learn how to create a
Sitefinity page programmatically and then how to display the hierarchy of pages in a tree
view. You'll also create content programmatically and perform CRUD (Create Read
Update Delete) operations against content items. Finally, you will add a programmatically
created content item to a page, on-the-fly.
Using the Sitefinity API 285
© 2012 Falafel Software
Working with Pages
Why use code to work with pages? You may want to read from an outside table or site
map and create pages programmatically. You may be porting material from some legacy
system. You could also modify all the pages on the site in a batch, e.g. read and modify the
keywords for all pages in the system.
Tip!
Create your own set of tools to take with you when you work at other sites. For
example, utility classes or functions that iterate and modify pages, create new pages,
look for specific keywords, locked pages, empty keywords and so on.
Creating a Page Programatically
Creating a page at runtime involves the following:
PageData represents the Titles and Properties information for the page.
PageNode contains the actual instance of the page.
You create both of these in code and then assign the PageData to a property of the
PageNode.
1) In Page_Load of an ASP.NET page in the Sitefinity project, add code to get the currently
running singleton instance of the PageManager and turn off security checks.
PageManager pageManager = PageManager.GetManager();pageManager.Provider.SuppressSecurityChecks = true;
2) Then add the PageData to represent header information about the page.
// create the PageData corresponding to "Titles and Properties"PageData pageData = pageManager.CreatePageData();pageData.HtmlTitle = "CarConduit Blogs Title for Search Engines";pageData.Title = "CarConduit Blogs";pageData.Description = "CarConduit Blogs Description";pageData.Keywords.Value = "Cars,Autos,Collectors"; pageData.Status = ContentLifecycleStatus.Live;
The PageManager CreatePageData() method returns a PageData instance. Use the
PageData instance properties to set all the entries you normally see in the Titles and
Properties for the page.
Sitefinity 5286
© 2012 Falafel Software
3) Add the code below to assign the "Left Sidebar, Content" template.
pageData.Template = pageManager.GetTemplates() .Where(t => t.Title.Equals("Left Sidebar, Content")) .FirstOrDefault();
The page uses the default layout template if the PageData.Template property is not
assigned. Use the PageManager.GetTemplates() method to list all possible templates
you can assign. The LINQ expression compares against the Template Title property.
4) Add the code below to create a page instance.
// create the page instance as a child of the root nodePageNode pageNode = pageManager.CreatePageNode();PageNode parentNode = pageManager.GetPageNode(SiteInitializer.FrontendRootNodeId);pageManager.ChangeParent(pageNode, parentNode);pageNode.UrlName = "CarConduitBlogs";pageNode.ShowInNavigation = true;
In particular, notice the reference returned by GetPageNode(). GetPageNode() passes
a SiteInitializer (from the Telerik.Sitefinity.Abstractions namespace) property called
FrontendRootNodeId. This is a Guid that identifies the site's root node. The
PageManager ChangeParent() method makes the root node the parent for the page
we're creating.
5) To marry the PageData to the PageNode, assign the PageNode.Page property, then save
the changes. To publish the page, send a message through the WorkflowManager.
pageNode.Page = pageData;pageManager.SaveChanges();
// publish through the workflowWorkflowManager.MessageWorkflow(pageNode.Id, typeof(PageNode), null, "Publish", false, new Dictionary<string, string>());
Using the Sitefinity API 287
© 2012 Falafel Software
6) Run the application, then navigate to the Sitefinity Administrator Pages to view the new
page.
Figure 268 --Viewing the New Page
7) Select the Actions > Title & Properties link. The properties values set by the PageNode
and PageData all show up in the Titles & Properties page.
Figure 269 --Title & Properties
Sitefinity 5288
© 2012 Falafel Software
Tip!
To park your new page underneath some other node, you need to get its Guid
identifier. Use the GetPageNodes() method to return all page nodes, then use LINQ
to filter out the page you want to use as a parent. Each PageNode has an Id property
-- a Guid suitable for passing to the ChangeParent() method.
PageNode homePageNode = pageManager .GetPageNodes() .Where(n => n.Title.Equals("Home")) .FirstOrDefault();pageManager.ChangeParent(pageNode, homePageNode);
Now the tree of pages displays the new "CarConduit Blogs" page under the "Home"
page instead of as a sibling.
Figure 270 --New Page Listed Under Home
Using the Sitefinity API 289
© 2012 Falafel Software
Show Hierarchy of Pages
While the PageData class knows about the header information for the page, the actual
page instance is encapsulated in a PageNode object. Each PageNode has an Id Guid
property that identifies it and a Parent property that itself is a PageNode. Using the
Manager's GetPageNodes() method we can retrieve the nodes for all the pages in the web
site and display them as a tree. The example below displays page titles in a RadTreeView
control.
1) Drag a RadTreeView from the Toolbox onto an ASP.NET page.
2) In the Page_Load event handler, add the code below. There are a few things to note in
the example below. We aren't handling security directly in this example, so we need to
set the SuppressSecurityChecks property true to avoid security exceptions. The Select
() clause projects the elements of the PageNode into something more compatible with
the RadTreeView. RadTreeView expects a DataFieldID for the current node and a
DataFieldParentID to point at the id for its parent. For root nodes, the PageNode.Parent
object is null, so we check for that and pass Guid.Empty in those cases.
protected void Page_Load(object sender, EventArgs e){ PageManager manager = PageManager.GetManager(); manager.Provider.SuppressSecurityChecks = true; var list = manager.GetPageNodes() .ToList() .Select(p => new { Id = p.Id, ParentId = p.Parent == null ? Guid.Empty : p.Parent.Id, Title = p.Title }); RadTreeView1.DataSource = list; RadTreeView1.DataTextField = "Title"; RadTreeView1.DataFieldID = "Id"; RadTreeView1.DataFieldParentID = "ParentId"; RadTreeView1.DataBind();}
Sitefinity 5290
© 2012 Falafel Software
3) Run the example. Pages defined in your site should show up in tree form. You can
refine the query to only return front end pages or provide other filtering.
Figure 271 --Tree of Pages
Using the Sitefinity API 291
© 2012 Falafel Software
Working with Content Items
The Sitefinity API is very consistent between modules, whether you are working with
generic content, blogs, events or news. The first step is always to get the manager object.
Generic content is a relatively simple starting point, so we will get a reference to the
ContentManager .
ContentManager manager = ContentManager.GetManager();
ContentManager knows how to perform basic "CRUD" operations (Create, Read, Update,
Delete):
CreateContent() generates a ContentItem. ContentItem properties can then be
populated with Title, Name, Author, and Content.
Return a single ContentItem using the GetContent() method and passing a Guid.
GetItems() returns an IQueryable<T> with all content items, suitable for "slicing-and-
dicing" with LINQ. There are also several methods for returning, Master, Temp and Live
versions of a ContentItem.
To update a ContentItem, get an instance of the item and simply edit its properties.
To delete a ContentItem, use the Delete() method.
Three other important ContentManager methods round out the field:
RecompileItemUrls<T>(): This method needs to be called each time an item changes.
The method generates a url for the item and saves the changes.
Publish(): Newly created items are in Draft mode. Calling the manager's Publish()
method makes managed content visible to the end user.
SaveChanges(): This method commits any changes to the database.
Sitefinity 5292
© 2012 Falafel Software
Creating an Item
The first API call always gets the manager for a specific module. The manager object can
then be used to create some kind of item (ContentItem, BlogPost, etc.). The last few calls
will be to RecompileItemUrls(), Publish() and SaveChanges(). The example below
creates a generic content item, populates the properties and finally performs housekeeping
methods to generate the item url, publish and save the item to the database.
ContentManager contentManager = ContentManager.GetManager();contentManager.Provider.SuppressSecurityChecks = true;
ContentItem item = contentManager.CreateContent();
// set item propertiesitem.Title = "My Generic Content Title";item.Name = "MyGenericContent";item.Author = "Bob Smith";item.Content = "My content <b>HTML</b>";item.UrlName = "MyGenericContentUrl";
UserManager userManager = new UserManager();userManager.Provider.SuppressSecurityChecks = true;User user = userManager.GetUsers() .Where(u => u.UserName.Equals("admin")) .FirstOrDefault();
item.Owner = user.Id;
// generates the url and save changes, called each time "item" changescontentManager.RecompileItemUrls<ContentItem>(item);// has been in draft till now, so publishcontentManager.Lifecycle.Publish(item);// commit to databasecontentManager.SaveChanges();
Setting the SuppressSecurityChecks property to True avoids having to deal with
permissions issues for just now. See the Permissions section of this courseware for more
information.
You may also want to set the "Owner" for the item. An item's Owner is a Guid property
and can be returned by way of the UserManager .
UserManager userManager = new UserManager();userManager.Provider.SuppressSecurityChecks = true;User user = userManager.GetUsers() .Where(u => u.UserName.Equals("bsmith")) .FirstOrDefault();
The code above returns a User object from the Telerik.Sitefinity.Security.Model
namespace. The User.Id property is the Guid that represents a particular user and can be
assigned to an item's Owner property.
Using the Sitefinity API 293
© 2012 Falafel Software
// set item properties ...item.Owner = user.Id;
Figure 272 --The Resulting Item
The resulting item displays in the
list of Content Block items.
Retrieving, Deleting and Editing Items
Each of the "FooManager" objects has a "GetFoo()" method that returns an IQueryable<T>
of whatever kind of object you're working with. You can use the IQueryable<T> as a
starting point for both iterating lists and selecting individual elements in the list.
Retrieve a List of Content Items
The ContentManager GetContent() method returns an IQueryable of ContentItem. You
can use the entire list or filter using LINQ. For example, if you want to display all the
generic content visible to the public, use a Where() clause to check the life cycle status of
the item.
ContentManager contentManager = ContentManager.GetManager();contentManager.Provider.SuppressSecurityChecks = true;
IQueryable<ContentItem> items = contentManager .GetContent() .Where(i => i.Status == ContentLifecycleStatus.Master); foreach (ContentItem item in items){ string response = String.Format("{0}<br />{1}<br /><br />", item.Title, item.Content); Response.Write(response);};
Sitefinity 5294
© 2012 Falafel Software
Retrieve an Instance, Deletion
If you want to return a particular ContentItem, use the Where() clause to pinpoint a
specific element in the list. The example below deletes a single item. First, a lambda
expression in the Where() extension method returns a content item with a particular title.
The FirstOrDefault() method returns a single instance of the item. Finally, the
ContentManager Delete() method is passed the ContentItem to be deleted.
ContentManager contentManager = ContentManager.GetManager();contentManager.Provider.SuppressSecurityChecks = true;
ContentItem item = contentManager .GetContent() .Where(i => i.Title.Equals("My Generic Content Title")) .FirstOrDefault();contentManager.Delete(item);
contentManager.SaveChanges();
Using the Sitefinity API 295
© 2012 Falafel Software
Edit
To edit an item, get an instance of the item and simply set it's properties. The example
below gets a reference to a single generic content item and updates the Content property
with text. Once you're done with setting properties, call the ContentManager
SaveChanges() method to retain the new properties in the database.
ContentManager contentManager = ContentManager.GetManager();contentManager.Provider.SuppressSecurityChecks = true;
ContentItem item = contentManager .GetContent() .Where(i => i.Status == ContentLifecycleStatus.Master) .Where(i => i.Title.Equals("My Generic Content Title")) .FirstOrDefault();
item.Content = "New content set at " + DateTime.Now.ToLongTimeString();
contentManager.RecompileItemUrls<ContentItem>(item);contentManager.Lifecycle.Publish(item);contentManager.SaveChanges();
Sitefinity 5296
© 2012 Falafel Software
Q & A...
Question: When I enter a news item, events, blog, etc there are 2 rows entered into
the table for that record, Why is there 2 rows?
Answer: Each piece of content has 3 stages:
Master - This is the primary state of an item and always exists. You see only drafts
in the backend.
Temp - This is a copy of the item that exists to mark changes in an edit screen. It
marks the item as locked.
Live - This is a snapshot of the item that is visible on the public side.
Using the Sitefinity API 297
© 2012 Falafel Software
Publishing
For items that must be published through the lifecycle, e.g. News, Blogs, Pages, you will
need to publish by sending a message to notify the workflow manager of the new status.
The general pattern to do this is to create a dictionary with a single "ContentType" key that
points to the FullName of the type you're working with. Then call the WorkflowManager.
MessageWorkflow() method passing:
The Guid id of the item.
The type of the item.
If you have a custom provider you can pass it, but typically this will be null.
The name of the operation, i.e. "Publish".
If the item is already checked out, this parameter should be true.
The dictionary.
var bag = new Dictionary<string, string>(); bag.Add("ContentType", YourType.FullName); WorkflowManager.MessageWorkflow(ModuleItem.Id, TestType, null,"Publish", false, bag);
Here's an example of creating and publishing an News item:
NewsManager newsManager = NewsManager.GetManager();Guid masterNewsId = Guid.NewGuid();string newsTitle = "news title";string newsContent = "news content";NewsItem newsItem;newsItem = newsManager.CreateNewsItem(masterNewsId);
newsItem.Title = newsTitle;newsItem.Content = newsContent;newsItem.DateCreated = DateTime.UtcNow;newsItem.PublicationDate = DateTime.UtcNow;newsItem.LastModified = DateTime.UtcNow;newsItem.UrlName = Regex.Replace(newsTitle.ToLower(), " ", "_");newsManager.SaveChanges();
//Publish the news item through workflowvar bag = new Dictionary<string, string>();bag.Add("ContentType", typeof(NewsItem).FullName);WorkflowManager.MessageWorkflow(masterNewsId, typeof(NewsItem), null, "Publish", false, bag);
Sitefinity 5298
© 2012 Falafel Software
Summary
This chapter explained how to work with the Sitefinity API. First you learned how to
create a Sitefinity page programmatically and then how to display the hierarchy of pages
in a tree view. You also created content programmatically and performed CRUD (Create
Read Update Delete) operations against content items. Finally, you added a
programmatically created content item to a page, on-the-fly.
15Authentication and Security
Sitefinity 5300
© 2012 Falafel Software
15 Authentication and Security
Operations in Sitefinity frequently require certain permissions. Permissions require
authentication, that you are who you say you are, for Sitefinity to know what permissions
to give you.
Authentication and Security 301
© 2012 Falafel Software
Objectives
This chapter demonstrates how to login and logout programmatically, how to create a
user, how to create a role and how to assign a role to a user.
Sitefinity 5302
© 2012 Falafel Software
Claims vs Forms Authentication
Using the default Claims Authentication within Sitefinity, you will no longer "hit the wall"
when trying to integrate your site within a larger security framework. Prior to version 5.x,
Sitefinity used Forms Authentication to verify user credentials and allow access to Sitefinity
applications. Forms Authentication essentially retrieved the user's name/password and
checked it against user data stored in the database for that particular application. That
works well enough but comes up short in scenarios required by many organizations:
"Single Sign On" (SSO) where you have several Sitefinity sites that should have only one
login for the user. SSO allows you to show a single site to the user that is actually made
up of multiple sites.
When you need to use authentication provided from outside the Sitefinity application, e.
g. Active Directory domains, another application or certificate authorities.
When the login comes from a non-standard source such as biometric authentication.
When authentication lifespan should not be tied to cookie expiration. Using Forms
Authentication, the authentication information is stored in a cookie and the user is
logged out when the cookie expires.
Claims Authentication is a more robust approach that uncouples authentication from the
application logic. Claims authentication uses these components:
Subject is an entity that is being authenticated, e.g. a user.
An Issuer makes claims about the subject and issues security tokens.
A Claim is an assertion about the subject, e.g. the user's name or thumbprint.
A Token is a digitally signed string created when the issuer makes a claim about a
subject. The token contains authentic details about the subject.
The Sitefinity Claims Authentication implementation doesn't directly impact backend
administration or even API programming within the web site. The real boost comes in
integrating with other Sitefinity sites, applications and services. Sitefinity REST web
services for example require a call up front to retrieve the claims token. After that, you just
pass the token in the request headers of each REST web service call.
Authentication and Security 303
© 2012 Falafel Software
Setting the Authentication Type
By default, user authentication is handled through Claims based authentication. If you have
a site built with an older version of Sitefinity that uses web services, you may revert to
Forms authentication. To toggle this setting, go to Administration > Settings (Basic Settings)
> User Authentication.
Figure 273 --Reverting to Forms Authentication
For all projects going forward, Claims Authentication is the stronger choice.
Sitefinity 5304
© 2012 Falafel Software
Login Programmatically
To login programmatically, use the SecurityManager object and call the
AuthenticateUser() method. There are several overloads of this method that all take some
combination of user name and password. The example below passes a Credentials object,
that simply packages up the user name, password, persistence and provider. If the
Persistent property is true, then the authentication cookie is retained between sessions.
Credentials credentials = new Credentials(){ UserName = "admin", Password = "password", Persistent = true,};var result = SecurityManager.AuthenticateUser(credentials);
if (result == UserLoggingReason.Unknown){ // throw exception here}
AuthenticateUser returns a UserLoggingReason enum member that you check before
taking action. For example, UserLoggingReason.Unknown indicates an invalid username
or password. You can use the other members of UserLoggingReason if you need even
more specific information about how the site is being used:
UserLoggingReason Enum Member Description
Success User was successfully registered as logged in
UserLimitReached The limit of maximum simultaneous logged in users is
reached
UserNotFound User not found in any provider
UserLoggedFromDifferentIp User is already logged in from a different IP address
SessionExpired Indicates that the user logical session has expired
UserLoggedOff User has the authentication cookie but is not logged in the
database or user is already logged out.
UserLoggedFromDifferentComputer More than one user trying to login from the same IP but
from different computers.
Unknown Invalid username or password specified.
Authentication and Security 305
© 2012 Falafel Software
UserLoggingReason Enum Member Description
NeedAdminRights User is not administrator to logout other users
UserAlreadyLoggedIn User already is logged in. We need to ask the user to
logout or to logout someone else .
UserRevoked User was revoked: the user was deleted or user rights and
role membership was changed.
Sitefinity 5306
© 2012 Falafel Software
Logout Programmatically
To logout programmatically, simply call the SecurityManager static Logout() method. This
logs out the user making the current request.
SecurityManager.Logout();
You can also use a Logout() overload if you need to pass specific credentials:
Credentials credentials = new Credentials(){ UserName = "admin", Password = "password",};SecurityManager.Logout(credentials);
Gotcha!
You must have administrative rights to logout other users or match the
credentials of the user to perform the logout, otherwise an
UnauthorizedAccessException is thrown.
Authentication and Security 307
© 2012 Falafel Software
Create a User
To create a user, first get an instance of the UserManager by calling GetManager(). Then
call the CreateUser() method and pass the login name. Populate the returned User object
properties, then finally call the SaveChanges() method.
UserManager userManager = UserManager.GetManager();User user = userManager.CreateUser("ayamada");user.Password = "password";user.Email = "[email protected]";user.FirstName = "Aiko";user.LastName = "Yamada";user.Comment = "Popular blogger";userManager.SaveChanges();
Another overload of CreateUser() allows you to set many of the properties of the User at
one time and also returns a MembershipCreateStatus. If the status is equal to Success,
then you can set more properties of the user object and finally call the SaveChanges()
method.
MembershipCreateStatus createStatus;
UserManager userManager = UserManager.GetManager();
User user = userManager.CreateUser( // user name "ayamada", // password "password", // email "[email protected]", // security question "what is your favorite pet's name?", // security answer "spot", // isApproved true, // provider user key null, // create status out createStatus);
if (createStatus == MembershipCreateStatus.Success){ user.FirstName = "Aiko"; user.LastName = "Yamada"; userManager.SaveChanges();}
Sitefinity 5308
© 2012 Falafel Software
Roles and Permissions
You now have a user in the system, but what can they do? Not a thing. A new user is not
associated with any roles in the system and therefore has no permissions to do anything.
To give the user permissions to do something, you must add the person to a role. The
basic elements to associating a role with a user are:
Get an instance of a RoleManager for a particular providers. The built-in providers
available out-of-the-box are listed in Settings > Security > Role Providers. Use the
"AppRoles" provider when trying to get at roles already in the system, such as
"Administrators" or "BackendUsers". For roles you create yourself, use the "Default"
provider.
Figure 274 --List of Role Providers
Get a specific Role, e.g. "BackendUsers" or "Authors".
Add the User to a Role.
Save changes.
Authentication and Security 309
© 2012 Falafel Software
This walk-through demonstrates creating a user and adding that user to the
"BackendUsers" and "Authors" roles.
1) Add the code below to create the User object and respond to the returned status. The
code can be added to the Page_Load event of a standard ASP.NET page.
MembershipCreateStatus createStatus;
UserManager userManager = UserManager.GetManager();
User user = userManager.CreateUser( "ayamada", "password", "[email protected]", "what is your favorite pet's name?", "spot", true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success){ userManager.SaveChanges(); // role code goes here -->}
2) Replace the comment "role code goes here -->" with the code below. The code returns
a RoleManager for the built in "AppRoles". The GetRoles() method returns an
IQueryable of Roles, suitable for LINQ expressions. The LINQ is used to single out the
role named "BackendUsers", then the role for "Authors". The RoleManager
AddUserToRole() method establishes the association between the two. Don't forget to
call the SaveChanges() method for the RoleManager (not just the UserManager).
// get the built in rolesRoleManager roleManager = RoleManager.GetManager(SecurityManager.ApplicationRolesProviderName);
// retrieve the "BackendUsers" roleRole backendUserRole = roleManager.GetRoles() .Where(r => r.Name.Equals(SecurityManager.BackendUsersRoleName)))) .Single();
// retrieve the "Authors" roleRole authorRole = roleManager.GetRoles() .Where(r => r.Name.Equals("Authors")) .Single();
// add the user to both rolesroleManager.AddUserToRole(user, backendUserRole);roleManager.AddUserToRole(user, authorRole);
// save the new role settingsroleManager.SaveChanges();
Sitefinity 5310
© 2012 Falafel Software
3) Run the application, then find the user in the Sitefinity Administration > Users list.
Notice that the "BackendUsers" and "Authors" roles have been added.
Figure 275 --New User w ith Roles Assigned
Authentication and Security 311
© 2012 Falafel Software
Summary
This chapter demonstrated how to login and logout programmatically, how to create a
user, how to create a role and how to assign a role to a user.
16Using the Fluent API
Using the Fluent API 313
© 2012 Falafel Software
16 Using the Fluent API
The Fluent API is a simplified interface, or Facade, over the full Sitefinity API. It provides
an easy-to-use syntax for being productive with Sitefinity development right away. The
single entry point App followed by the method WorkWith() returns an instance of the
Fluent API.
var fluent = App.WorkWith();
After the call to WorkWith() follows the specific interface you want to work with. For
example, if you want to work with generic content items, you would write the code below,
where ContentItem() is the gateway to all methods that access a single content item.
App.WorkWith() .ContentItem();
From there you can call one of the content item methods, such as CreateNew();
App.WorkWith() .ContentItem() .CreateNew()
Using the Fluent API, you can continue to chain methods to perform some logical task in a
single line of easy-to-read, maintainable code. The example below creates a new generic
content item, assigns the properties, publishes the item and saves to the database.
App.WorkWith() .ContentItem() .CreateNew() .Do(c => { c.Title = "My Fluent Title"; c.Name = "MyFluentContent"; c.Content = "<h1>Fluent Content<h1>"; c.UrlName ="MyGenericContentUrl"; }) .Publish() .SaveChanges();
Notes
Notice the convention where each method is lined up vertically. Long chains of
method calls are easier to read when structured this way.
Sitefinity 5314
© 2012 Falafel Software
Objectives
This chapter demonstrates how the Fluent API works with pages and content items. You
will learn how to upload images and documents. In particular, you will use a web service
to load images to an Album en-masse. Finally, you will use the Fluent API to return lists of
content items, filter, sort and select content items into useful subsets and then bind your
results to ASP.NET controls.
Using the Fluent API 315
© 2012 Falafel Software
Fluent API Facades
App.WorkWith() returns a FluentSitefinity representing a single request to the fluent
API. The FluentSitefinity class contains a series of methods that return facades for specific
modules in Sitefinity including:
Albums and Images
Generic Content Items
Blogs and BlogPosts
Documents and Document Libraries
Events
Dynamic Data
Pages
News Items
Videos and Video Libraries
Sitefinity 5316
© 2012 Falafel Software
Working with Pages
Using the Fluent API, you can create new pages and perform operations against multiple
pages at once. The Fluent syntax makes it easy to include methods that checkout draft
versions of a page, publish and save changes to the database.
Creating Pages Programmatically
1) In Page_Load of an ASP.NET page in the Sitefinity project, add the code below. In a
single line of Fluent code, this statement creates a standard page, populates the
properties for the page, creates a draft of the page, saves the page to the database and
publishes through the WorkflowManager.
SecurityManager.AuthenticateUser(String.Empty, "admin", "password", false);
var pageId = Guid.NewGuid();
App.WorkWith() .Page() .CreateNewStandardPage(pageId) .Do(p => { p.Name = "MyFluentPage"; p.Title = "My Fluent Page"; p.Page.Title = "My Fluent Page"; p.Description = "My Fluent Page Description"; p.ShowInNavigation = true; p.UrlName = "MyFluentPage"; }) .CheckOut() .Publish() .SaveChanges();
// publish through the workflowvar bag = new Dictionary<string, string>();bag.Add("ContentType", typeof(PageNode).FullName);WorkflowManager.MessageWorkflow(pageId, typeof(PageNode), null, "Publish", false, bag);
SecurityManager.Logout();
2) Run the application, then navigate to the Sitefinity Administrator Pages to view the new
page.
Using the Fluent API 317
© 2012 Falafel Software
Figure 276 --New Page Added Using Fluent API
Show Hiearchy of Pages
To get page objects, simply use the Pages() method facade. If you're binding to some
control that requires a hierarchical representation, such as RadTreeView, be sure to get
both the Id of the current page and the Parent's Id property. The example below retrieves
all pages in the system, projects properties into a new anonymous type and binds to a
RadTreeView.
SecurityManager.AuthenticateUser(String.Empty, "admin", "password", false);
var pages = App.WorkWith() .Pages() .Get() .ToList() .Select(p => new { Id = p.Id, ParentId = p.Parent == null ? Guid.Empty : p.Parent.Id, Title = p.Title, Published = p.ApprovalWorkflowState == "Published" });
RadTreeView1.DataSource = pages;RadTreeView1.DataTextField = "Title";RadTreeView1.DataFieldID = "Id";RadTreeView1.DataFieldParentID = "ParentId";RadTreeView1.DataBind();
SecurityManager.Logout();
Sitefinity 5318
© 2012 Falafel Software
Figure 277 --Pages From
the Fluent API
The pages display listed in the RadTreeView.
Using the Fluent API 319
© 2012 Falafel Software
Working with Content Items
Creating Items
To create any kind of item with the Sitefinity Fluent API, first start with App.WorkWith()
method to access all the available facades. This is followed by the specific facade you want
to work with. The example below is using the NewsItem facade, followed by a call to
CreateNew(). The Do() method contains a lambda expression that allows you to populate
all the fields of the NewsItem object. Finally, a call to SaveChanges() retains the object in
the database. There is no call to the Publish() method in this example. Instead, the
PublicationDate is set to seven days in the future.
App.WorkWith() .NewsItem() .CreateNew() .Do(n => { n.Title = "Vintage Cars"; n.Content = "The Vintage Cards Field Guide helps locate hard to find parts"; n.Author = "Bob Smith"; n.SourceSite = "http://www.vcfg.net"; n.SourceName = "Vintage Cars Field Guide"; n.PublicationDate = DateTime.Now.AddDays(7); }) .SaveChanges();
The item shows up in the list of News content:
Figure 278 --The Fluent API Generated News Item
Sitefinity 5320
© 2012 Falafel Software
The Title and Properties for the news item reflect the property settings set in the Do()
method.
Figure 279 --News Item Title and Properties
Using the Fluent API 321
© 2012 Falafel Software
Uploading Images and Documents
You can add a new item that has text by simply calling CreateNew() and setting some
properties within the Do() method lambda. How do you get binary objects like images or
PDF files into the system? The short answer is that you have to perform an additional step
of uploading the content.
Fortunately, the Fluent API includes a method to handle this situation: the
UploadContent() method takes a stream of bytes and a file extension. The partial example
below shows the general pattern uploading a "jpg" image to an Album.
byte[] bytes = GetSomeData(); Stream stream = new MemoryStream(bytes);App.WorkWith() .Album(album.Id) .CreateImage() .Do(item =>{ item.Title = "My Title";}).CheckOut().UploadContent(stream, ".jpg").CheckInAndPublish().SaveChanges();
Sitefinity 5322
© 2012 Falafel Software
Uploading an Image
To upload an image:
1. Get a reference to an Album. The example below gets an Album reference where the
title is "Default Album".
2. Get a stream of bytes representing the image. The example below uses the WebClient
object to download data directly from a given url. The example uses a url to one of the
"built with Telerik controls" icons.
Using the Fluent API 323
© 2012 Falafel Software
3. Upload the byte stream to the album. To do this, first call CheckOut() on the album,
then UploadContent() followed by CheckIn() and finally to Publish(). UploadContent
() parameters takes the stream of bytes followed by the name of the extension (don't
forget the leading ".").
SecurityManager.AuthenticateUser(String.Empty, "admin", "password", false);
const string url = "http://www.telerik.com/libraries/company/builtwith_white.sflb";
using (var fluent = App.WorkWith()){ // get the album Album album = fluent.Albums() .Where(a => a.Title == "Default Library") .Get() .SingleOrDefault();
// download the image byte stream WebClient webClient = new WebClient(); byte[] bytes = webClient.DownloadData(url); Stream stream = new MemoryStream(bytes);
// upload the bytes to the album fluent .Album(album.Id) .CreateImage() .Do(item => { item.Title = "Telerik Logo"; }) .CheckOut() .UploadContent(stream, ".gif") .CheckIn() .Publish() .SaveChanges();
SecurityManager.Logout();
The uploaded image shows with its title in the Default Album.
Figure 280 --The Uploaded Image
Sitefinity 5324
© 2012 Falafel Software
Uploading En-masse From a Web Service
Tweets, blogs, web services and RSS feeds all offer the possibility of loading large blocks of
content, all at one time. The Xdocument class along with LINQ can work with the Fluent
API to move XML content to your web site. This is particularly useful for one-time
migration tasks, but can be used for any occasion where a Url points to XML data.
The general steps for uploading from an XML source that contains urls to images:
1. Create a custom class to contain each image title and url.
2. Get a list objects with image data from a Url with XML data.
3. Get an existing Album to contain the images. Create a new Album if necessary.
4. Upload the images.
The walk-through that follows uses the Bing API to get a series of images. You will need to
apply for a developer's application ID to complete the walk-through. To get an ID, follow
the prompts at:
http://www.bing.com/developers/
Notes
RSS feeds typically don't require an ID. Most of the public API REST services, such
as Google, Flickr, Imgur, etc. all require an application ID. Some may also require
additional authorization.
Be aware that you are responsible for your use of any REST services, so be sure to
read and follow the agreements and documentation.
Using the Fluent API 325
© 2012 Falafel Software
Create Custom Class
We could use anonymous types to hold the results of the Bing request. Instead, we will
create a custom object that can be passed easily between methods.
1) Create a new class in your project and name it "BingResult".
2) Replace the class code with the code below.
public class BingResult{ public String Title { get; set; } public String Url { get; set; }}
Make Bing Request
1) In the code behind for the startup page in your project, add the GetBingResults()
method below.
private static IEnumerable<BingResult> GetBingResults(String searchOn){ const string BingAppId = "<Your App ID string goes here>"; // see http://www.b ing.com/developers/ to get id
// request url, along with app id and parameters string requestString = "http://api.bing.net/xml.aspx?" + "&AppId=" + BingAppId + "&Query=" + searchOn + "&Sources=Image" + "&Adult=Strict" + "&Image.Count=10";
// namespace used to qualify elements XNamespace ns = "http://schemas.microsoft.com/LiveSearch/2008/04/XML/multimedia";
// load the url as an xdocument Xdocument document = XDocument.Load(requestString);
// use LINQ to parse and project document elements to custom class IEnumerable<BingResult> results = from r in document.Descendants(ns + "ImageResult") select new BingResult { Title = r.Element(ns + "Title").Value, Url = r.Element(ns + "Thumbnail").Element(ns + "Url").Value };
return results;}
Sitefinity 5326
© 2012 Falafel Software
The method defines a request to the Bing API using some of the query string
parameters as defined in the Bing API documentation. The XDocument.Load()
method does the grunt work of downloading from a given Url into an Xdocument.
Xdocument exposes Elements, where each Element has a Value property. LINQ
expressions make it easy to project results into another object type. In this case, the
parsed results are projected into a collection of BingResult objects and returned.
Get Album
1) In the code behind for the page, add the GetAlbum() method code listed below.
private static Album GetAlbum(String title){ // get an existing album with a given title Album album = App.WorkWith() .Albums() .Where(a => a.Title.Equals(title)) .Get() .SingleOrDefault();
// if the album doesn't exist, create it if (album == null) { App.WorkWith() .Album() .CreateNew() .Do(a => { a.Title = title; }) .Get(out album) .SaveChanges(); } return album;}
The method first uses the Fluent API to get an Album that has a particular title. If the
Album doesn't exist, the second statement in the method creates the Album object.
Using the Fluent API 327
© 2012 Falafel Software
Upload Images to Album
1) Add a method to upload a single image using the information from a BingResult object,
to a particular Album.
private static void UploadSingleImage(Album album, BingResult result){ // use WebClient to download image from url, get stream WebClient webClient = new WebClient(); byte[] bytes = webClient.DownloadData(result.Url); Stream stream = new MemoryStream(bytes);
// create the Sitefinity Image, set the title and upload stream App.WorkWith() .Album(album.Id) .CreateImage() .Do(item => { item.Title = result.Title; }) .CheckOut() .UploadContent(stream, ".jpg") .CheckIn() .Publish() .SaveChanges();}
This method first uses the WebClient object to download from an image url as a
stream of bytes. Then the Fluent API creates a new Image object and uploads the
image stream to the image.
Putting It All Together
1) Add the code below to the Page_Load event handler for the startup page of your
project.
protected void Page_Load(object sender, EventArgs e){
// add authentication here...
String subject = "Model T";
IEnumerable<BingResult> results = GetBingResults(subject);
Album album = GetAlbum(subject);
foreach (BingResult result in results) { UploadSingleImage(album, result); }}
Sitefinity 5328
© 2012 Falafel Software
The GetBingResults() method returns an IEnumerable of BingResult for a search on
"Model T", the GetAlbum() method ensures there is an album with the title of "Model
T", and finally, the results are uploaded, one-at-a-time to the album.
2) Replace the comment "add authentication here..." with the code below. Replace the
user name and password with a valid user name and password for your Sitefinity web
site that has permissions to create albums and images.
protected void Page_Load(object sender, EventArgs e){ SecurityManager.AuthenticateUser(new Credentials() { UserName = "admin", Password = "password" });
//. . .}
3) Run the application, then check the Images administration page to view the results. You
should see images uploaded into the new album.
Figure 281 --Uploaded Images
Using the Fluent API 329
© 2012 Falafel Software
Uploading Documents
Any kind of document can be uploaded to a Sitefinity Library as a stream. The pattern is
parallel to the example in Upload Images to Album. You'll need to get a stream of bytes
that contains your document. Bytes can come from a Url using WebClient methods or
from your local file system using System.IO objects.
This example assumes you have a "\Documents" folder in the project with one or more
files. Server.MapPath() gets the physical directory path of "\Documents", then uses the
DirectoryInfo GetFiles() method to access an IEnumerable of FileInfo. FileInfo, in turn,
has an Open() method that returns a stream. In the code below, notice the
UploadContent() method takes the FileInfo.Open() to get the byte stream and the
FileInfo.Extension property to sense whether this file is a .doc, .pdf, .xlsx, etc.
SecurityManager.AuthenticateUser(String.Empty, "admin", "password", false);
var path = Server.MapPath("~\\Documents");var files = new DirectoryInfo(path).GetFiles();
// create the Sitefinity Image, set the title and upload streamusing (var fluent = App.WorkWith()){ // get the default lib rary var defaultLibrary = fluent .DocumentLibraries() .Where(lib => lib.Title == "Default Library") .Get() .FirstOrDefault();
// get the stream for each file and upload foreach (var file in files) { fluent .Document() .CreateNew() .Do(doc => { doc.Parent = defaultLibrary; doc.Title = file.Name; }) .CheckOut() .UploadContent(file.Open(FileMode.Open), file.Extension) .CheckIn() .Publish() .SaveChanges(); }}
SecurityManager.Logout();
Sitefinity 5330
© 2012 Falafel Software
The uploaded documents are displayed in the library with the appropriate icons for each
file type.
Figure 282 --Uploaded Documents
Using the Fluent API 331
© 2012 Falafel Software
Retrieving Collections of Content Items
To get a list of items, first start with App.WorkWith() to get at the Fluent API facades. Use
the plural method name of whatever content you're interested such as NewsItems or
Albums.
Get FluentSitefinity Methods
How can you find the names of the methods to work with? You can look them up in the
online documentation. You can also get the method names "straight from the horses
mouth" using the Visual Studio. The App.WorkWith() method is actually a
FluentSitefinity object. To peer inside FluentSitefinity:
1. From the View menu in Visual Studio, select the Class View menu option.
2. In the Class View pane, enter "FluentSitefinity" and press Enter.
3. The methods are listed in the lower window. In the screenshot below you can see the
Images, NewsItems and Pages methods that will return collections that you can iterate
or filter using a LINQ Where() method.
Figure 283 --Listing of FluentSitefinity Methods
Sitefinity 5332
© 2012 Falafel Software
Coding the List
The Fluent API facades have a complete set of methods to make LINQ style statements
easier to code, including First(), Last(), Count(), Where(), Skip(), Take(), OrderBy(),
OrderByDescending() and Get().
Filtering
Minimally, you can use the Where() method to filter for Live content items, the Get()
method to convert the facade into a LINQ friendly IQueryable and finally call ToList() to
execute the query and return a generic List<> of the specific type you want to work with.
The example below demonstrates getting a simple list of live news items, iterates the list
and prints out the titles.
List<NewsItem> news = App.WorkWith() .NewsItems() .Where(n => n.Status == ContentLifecycleStatus.Live) .Get() .ToList();
foreach (NewsItem newItem in news){ this.Response.Write(newItem.Title + "<br />"); }
Sorting
You can order the list using the OrderBy() or OrderByDescending method methods to
sort the list by any column. Both methods take a lambda expression that can be used to
reference the columns you want to sort on. Using the OrderByDescending() along with
Take() methods you can get the top five news items based on the most recent publication
date. The example below filters for all the live news items, sorts them in descending order
and returns five items.
List<NewsItem> news = App.WorkWith() .NewsItems() .Where(n => n.Status == ContentLifecycleStatus.Live) .OrderByDescending(o => o.PublicationDate) .Take(5) .Get() .ToList();
foreach (NewsItem newItem in news){ this.Response.Write(newItem.Title + "<br />");}
Using the Fluent API 333
© 2012 Falafel Software
Projections
Use the Select() method to "project" the items properties into another class. This can be a
custom class you write or an anonymous class. The example below projects NewsItem
properties into a list of MyNewsItem objects. The Select() method takes a lambda
expression that surfaces the properties of the NewsItem. For each NewsItem, a new
MyNewsItem is created and populated with the NewsItem properties.
public class MyNewsItem{ public String Title { get; set; } public String Description { get; set; } public String Summary { get; set; }}
//. . .
IEnumerable<MyNewsItem> news = App.WorkWith() .NewsItems() .Where(n => n.Status == ContentLifecycleStatus.Live) .Get() .ToList() .Select(ni => new MyNewsItem() { Title = ni.Title, Description = ni.Description, Summary = ni.Summary });
foreach (MyNewsItem newItem in news){ this.Response.Write(newItem.Title + "<br />");}
Notes
The IEnumerable<MyNewsItem> news in the example above could be stated as
var news. The longer syntax is used here for learning purposes so you can easily see
what kind of objects we're working with.
Sitefinity 5334
© 2012 Falafel Software
You can just as easily create an anonymous type without having to specifically code a
"MyNewsItem" class. In the code example below, notice that in the Select() method
lambda, the new keyword is used and is not followed by a class name. .Net creates an
anonymous class where the property names correspond to the names in the lambda
expression on the left, i.e. "Title", "Description" and "Summary".
var news = App.WorkWith() .NewsItems() .Where(n => n.Status == ContentLifecycleStatus.Live) .Get() .ToList() .Select(ni => new { Title = ni.Title, Description = ni.Description, Summary = ni.Summary });
Using the Fluent API 335
© 2012 Falafel Software
Binding Lists to Controls
While this topic doesn't strictly relate to Sitefinity only, you may want to interact with
ASP.NET controls within a standard ASP.NET page or a widget of a Sitefinity page. This
topic describes how to populate controls with data from the Sitefinity Fluent API.
To display and manipulate data, you will need to bind the Sitefinity data to a visual control.
Binding involves setting properties on the control that specify where the data is and what
columns of the data should be displayed. You can bind any object that implements
IEnumerable including arrays and generic lists. The code below can be included in the
Page_Load event handler of a standard page. The example creates a list of anonymous
objects and binds to a standard ASP.NET DropDownList control.
Assign the list of Sitefinity items to the control's DataSource property. The DataTextField
is assigned the property that you want to display in the control. The DataValueField can
be assigned a property that you want to reference when the user selects an item in the list.
Be sure to call the DataBind() method so that the binding takes place and the data
displays in the control.
var news = App.WorkWith() .NewsItems() .Where(n => n.Status == ContentLifecycleStatus.Live) .Get() .ToList() .Select(ni => new { Id = ni.Id, Title = ni.Title, Description = ni.Description, Summary = ni.Summary });
ListBox1.AutoPostBack = true;ListBox1.DataSource = news;ListBox1.DataTextField = "Title";ListBox1.DataValueField = "Id";ListBox1.DataBind();
The screenshot below shows the titles of the two live news items in the system.
Figure 284 --Bound Control
Sitefinity 5336
© 2012 Falafel Software
The specific control will typically have some event that allows you to retrieve the selected
item. The ListBox control, for example, has a SelectedValue property. The DataValueField
assigned in the binding, is available as the SelectedValue when the selection changes. The
SelectedIndexChanged event handler code example below retrieves the SelectedValue (a
string) and converts the string to a Guid. The Guid is the Id for a news item. Use this Guid
in the Where() method lambda to retrieve the NewsItem object.
protected void List_SelectedIndexChanged(object sender, EventArgs e){ Guid id = Guid.Parse((sender as ListBox).SelectedValue); var newsItem = App.WorkWith() .NewsItems() .Where(ni => ni.Id.Equals(id)) .Get() .FirstOrDefault(); RightPane.ContentUrl = "http://www.bing.com/search?q=" + newsItem.Title;
}
The NewsItem object is used to populate other controls. In this example, RadPane is
displaying a Bing web search for the selected NewsItem Title.
Figure 285 --Selected NewsItem Title Search
Using the Fluent API 337
© 2012 Falafel Software
Summary
This chapter demonstrated how the Fluent API works with pages and content items. You
learned how to upload images and documents. In particular, you used a web service to
load images to an Album en-masse. Finally, you used the Fluent API to return lists of
content items, then filtered, sorted and selected content items into useful subsets and
bound those results to ASP.NET controls.
17Working with Forms
Working with Forms 339
© 2012 Falafel Software
17 Working with Forms
To work with Forms programmatically, you can use the standard API FormsManager .
Using the FormsManager you can retrieve lists of forms, a single form description and all
the entries for a form.
Sitefinity 5340
© 2012 Falafel Software
Objectives
This chapter explains how to programmatically retrieve forms and form items. This
chapter will also discuss how to get at the form entry column names and captions.
Working with Forms 341
© 2012 Falafel Software
Getting a List of All Forms
To list every form on your website, use the GetForms() method. The method returns an
IQueryable of FormDescription objects. You can perform operations against each
FormDescription using the FormsManager. The example below iterates the list looking for
forms where the Name property contains the word "test" and deletes each matching
instance.
protected void DeleteTestFormsButtonClick(object sender, EventArgs e){ SecurityManager.AuthenticateUser(String.Empty, "admin", "password", false);
using (FormsManager formsManager = FormsManager.GetManager()) { var forms = formsManager.GetForms().Where(f => f.Name.ToLower().Contains("test"));
foreach (var form in forms) { formsManager.Delete(form); }
formsManager.SaveChanges(); }
SecurityManager.Logout();}
You can also bind the collection directly as a DataSource. The example below populates a
RadComboBox with the names of each form. Notice that the DataValueField, a string
property, contains the string representation of a Guid Id for a given form.
protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { using (FormsManager formsManager = FormsManager.GetManager()) { RadComboBox1.DataSource = formsManager.GetForms().ToList(); RadComboBox1.DataTextField = "Title"; RadComboBox1.DataValueField = "Id"; RadComboBox1.DataBind(); RadComboBox1.SelectedIndex = 0; } }}
Sitefinity 5342
© 2012 Falafel Software
The screenshot below shows the titles for each form in a RadComboBox.
Figure 286 --Form Titles
Displayed in a RadComboBox
Working with Forms 343
© 2012 Falafel Software
Retrieve a Single Form
You can use LINQ to filter Forms to access a specific member. If you have a Guid, you can
use the GetForm() method and pass a Guid in the constructor.
protected void RadComboBox1_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e){ string id = RadComboBox1.SelectedValue; using (FormsManager formsManager = FormsManager.GetManager()) { FormDescription formDescription = formsManager.GetForm(new Guid(id)); /// access the FormDescription Title and collection of Entries. }}
Sitefinity 5344
© 2012 Falafel Software
Retrieving Form Entry Values
To retrieve the responses from all the people that have used the form and entered data, use
the FormsManager.GetFormEntries() method. Pass the FormDescription for the form as a
parameter to GetFormEntries(). This will return a collection of FormEntry objects.
Retrieve a Single Column Value
You can use the FormEntry.GetValue() method and pass the name of the column (you
can see the programmer-accessible name in the Sitefinity Administrator when editing the
form). The example below iterates all form entries, retrieves a value for a field named
"newtextbox" and adds the values to a ListBox control.
FormsManager formsManager = FormsManager.GetManager();
// Get the form named "sf_testform"var forms = formsManager.GetForms().Where(f => f.Name == "sf_testform");
foreach (var form in forms){ var records = formsManager.GetFormEntries(form);
// Loop through all the response records for this form foreach (var record in records) { FormEntry fe = (FormEntry)record;
// Grab the newtextbox column value to display in a list box var TextBoxValue = fe.GetValue("newtextbox");
ListBox1.Items.Add(new ListItem() { Text = TextBoxValue.ToString() }); }}
Running in the browser, the ListBox displays the values for each entry.
Figure 287 --Displaying Form
Values
Working with Forms 345
© 2012 Falafel Software
Retrieve All Values
You can bind a list of form entries directly to a control. The example below binds the list of
FormEntry to the DataSource of a RadGrid.
protected void RadComboBox1_SelectedIndexChanged(object sender, Telerik.Web.UI.RadComboBoxSelectedIndexChangedEventArgs e){ string id = RadComboBox1.SelectedValue; using (FormsManager formsManager = FormsManager.GetManager()) { var form = formsManager.GetForm(new Guid(id)); RadGrid1.AutoGenerateColumns = true; var entries = formsManager.GetFormEntries(form); RadGrid1.DataSource = entries; RadGrid1.DataBind(); }}
This brings back all the information for each entry, including various Ids associated with
the entry, DateTime values, source keys, etc. The dynamically created form entry fields are
shown in the last columns on the right, i.e. "FormParagraphTextBox_C003" etc., that the
actual user entries are contained in.
Figure 288 --Entries Data Bound to Grid
Sitefinity 5346
© 2012 Falafel Software
Retrieve Form Entry Column Names and Captions
What if I don't want all columns? What if I only want the list of form entry field names
and captions for the user entry?
With a FormDescription you can spelunk into both the input Controls and output Entries
of the form. As of this writing, to get the field names programmatically requires parsing
the Properties of the Controls. The LINQ statement below gets both the MetaField
property that holds the field name used to access a particular column in code and the Title
property that acts as a label that the user sees when entering data to the form.
public class FormColumn{ public string FieldName { get; set; } public string Caption { get; set; }}
//. . .
private static IEnumerable<FormColumn> GetFormColumns(FormDescription formDescription){ IEnumerable<FormColumn> columns = from c in formDescription.Controls let metaField = c.Properties .FirstOrDefault(p => p.Name.Equals("MetaField")) let labelField = c.Properties .FirstOrDefault(p => p.Name.Equals("Title")) where metaField != null select new FormColumn { FieldName = metaField .ChildProperties .FirstOrDefault(m => m.Name.Equals("FieldName")) .Value, Caption = labelField == null ? String.Empty : labelField.Value }; return columns;}
When the returned columns are bound to a grid, the result looks like the screenshot
below.
Figure 289 --Form Column Data in Grid
Working with Forms 347
© 2012 Falafel Software
Show Only Form Entry Columns
Using the List of column names retrieved in the previous Topic, Retrieving Form Entry
MetaData, you can iterate the meta data and only create grid columns for the user entry
data.
The example in the screenshot below has a checkbox that toggles between showing all
columns and just the data entry columns of the form.
Figure 290 -- Form with All Columns
When the checkbox is off, only the data entry fields display. Also notice that the Captions
for these columns display, not the form field control names.
Figure 291 --Data Entry Fields from the Form
Sitefinity 5348
© 2012 Falafel Software
Create a RadGrid NeedDataSource event handler to reload the grid with the currently
selected form data. NeedDataSource fires when the page is first loaded and in response to
RadGrid Rebind() method calls.
protected void RadGrid1_NeedDataSource(object sender, Telerik.Web.UI.GridNeedDataSourceEventArgs e){ string id = RadComboBox1.SelectedValue; using (FormsManager formsManager = FormsManager.GetManager()) { FormDescription formDescription = formsManager.GetForm(new Guid(id)); RadGrid1.DataSource = formsManager.GetFormEntries(formDescription); }}
The RadGrid PreRender event handler compares the column metadata retrieved from the
form against the grid columns. The grid columns that don't match form entry columns are
hidden. Grid columns that match a form entry are displayed and assigned a friendly
caption for the HeaderText.
protected void RadGrid1_PreRender(object sender, EventArgs e){ RadGrid grid = sender as RadGrid;
string id = RadComboBox1.SelectedValue; using (FormsManager formsManager = FormsManager.GetManager()) { var form = formsManager.GetForm(new Guid(id)); var formColumns = this.GetFormColumns(form);
foreach (GridColumn gridColumn in grid.MasterTableView.AutoGeneratedColumns) { // get a grid column that matches one of the form entry columns FormColumn formColumn = formColumns.Where(c => c.FieldName.Equals(gridColumn.UniqueName)).FirstOrDefault(); // if we can't find a match, hide this column. // If the "All" checkbox is checked, unconditionally show gridColumn.Visible = formColumn != null || ShowAllCheckbox.Checked; // if there is a match, use the form entry caption if (formColumn != null) { gridColumn.HeaderText = formColumn.Caption; } } } grid.Rebind();}
Working with Forms 349
© 2012 Falafel Software
Summary
This chapter explained how to programmatically retrieve forms and form items. This
chapter also discussed how to get at the form entry column names and captions.
18Localization
Localization 351
© 2012 Falafel Software
18 Localization
The ability to localize your entire site to any language is baked right into Sitefinity. You can
localize not only the text but any other content to be relevant to the culture of your
website visitor. The back-end of the website is also fully localizable. All menu items,
button text, labels, etc. are localizable. Predefined "Language Packs" for Sitefinity can be
found at http://www.sitefinity.com/marketplace/modules.aspx.
Sitefinity 5352
© 2012 Falafel Software
Objectives
In this chapter you will learn how to localize front end pages using Sitefinity
Administration, how to localize strings in code, how to localize back end pages and how to
use the Interface Labels & Messages page.
Localization 353
© 2012 Falafel Software
Localizing Front End Pages
In this next walk through we will add the Spanish language and localize a front-end page
to reflect the language choice.
1) Select the Administration menu Settings option.
2) From the list on the left side of the page select the Languages option.
3) Click the Add languages... button.
4) Use the search box to locate "Spanish" in the list and select the check box.
Figure 292 --Selecting "Spanish"
5) Click the Done button. Now the new "Spanish" language entry shows up under the
default "English" entry.
Figure 293 --Selected Languages
Sitefinity 5354
© 2012 Falafel Software
Notes
Notice that the culture code shows up next to each full language name. Also notice
that you can click the Set as default link to use any language as the default. Later,
we'll look at how the user can select the language for themselves.
6) The Multilingual URLs section determines how the localized pages will be organized and
accessed. Leave the default Directories setting.
Using the Directories option, all languages for the site all come under the same
domain, and where the directory name indicates the language. The localized page
versions will use an industry standard, two letter "culture code" to describe the
language. For example "es" is the culture code for Spanish.
Using the Different domains option, the culture code is appended to the front of the
domain. See the descriptions in the screenshot below each option to see how the
URLs are setup.
Figure 294 --Language Access
7) You can even change the language for the backend system by clicking the Manage
backend languages link and adding languages there. Leave the default setting for this
example.
8) Click the Save changes button.
Localization 355
© 2012 Falafel Software
9) Select the Administration menu Pages option. This option will take extra time the
because Sitefinity needs to accommodate the new languages by making database
changes. When the list refreshes, all the pages in our site are "localization ready" and
have a new Translations column.
Figure 295 --Localization Ready Pages
10)Click the ES Add link for the Welcome page.
Figure 296 --Adding a Page Translation
Sitefinity 5356
© 2012 Falafel Software
11)Create a page (ES) displays so you can supply a new page Name, URL and Title in the
appropriate language.
Figure 297 --Creating the Translated Page
Tip!
To test your pages without performing a production level translation, use Google's
translation service at http://translate.google.com.
Figure 298 --Google's Translation Service
12)Click the Create and go to add content button.
Localization 357
© 2012 Falafel Software
13)Now you have the option of Copying from another language, or to Start from Scratch.
This option is especially important if you have images that you want to copy between
versions. Click the Copying from another language link.
14)The Copy content from another language dialog displays. The English language is the
only version available for this page, so the drop down list is disabled. Select the "Keep all
language versions synced" check box. Click the Done button to close the dialog.
Figure 299 --Copy Content Dialog
Sitefinity 5358
© 2012 Falafel Software
15)The translated page displays. Notice the message at the top of the page that lets you
know that the pages are synced and what kind of behavior you can expect while
designing the page. Also notice that most of the widgets are not populated with content
yet. Except for the Download List at the end of the page that shows the document titles.
Figure 300 --Translated Page
16)Click the Content block Edit button.
17)Paste "Bienvenido a CarConduit!" into the editor window. Click the Save button.
18)Click the Publish button. Publishing pushes out all the translations. .
Localization 359
© 2012 Falafel Software
19)View the page. Notice the Url in the address bar uses the culture code "es". The translatedcontent shows at the head of the page.
Figure 301 --The Translated Page
Sitefinity 5360
© 2012 Falafel Software
User Language Selection
You can use the Language Selector widget right in your page so that the user can
dynamically choose the language they want to view the page in.
1) Open the localized page for editing again.
2) In the Drag Widgets area to the right side to the page, locate the Navigation section and
open it. Drag the Language selector widget to the top of the page.
3) Click the Language selector widget Edit button. In the Display language selector as...
option, select Drop-down menu.
Also notice the options to include the current language in the selector.
What to do with languages without translations? You can Hide the link to the missing
translation or Redirect to the home page....
Figure 302 --Configuring the Language Selector
4) Click the Save button to close the dialog.
Localization 361
© 2012 Falafel Software
5) Publish and view the page. Use the drop down language selection to show both
translations of the page.
Sitefinity 5362
© 2012 Falafel Software
Localizing In Code
Once Sitefinity is configured for multiple languages as described in the Localization
section of this courseware, you can programmatically translate pages and content. The key
is to change the UICulture property of the page before modifying PageData properties.
The example below changes the UICulture to "ES", gets an instance of the page titled
"Home" and changes the Title to "Casa".
protected void LocalizePageButtonClick(object sender, EventArgs e){ PageManager manager = PageManager.GetManager(); this.UICulture = "ES"; var page = manager.GetPageDataList() .ToList() .Where(p => p.Title == "Home") .Where(p => !p.IsBackend) .Single();
page.Title = "Casa"; manager.SaveChanges();}
After running this code and navigating back to Pages, the "ES" edit button is now enabled
and when "espanol" is selected from the languages drop down, the translated text "Casa"
shows up.
Figure 303 --Localized Title
Localization 363
© 2012 Falafel Software
Localizable Strings
The Title and other localizable Sitefinity properties aren't strings but actually Lstring
properties. Lstring is a localizable string that is sensitive to the current culture. In most
cases you treat an Lstring like a standard string, and as long as you have the UICulture set,
Sitefinity will place your string assignments into the storage for the proper culture.
Sitefinity 5364
© 2012 Falafel Software
Localizing Back End Pages
Localizing back end pages is similar to localizing front-end pages, using the same
mechanism from the Administration Settings > Languages to add languages. Click the
Manage backend languages link to see the Add languages... button. Click Add languages...
to display the Select languages dialog. Select one or more languages from the list and click
the Done button. Finally, click the Save changes button on the Languages page.
Figure 304 --Adding Languages to the Backend
After clicking the Close languages for the backend system link, a drop down will allow you
to choose the language for the backend system. Select a new language from the drop
down list, then click the Save changes button.
Figure 305 --Choosing the Backend Language
There is no immediate change where you see the menu language change. You need to load
translated Interface Labels & Messages to see the effect.
Localization 365
© 2012 Falafel Software
Interface Labels & Messages
The Administration > Interface Labels & Messages menu item displays a page that lists all the
labels, captions and other text in the system that can be localized. These labels populate all
text in the system including the Administration menu text, widget text and even the
column headings in grid widgets. Each label can be edited to define the Invariant language
(the default language) and for each language you have configured from the Administration
> Settings > Languages. You can import "Language Packs" of these labels in .xlsx
spreadsheet format. Sample language packs can be downloaded from the Sitefinity
marketplace online.
Figure 306 --Interface Labels & Messages page.
Refresh the page to see all the resourced items in the system display in the corresponding
language.
Figure 307 --Resourced Labels
Sitefinity 5366
© 2012 Falafel Software
Click on an item in the list to edit the "Invariant" (default) language, and for each language
you have defined.
Figure 308 --Saving a Translated Label
Localization 367
© 2012 Falafel Software
Summary
In this chapter you learned how to localize front end pages using Sitefinity Administration,
how to localize strings in code, how to localize back end pages and how to use the
Interface Labels & Messages page.
19Working with Widgets
Working with Widgets 369
© 2012 Falafel Software
19 Working with Widgets
You can create widgets for your Sitefinity website by writing a user control or a custom
control. A user control is easier to build using Visual Studio support but does not allow
Sitefinity design time support and is not designed to be deployed across multiple web
sites. A custom control is slightly more difficult to build, but does allow design time
support and can be deployed as a single .dll across multiple web sites.
Sitefinity 5370
© 2012 Falafel Software
Objectives
This chapter steps you through how to create user and custom controls available from the
toolbox and usable within the page. You will also learn how to create designers for custom
controls to assist your users in configuring the control. You will use a RadControls
"RadComboBox" and "RadGrid" inside your page as well as perform CRUD operations
against live data. You will see how to integrate a Silverlight control and how to make the
Silverlight control and page communicate. Finally, you will create a custom form control.
Working with Widgets 371
© 2012 Falafel Software
User Controls
User controls are an easy way to encapsulate some set of controls and HTML layout in a
single named control. User controls can be stuffed with standard ASP.NET controls,
RadControls for ASP.NET or any other third party controls. The following shows how to
build a control right in the Visual Studio designer, dragging and dropping controls from
the Toolbox to create whatever layout you want and adding your own code-behind if
necessary.
Within your user control, you have a complete user interface. This is pure ASP.NET
development where you can connect to databases: OpenAccess, MS SQL, Oracle or any
other database you have a driver for. You can also use web services to get data from the
"outside world" such as SalesForce or some other CRM product.
Once the control is created, you register the control and it becomes a "first class citizen" in
Sitefinity that can be used like any other widget and dropped into any Sitefinity content
placeholder.
Sitefinity 5372
© 2012 Falafel Software
Create a User Control
In this set of steps you create a user control that is a "bread sandwich". It really doesn't do
anything meaningful yet
1) From the Visual Studio Solution Explorer, right-click the Sitefinity project and select
Add > New Item.
2) In the Add New Item dialog, select Web > Web User Control.
3) Name the control "MyControl.ascx" and click the Add button. This will create the .ascx
file and the associated code behind file.
Figure 309 --Adding the User Control
Working with Widgets 373
© 2012 Falafel Software
4) Drag a Label control from the Toolbox to either the Design or Source view of the
MyControl.ascx control.
Figure 310 --Designing the User Control
5) Using the Properties pane, change the Label properties to the following:
ID: "MyLabel"
Text = "Hello Sitefinity!"
6) Build the project.
Register a User Control
For the user control to be recognized in Sitefinity and visible in the Sitefinity toolbox, you
will need to register the control. You should create one or more Toolbox sections that will
contain your control, then add your new widget your Toolbox section.
Sitefinity 5374
© 2012 Falafel Software
Create a Toolbox Section
A toolbox section is used to organize widgets and could be named for your organization e.
g. "My Company Widgets" or for some category you choose e.g. "List Widgets", "New
related widgets", etc.
1) From the Sitefinity menu, select Administration > Settings.
2) Click the Advanced link to see all the possible settings.
3) Select the Toolboxes > Toolboxes > PageControls > Sections option.
4) Click the Create new button. This will create a new Toolbox section.
5) Enter the following:
Name: "MyControls". You can use this internal name later to access this section of
widgets.
Title: "My Controls". This text will be displayed in the user interface.
Description: "These are my controls". This describes the section in the toolbox.
ResourceClassId: leave this blank. You can use this later if you want to include an
image, font or other resource for this specific section.
Working with Widgets 375
© 2012 Falafel Software
6) Click the Save changes button.
Figure 311 --Defining a Toolbox Section
Sitefinity 5376
© 2012 Falafel Software
Add a Widget to the Toolbox
1) In Settings, navigate to the tools for your new section at Toolboxes > Toolboxes >
PageControls > Sections > MyControls > Tools. There shouldn't be any tools listed there
yet.
2) Click the Create new button.
Figure 312 --Creating a New Toolbox Item
3) Some of the fields on this page are specific to custom controls or controls within
modules and can be left alone. Enter the following and leave the remaining fields blank:
Control CLR Type or Virtual Path: "~/MyControl.ascx". In the case of a User
Control, this is a virtual path to the control in the project. The leading tilde "~"
indicates a path relative to the root of the website.
Name: "MyControl"
Title: "My Control"
Description: "My Control Description"
Working with Widgets 377
© 2012 Falafel Software
4) Click the Save changes button.
Figure 313 --Adding the Toolbox Item
Sitefinity 5378
© 2012 Falafel Software
Notes
All the information for configuring the widget ends up in a configuration
file \App_Data\Sitefinity\Configuration\ToolboxesConfig.config.
. . . <add enabled="True" title="My Controls" description="These are my controls" resourceClassId="" name="MyControls"> <tools> <add enabled="True" type="~/MyControl.ascx" title="My Control" description="My Control Description" resourceClassId="" cssClass="" layoutTemplate="" moduleName="" name="MyControl" /> </tools> </add> </sections> </toolbox> </toolboxes></toolboxesConfig>
Only ASP.NET specific configuration is found in the Web.Config file, all other
Sitefinity specific configuration has been moved into separate, purpose specific,
XML files in \App_Data\Sitefinity\Configuration.
Working with Widgets 379
© 2012 Falafel Software
Test the New Widget
1) From the Sitefinity menu, select Pages.
2) Open an existing page or create a new page to work with.
3) Scroll to the bottom of the list of widgets and find your new section and widget:
4) Drag the widget to a content area on the page. The widget should display the message.
Figure 314 --Adding the Widget to the Page
5) Notice that the Toolbox shows the title of the section as "My Controls" and the title of
the control as "My Control". The actual content of the label displays in the widget itself
when dropped on the page.
Gotcha!
If a message pops up "Type 'MyControl.ascx' cannot be resolved", go back to the
Toolbox configuration and change the Control CLR Type or Virtual Path entry. If the
control is in the root directory of the project, the correct path will be "~/MyControl.
ascx". Production sites typically have controls grouped in a subdirectory, e.g. "/
MyControls", in which case Control CLR Type or Virtual Path will be "~/MyControls/
MyControl.ascx". Also, be sure to build the project so that the type is available when
Sitefinity goes looking for it.
Sitefinity 5380
© 2012 Falafel Software
Adding Code Behind
The widget shows up in the toolbox, can be dragged into the page, but so far has no real
functionality. The next step is to add a property to the widget that can be set when
designing the Sitefinity page.
1) In the Visual Studio Solution Explorer, open the MyControl.ascx.cs file for editing.
2) Add a new string property named "MyProperty". Decorate the property with the
Category attribute, passing the category name "My Properties".
[Category("My Properties")]public string MyProperty { get; set; }
3) In the Page_Load event handler, assign "MyProperty" to the Text property of the Label.
protected void Page_Load(object sender, EventArgs e){ this.MyLabel.Text = this.MyProperty; }
4) Build the project.
5) Open the Sitefinity dashboard and navigate to the test page for your widget. You can
either use an existing page or create a new page for this.
6) If "MyControl" isn't already on the page, drag it onto the page from the widgets listed to
the right of the design area.
7) Click the Edit link found on the upper right of the control.
Figure 315 --Editing the Control Properties
8) Click the Categorized button.
Figure 316 --Categorizing
Properties
Working with Widgets 381
© 2012 Falafel Software
9) Notice the "My Properties" category has appeared with "MyProperty" underneath it.
Enter some text into MyProperty and click the Save button.
Figure 317 --Saving the Properties
10)The control now displays the text in the label.
Figure 318 --The Property Value Reflected in the Control
Sitefinity 5382
© 2012 Falafel Software
Custom Controls
While Custom Controls are somewhat more difficult to build, they are more powerful and
easier to deploy than User Controls. This is the recommended method for building
production controls in Sitefinity websites.
The Game Plan
The steps to building a Custom Control are:
1) Create a Class Library Project.
2) Add a Layout Template (ascx file) to the class library.
3) Create a Custom Control that consumes the Layout Template, declares properties and
initializes the control according to the property values.
4) Register the Custom Control in the Sitefinity administrator.
5) Test the Custom Control.
Create the Class Library Project
1) From the Visual Studio Solution Explorer, right-click the solution and select Add > New
Project from the context menu.
2) In the Add New Project dialog, select the Class Library project type and make sure that
"NET Framework 4" is selected in the drop down at the top of the form. Enter project
properties:
Name: "MyOrganization.MyControls".
Notes
As a convention, projects are often named akin to a namespace, in roughly the
form shown below:
<Organization name>.<Functional category>.<specific control>
Location: Leave the default.
Working with Widgets 383
© 2012 Falafel Software
3) Click the OK button to create the project.
Figure 319 --Creating the Project
4) In the Solutions Explorer, right-click the References node, select Add Reference, locate
and select "System.Web" and click the OK button to add the references and close the
Add Reference dialog. Also add a reference to "Telerik.Sitefinity" by using the Browse tab
of the Add Reference dialog, then locating the assembly in the Sitefinity install directory
under \_EmptyProject\bin.
Sitefinity 5384
© 2012 Falafel Software
Add a Layout Template
1) To the Solution Explorer, right-click the SitefinityWebApp and select Add > New Item...
from the context menu.
Select Web > Web User Control.
Name the file "MyLayoutTemplate.ascx".
Figure 320 --Defining the Layout Template
2) Also, in the Solution Explorer, cut the "MyLayoutTemplate.ascx" from the
SitefinityWebApp project. Paste the file to the MyOrganization.MyControls project. Tip:
You can also drag the file, while holding to the Shift key to move the file from one
project to another. The solution should now look something like the screenshot below.
Figure 321 --The Template in the Project
3) In the Solution Explorer, right-click the "MyLayoutTemplate.ascx" and select Properties
from the context menu. Set the Build Action property to Embedded Resource.
Working with Widgets 385
© 2012 Falafel Software
Gotcha!
You may see an error "Unable to find resource..." if you forget this step.
4) In the Solution Explorer, double-click the "MyLayoutTemplate.ascx" file to open it for
editing.
5) Drag a Label from the Toolbox to the end of the aspx markup.
Figure 322 --Adding a Label to the Layout Template
Sitefinity 5386
© 2012 Falafel Software
Create the Custom Control
Now that the class library is created you can add your custom control class to it.
1) In the Solution Explorer, right-click the default "class1.cs", select Rename from the
context menu and set the name to "MyCustomControl.cs".
2) A dialog will display asking if you want to rename the underlying class. Select OK.
Figure 323 --Allowing the Rename
3) Add the "public" keyword and inherit the class from SimpleView.
SimpleView has the basic functionality needed for any web control that has child
controls and adds the Sitefinity-specific properties for handling templates and
resources.
public class MyCustomControl: SimpleView {}
4) Right-click SimpleView and select Implement Abstract Class from the context menu.
Working with Widgets 387
© 2012 Falafel Software
5) Implement the LayoutTemplateName property.
This should return the name of the project followed by the path to the layout template
file. In this case, "MyCustomView.ascx" is in the root of the "MyOrganization.
MyControls" project. SimpleView automatically reads the LayoutTemplateName
property each time the widget is refreshed, e.g. just after editing any properties of the
widget.
protected override string LayoutTemplateName{ get { return "MyOrganization.MyControls.MyLayoutTemplate.ascx"; }}
6) Override the InitializeControls() method using the code below.
This example gets a reference to the "Label1" control in the "MyCustomView.ascx"
layout template. Label1's Text property is set to the value of MyCustomProperty - we
will define MyCustomProperty in the next step of this walk-through.
InitializeControls() runs right after the assignment of the LayoutTemplateName and
allows you to access any controls in the layout template and initialize them.
protected override void InitializeControls(GenericContainer container){ Label label = container.GetControl<Label>("Label1", true); label.Text = this.MyCustomProperty; }
Sitefinity 5388
© 2012 Falafel Software
Tip!
If you don't have a reference in the "using" (C#) or "Imports" (VB) to support a
particular class, then class names may be underlined in red to flag the error. The
easy way to fix this is to place your cursor on the class name. Notice the small
blue underline and move your mouse over this area. From the drop down menu
that appears, select the "using" option to automatically add the reference.
Working with Widgets 389
© 2012 Falafel Software
7) Add a property with a category to the custom control class.
[Category("My Category")]public string MyCustomProperty { get; set; }
Q & A...
Question: I want to hide the EnableViewState property so that the designer does
not need to see it. Can I hide an existing property?
Answer : Yes, you can override any of the properties coming from
CompositeControl and decorate these properties with the Browsable() attribute,
passing false as the parameter. The example below hides the EnableViewState
from view when editing the custom control.
[Browsable(false)]public override bool EnableViewState{ get { return base.EnableViewState; } set { base.EnableViewState = value; }}
Sitefinity 5390
© 2012 Falafel Software
8) Build the project.
9) Add the reference to your class library to the Sitefinity project.
Right-click the SitefinityWebApp project and select Add Reference... from the context
menu.
In the Add Reference dialog that appears, select the Projects tab.
Select your class library from the list and click the OK button.
The class library should now show in the list of referenced assemblies:
Figure 324 --Referencing the Class Library
Working with Widgets 391
© 2012 Falafel Software
Register the Custom Control
1) From the Sitefinity menu, select Administration > Settings.
2) Click the Advanced link to see all the possible settings.
3) Select the Toolboxes > Toolboxes > PageControls > Sections option.
4) You can use the existing "MyControls" section created in the previous walk-through
User Controls > Register a User Control > Create a Toolbox Section, or create a new
section.
5) Navigate to the Tools node of the section and click the Create new button.
Figure 325 --Creating a new Tool Item
6) Enter the following settings:
Control CLR Type or Virtual Path: "MyOrganization.MyControls.MyCustomControl,
MyOrganization.MyControls". The basic naming scheme is:
<full name of class>,<name of the dll>
The full name of the class includes the entire namespace of the class. A comma
follows the full class name. Next comes the name of the dll (without the dll
extension). Another example if the namespace of the class is "InterSlice.
VisualControls", the class name is "Spinner" and the dll is "InterSliceControls.dll",
then CLR Type should be:
InterSlice.VisualControls.Spinner,InterSliceControls
Sitefinity 5392
© 2012 Falafel Software
Name: "MyCustomControl"
Title: "My Custom Control"
Description: "My Custom Control Description"
Figure 326 --Defining the Tool Item
7) Click the Save changes button.
Working with Widgets 393
© 2012 Falafel Software
Test the Custom Control
1) From the Sitefinity menu, select Pages.
2) Open an existing page or create a new page to work with.
3) Scroll to the bottom of the list of widgets and find the section that you added your
custom control to and the custom control itself:
4) Drag the widget to a content area on the page.
5) Click the Edit link. Notice that there are more properties found in the SimpleView and
that "MyCustomProperty" is also included in the list.
6) Enter some text to MyCustomProperty and then click the Save button.
Figure 327 --Custom Control Displayed
Sitefinity 5394
© 2012 Falafel Software
Custom Control Designers
By default, the Advanced designer for a custom control is a simple dump of every
property picked up using reflection. This presents unwanted properties that can confuse
non-programmers or allow property changes that can actually cause a widget to perform
incorrectly.
Figure 328 --Advanced Designer
Working with Widgets 395
© 2012 Falafel Software
If you want a designer that is suitable for non-programmers to use, you will need to build
a designer for the control and make it available to Sitefinity. The following walk-through
leads you through creating a simple designer for the custom control created in the
previous section of this Courseware. In the example, your designer will have styles and an
image stored in a resource file and an HTML input control used to collect a value from the
user for storage in "MyProperty" and display in the custom control. The walk-through will
use the custom control created in the previous section Custom Controls.
Figure 329 --Designer for Custom Control
Sitefinity 5396
© 2012 Falafel Software
The Game Plan
Creating a designer for a custom control involves a number of files that must all work
together. You can only test the designer when all these pieces are in place. None of the
individual steps are too complicated, but all of the pieces must be correct for the designer
to display properly. Much of the code, particularly the JavaScript, is "boiler-plate" code
that you can reuse for other projects. But first you need to get it working that one time. Be
encouraged that all the code and screenshots are taken from a functioning example, so go
slow, make sure of your spelling (including case sensitivity) and copy & paste where you
can.
The walk-through that follows builds off the previous Custom Controls section of this
Courseware.
The steps to building a custom control designer are:
1) Prepare resource files to be used by the designer
Images
Style sheet
Designer JavaScript
2) Code the Designer
3) Register the Designer
4) Test the Designer
Working with Widgets 397
© 2012 Falafel Software
Preparing Resources
Everything used by the custom control and designer needs to be wrapped up in a dll -- no
stand-alone files allowed. CSS files, JavaScript and Images all need to be stored and
accessed as resources. The general steps to creating resource required by the designer are:
1) Create a \Resource directory in your class library project. The particular directory
name is optional, but Telerik recommends this approach and we will follow the
convention in this example.
2) Set the Build Action property of your resource file to "Embedded Resource". Resources
not marked in this way will not end up in your dll and therefore can't be found. This is
a key step that will cause a lot of fruitless debugging time if you forget. Get in the habit
of setting the Build Action property first thing after adding it to the \Resource directory.
3) Make the resources available to requests. This is done various ways depending on
where the resource is used.
Register resources in AssemblyInfo.cs to expose resources to web requests. This is
done by adding WebRequest attributes for each resource and is used for images
referenced in the style sheet.
Using the special Sitefinity ResourceFile tag in markup to include the resourced
stylesheet so it can be used right in an ascx. The designer ascx will use the ResourceFile
attribute to include the stylesheet resource so that the styles can be referenced directly
in the ascx markup.
JavaScript and ascx resource files will be referenced directly in the designer class code.
Prepare Images
1) In the Solution Explorer, add a new folder to the MyOrganization.MyControls project
and name it "Resources".
2) From the Windows Explorer, drag an image to the \Resources folder. You can borrow a
copy of the "Logo.png" image from the "CarConduit" theme.
3) Set the image file's Build Action property to "Embedded Resource".
Gotcha!
Forgetting this step can eat up a lot of development time. Get in the habit of setting
the Build Action right away after you add any resource.
Sitefinity 5398
© 2012 Falafel Software
4) Open the \Properties.AssemblyInfo.cs for the class library.
Figure 330 --Opening AssemblyInfo.cs
5) Scroll to the bottom of the file and add the WebResource attribute as shown in the
example below. The first parameter is the path to the image resource and the second is
the MIME type.
[assembly: WebResource("MyOrganization.MyControls.Resources.logo.png", "image/png")]
Your image resource is now prepared and ready to be accessed from a style sheet.
Working with Widgets 399
© 2012 Falafel Software
Prepare the Stylesheet
1) Right-click the \Resources folder and select Add > New Item...
2) Select the Web > Style Sheet item type. Name it "Default.css" and click the Add button.
3) Set the file's Build Action property to "Embedded Resource".
4) Replace the content of the style sheet with the styles below. Notice that the background-
image style uses a WebResource tag to set the url for the image.
body{}
.BackgroundStyle{ background-color: White; background-image:url(<% = WebResource("MyOrganization.MyControls.Resources.logo.png") %>); background-position: center center; background-repeat: no-repeat; height: 150px;}
.TitleStyle{ font-size:large; color:Gray; padding:10px; }
.MessageStyle{ float: right; margin: 10px; position: relative; top: 65px; }
Sitefinity 5400
© 2012 Falafel Software
Prepare Designer JavaScript
The JavaScript resource created in this step gets loaded later in the designer class code.
This code creates a client-side representation of the designer and allows interaction
between the designer and the custom control.
1) Right-click the \Resources folder and select Add > New Item...
2) Select the Web > Jscript item type. Name it "MyDesigner.js" and click the Add button.
3) Set the Jscript file Build Action property to "Embedded Resource".
4) Copy the JavaScript below into the MyDesigner.js file. The code here will register a
namespace, create a client-side instance of the designer class and register the designer
class with ASP.NET.
// register the namespaceType.registerNamespace("MyOrganization.MyControls");
// create an instance of the designer classMyOrganization.MyControls.MyDesigner = function (element) { MyOrganization.MyControls.MyDesigner.initializeBase(this, [element]);}
// add designer logic here -->
// register the designer classMyOrganization.MyControls.MyDesigner.registerClass('MyOrganization.MyControls.MyDesigner', Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesignerBase);
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
5) Replace the comment "add designer logic here" with the JavaScript below.
// add logic to the designer classMyOrganization.MyControls.MyDesigner.prototype = { initialize: function () { MyOrganization.MyControls.MyDesigner.callBaseMethod(this, 'initialize'); }, dispose: function () { MyOrganization.MyControls.MyDesigner.callBaseMethod(this, 'dispose'); }, // loads the current control settings // jQuery interacts with DOM, "#MessageText" is the id of a DOM element refreshUI: function () { var data = this._propertyEditor.get_control(); jQuery("#MessageText").val(data.MyCustomProperty); }, // called when user clicks save button applyChanges: function () { var controlData = this._propertyEditor.get_control(); controlData.MyCustomProperty = jQuery("#MessageText").val(); }}
Working with Widgets 401
© 2012 Falafel Software
This code has two sets of methods. The initialize() and dispose() methods create and
discard the designer instance when the custom control's edit dialog appears and closes.
This is "boiler-plate" code that just needs to be there and have the correct client-side
namespace for the designer.
The refreshUI() method loads the current settings for the custom control into properties of
the designer. The call to get_control() retrieves the custom control instance and can be
used to reference the custom control's properties. The "#MessageText" refers to a text
input where the ID is "MessageText". JQuery puts all of this together by first digging into
the DOM and getting the MessageText element instance, then the JQuery val() method
sets a value for MessageText from the custom control's property.
The applyChanges() method gets called when the user clicks the save button and does
essentially the reverse of the refreshUI method. In this case, the value of the MessageText
input control is assigned back to the custom control's property.
In this example we're keeping it simple with just a single property, but typically, both
methods will have a list of assignments, one for each property.
Sitefinity 5402
© 2012 Falafel Software
Create the Designer ascx
To create a visual layout for the custom control designer, you will need to create an ascx
file resource.
1) Create an ascx file to represent the designer user interface. The problem is that you can't
right-click the Resources folder and directly add an ascx for the Class Library project
type. The trick is to create the ascx in the Sitefinity web site project, then move it over to
the Resources folder.
In the Solution Explorer, right-click the Sitefinity web site project
Select Add > New Item... from the context menu.
Select the Web > Web User Control item type. Name the web user control
"MyDesigner.ascx" and click the Add button.
Figure 331 --Adding the ascx File
2) Drag the MyDesigner.ascx file from the SitefinityWebApp to the class library
"MyOrganization.MyControls\Resources" folder. Hold the Shift key down while you
drag to move the file instead of copying.
3) Set the ascx file's Build Action property to "Embedded Resource".
4) Open the MyDesigner.ascx to edit the markup.
Working with Widgets 403
© 2012 Falafel Software
5) At the bottom of the file, register the Telerik.Sitefinity assembly.
<%@ Register Assembly="Telerik.Sitefinity" Namespace="Telerik.Sitefinity.Web.UI" TagPrefix="sitefinity" %>
6) Below the assembly registry, add the ResourceLinks tag below. The ResourceLinks
control automatically loads resources and the ResourceFile represents a single resource
in the ResourceLinks collection. The ResourceFile Name attribute points to the path of
the resource file in the project. The AssemblyInfo points to the full name of the type
that contains the resource. Adding the Static attribute and setting it true indicates that
the resource is either an external or embedded resource (i.e. not part of a Telerik
theme).
<sitefinity:ResourceLinks runat="server"> <sitefinity:ResourceFile Name="MyOrganization.MyControls.Resources.Default.css" AssemblyInfo="MyOrganization.MyControls.MyCustomControl, MyOrganization.MyControls" Static="true" /></sitefinity:ResourceLinks>
7) Below the ResourceLinks tag, add the following markup. The markup sets up a basic
layout that uses the styles from the Default.css style sheet resource file and also includes
an HTML Input element that will collect data from the user.
<div class="BackgroundStyle"> <div class="TitleStyle"> CarConduit Designer</div> <input id="MessageText" type="text" class="MessageStyle" /></div>
That completes the designer layout so that it can be referenced from the designer class.
Sitefinity 5404
© 2012 Falafel Software
Code the Designer Class
The designer class pulls all the pieces you have prepared into a cohesive whole.
1) Right-click the class library project References and add System.Web.Extensions from
the .NET tab.
2) Right-click the class library project and select Add > Class... from the context menu.
Name the class "MyDesigner.cs" and click the Add button.
3) Add System.Web.UI and Telerik.Sitefinity.Web.UI.ControlDesign namespaces to
your "using" (C#) or "Imports" (VB).
4) Inherit your class from ControlDesignerBase.
public class MyDesigner: ControlDesignerBase{ }
5) Right-click the ControlDesignerBase class and select Implement Abstract Class from the
context menu. The code should now look like the example below:
public class MyDesigner: ControlDesignerBase{ protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container) { throw new System.NotImplementedException(); }
protected override string LayoutTemplateName { get { throw new System.NotImplementedException(); } }}
6) Replace the InitializeControls() method with the code below. This method determines
what the user sees in the dialog when they click the custom control's Edit link. You can
assign the ControlDesignerModes Simple, Advanced or Both. In this example, we will
only show our "Simple" designer instead of the default "Advanced" designer.
protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container){ base.DesignerMode = ControlDesignerModes.Simple; }
Working with Widgets 405
© 2012 Falafel Software
7) Replace the LayoutTemplateName property with the code below. When the designer
needs the layout template, the MyDesigner.ascx markup will be used.
protected override string LayoutTemplateName{ get { return "MyOrganization.MyControls.Resources.MyDesigner.ascx"; }}
8) Add an override for the TagKey property. This just specifies that we want a div
wrapper tag around the layout template to make common styling easier.
protected override HtmlTextWriterTag TagKey{ get { return HtmlTextWriterTag.Div; }}
9) Add an override for the GetScriptReferences() method. This code pulls the
MyDesigner.js file out of the resource and makes it available to the designer.
public override IEnumerable<ScriptReference> GetScriptReferences(){ var res = new List<ScriptReference>(base.GetScriptReferences()); var assemblyName = this.GetType().Assembly.GetName().ToString(); res.Add(new ScriptReference("MyOrganization.MyControls.Resources.MyDesigner.js", assemblyName)); return res.ToArray(); }
That completes the designer class so that the class can be registered as the designer for the
custom control.
Register the Designer
In the custom control itself, add the ControlDesigner attribute above the class
declaration. This initializes a designer instance for use with this custom control.
[Telerik.Sitefinity.Web.UI.ControlDesign.ControlDesigner(typeof(MyDesigner))]public class MyCustomControl : SimpleView
Sitefinity 5406
© 2012 Falafel Software
Test the Designer
1) Build the solution in Visual Studio.
2) In the Sitefinity administration, navigate to the test page you used in for Custom
Controls section of this courseware.
3) Click the Edit link of the custom control. If the steps up to this point are performed
correctly, you should see the Simple designer. Styling should place the text
"CarConduit Designer" in the upper left corner, using a large gray font. The image
should be centered in a white background. The text input should appear in the lower
right area.
4) The first time you see this text input, it may have the text "NULL" -- you will need to
write safety code in the JavaScript refreshUI() method to fix this. For now, just enter
some text into the text input and click the Save button.
Figure 332 --The Working Designer
5) When the designer dialog closes, the custom control should display the value entered in
the designer.
Figure 333 --Designer Value Displayed in Control
Working with Widgets 407
© 2012 Falafel Software
Troubleshooting
Here are a few things to check if the designer is not displaying for your control:
1) Are all resources marked with a Build Action of "Embedded Resource"?
2) If the image doesn't show, does the AssemblyInfo.cs WebResource() attribute point to
the correct image file name and path? Is the extension of the image and the MIME type
correct and matching?
3) In the MyDesigner.js code:
· Do the method names have the proper case sensitive names?
· If you copy and paste the code from the example (recommended), did you get all of
the code? Did you pick up any other characters that weren't part of the code?
· Does the namespace and class names throughout the JavaScript file agree?
4) Is the ControlDesigner attribute applied to the correct class? Make sure the attribute is
sitting on top of the SimpleView class.
5) In the designer class check:
· Does the control descend from ControlDesignerBase?
· In the InitializeControls() method, is the DesignerMode assigned Simple or Both? If
you're assigning Advanced, you will only see the default, Advanced designer.
· In the LayoutTemplateName property, is the path to the ascx control correct?
· In override of the GetScriptReferences() control, is the path to the JavaScript file
resource correct?
6) In the Default.css file, if the image is not showing, verify that the WebResource()
assignment to the background-image css selector uses the correct path.
7) Did you build the solution?
Sitefinity 5408
© 2012 Falafel Software
Using RadControls for ASP.NET AJAX with Sitefinity
RadControls can be used in both User Controls and Custom Controls. ASP.NET AJAX
support is included automatically by Sitefinity. From the Page properties you can optimize
the support with the following options:
Enable the Include RadScriptManager option to use a RadScriptManager instead of the
standard ScriptManager. This can increase efficiency by combining scripts, causing
fewer trips to the server.
Select the Enable ViewState option when the page needs to remember the state of a
control between refreshes. For example, if a combo box needs to retain the selected item
after the user clicks something from the list.
Prepare the Project
Setup the page to enable ViewState for controls that retain state between postbacks and to
include the RadScriptManager for better efficiency.
1) Create and register a user control as described in the User Controls section of this
courseware.
2) In the Sitefinity administration menu, click the Pages link.
3) In the Actions drop down for the page containing the user control, select the Titles &
Properties option. This will display the Edit a page dialog.
4) In the Edit a page dialog, select the checkboxes for Enable ViewState and Include
RadScriptManager.
Figure 334 --Enabling ViewState and
RadScriptManager
Working with Widgets 409
© 2012 Falafel Software
Display a Collection Using RadComboBox
The following walk-through demonstrates binding Roles to a RadComboBox.
1) In Visual Studio, drag a RadComboBox from the toolbox to the user control markup.
Set the AutoPostBack property to "true". The markup at this point should look
something like the example below.
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl.ascx.cs" Inherits="SitefinityWebApp.MyControl" %>
<telerik:RadComboBox ID="RolesCombo" runat="server" AutoPostBack="true" Label="Roles "></telerik:RadComboBox>
2) Add the code below to the user control code-behind in the Page_Load method. This will
populate the RadComboBox with all the built-in role names and their Guid Id's.
protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { RoleManager manager = RoleManager.GetManager(SecurityManager.ApplicationRolesProviderName); RolesCombo.DataTextField = "Name"; RolesCombo.DataValueField = "Id"; RolesCombo.DataSource = manager .GetRoles() .ToList(); RolesCombo.DataBind(); }}
3) Build the solution.
4) Test the control in a Sitefinity page.
Figure 335 --Displaying Roles in
RadComboBox
Sitefinity 5410
© 2012 Falafel Software
Silverlight Controls
Silverlight controls are designed to be hosted in ASP.NET applications and so can be
hosted by controls for your Sitefinity web application just as easily. You can host your
Silverlight control in a User Control or Custom Control. The example that follows uses a
simple Silverlight Button control. For a more complex scenario that builds on this walk-
through, see the Communication between Custom Control and Silverlight example that
displays Sitefinity information in a RadBook control.
The Game Plan
The steps to building a control that hosts a Silverlight control:
1) Follow the steps in the previous topic to create a Custom Control.
2) Create a Silverlight Control.
3) Integrate the Silverlight Control with the User Control.
4) Test the Widget.
Working with Widgets 411
© 2012 Falafel Software
Create a Silverlight Control
Creating a Silverlight control starts with creating a Silverlight application in the same
solution as the Sitefinity web site and then adding code to the Sitefinity web site that loads
the Silverlight user control into the ASP.NET custom control.
1) In the Solution Explorer, right-click the solution and select Add > New Project... from the
context menu.
2) In the Add New Project dialog, select Silverlight > Silverlight Application. Name the
application "MySilverlightApplication" and click the OK button.
Figure 336 --Creating a New Silverlight Application
Sitefinity 5412
© 2012 Falafel Software
3) In the New Silverlight Application dialog that displays, leave the Host the Silverlight
application... checkbox selected and the drop down should have the "SitefinityWebApp"
already selected. In the Options section of the dialog, unselect the Add a test page that
references the application checkbox. Click the OK button to create the Silverlight
application and close the dialog.
Figure 337 --Hosting the Silverlight Application in the Sitefinity Web Site
Instead of creating a new web site to host the Silverlight control, the Sitefinity web site
will now host the control.
Working with Widgets 413
© 2012 Falafel Software
4) In the "MainPage.xaml" editor, drag a Silverlight Button control from the Toolbox.
Figure 338 --Adding the Button
5) Add a Content attribute to the Button and set the value to "Click Me!".
6) Add a Click attribute to the Button. When you enter the equal "=" sign, IntelliSense will
prompt for "<New Event Handler>". Select the "<New Event Handler>" option to create
the event handler.
Figure 339 --Creating the New Event Handler
7) Right click the new Click attribute and select Navigate to Event Handler from the
context menu.
Figure 340 --Navigating to the Event Handler
Sitefinity 5414
© 2012 Falafel Software
8) In the button Click event handler add the code below to display a simple message box.
private void Button_Click(object sender, RoutedEventArgs e){ MessageBox.Show("Clicked!"); }
9) Save and build the solution. Open the \SitefinityWebApp\ClientBin directory. Notice
that the compiled Silverlight application is placed in a .xap file and included in the
SitefinityWebApp directory:
Figure 341 --The Compiled Silverlight Application
At this point you have a very simple Silverlight control hosted by the Silverlight
application.
Working with Widgets 415
© 2012 Falafel Software
Integrate the Silverlight Control with User Control
While you can reference the Silverlight application from the Sitefinity application at this
point, the Sitefinity page doesn't yet know to load the Silverlight control. The following
steps add JavaScript and HTML to the Custom Control that load the Silverlight plug-in
and startup your Silverlight application.
1) In the "MyOrganization.MyControls" custom control project, open the
"MyLayoutTemplate.ascx" file to edit the markup. At the end of the file, paste the
"boiler plate" JavaScript code below. This code will handle any errors that might occur
when loading Silverlight.
<script type="text/javascript"> function onSilverlightError(sender, args) { var appSource = ""; if (sender != null && sender != 0) { appSource = sender.getHost().Source; }
var errorType = args.ErrorType; var iErrorCode = args.ErrorCode;
if (errorType == "ImageError" || errorType == "MediaError") { return; }
var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n";
errMsg += "Code: " + iErrorCode + " \n"; errMsg += "Category: " + errorType + " \n"; errMsg += "Message: " + args.ErrorMessage + " \n";
if (errorType == "ParserError") { errMsg += "File: " + args.xamlFile + " \n"; errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } else if (errorType == "RuntimeError") { if (args.lineNumber != 0) { errMsg += "Line: " + args.lineNumber + " \n"; errMsg += "Position: " + args.charPosition + " \n"; } errMsg += "MethodName: " + args.methodName + " \n"; }
throw new Error(errMsg); }</script>
2) Below that, add the markup below. This contains the Silverlight plug-in object. In
particular, notice the "<param>" attribute with the name "source". This key parameter
points to your Silverlight application.
Sitefinity 5416
© 2012 Falafel Software
<div id="silverlightControlHost" style="height: 400px; width: 100%"> <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"> <param name="source" value='<%= ResolveUrl("~/ClientBin/MySilverlightApplication.xap") %>' /> <param name="onError" value="onSilverlightError" /> <param name="background" value="white" /> <param name="windowless" value="true" /> <param name="minRuntimeVersion" value="4.0.50401.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0" style="text-decoration: none"> <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style: none" /> </a> </object></div>
3) Locate the tag starting with "<param name='source'. Verify that the "value" part of the
tag so that the ResolveUrl() path matches the path to the .xap file for your Silverlight
application. In the example, the Silverlight application is named
"MySilverlightApplication", so the parameter should be:
<param name="source" value='<%= ResolveUrl("~/ClientBin/MySilverlightApplication.xap") %>' />
4) Build the solution.
Working with Widgets 417
© 2012 Falafel Software
Test the Widget
1) From the Sitefinity menu, select Pages.
2) Open an existing page or create a new page to work with.
3) Scroll to the bottom of the list of widgets and find your new section and widget:
4) Drag the widget to a content area on the page. The widget should display the Silverlight
user control that contains the button. The width and height properties on the button
have not been set, so the button takes up the entire Silverlight control area. The "Hello
Sitefinity!" message in the label at the top of the user control is from the original
Custom Controls topic and is not a Silverlight control.
Figure 342 --The Hosted Silverlight Control
5) Click the Preview button to display the page. Click the Silverlight, "Click Me!" button.
The Silverlight MessageBox.Show() method fires and displays a dialog above the
button.
Figure 343 --Testing the Event
Sitefinity 5418
© 2012 Falafel Software
Communication between Custom Control and Silverlight
"So far so good" in that we have a Silverlight control functioning inside a custom control.
It would be cool if we could get the Silverlight controls to talk with the custom control.
This conversation can happen by using a JavaScriptSerializer object. JavaScriptSerializer
can convert to and from JSON (JavaScript Object Notation). JavaScriptSerializer can be
used from both the ASP.NET code-behind of the custom control and in the JavaScript of
the ascx layout template.
In practice, the custom control code-behind can query the Sitefinity using the Standard
API or Fluent API. The results are serialized into JSON and stored in a hidden field. Every
time properties are changed for the widget, the Silverlight plug-in is reloaded and a
JavaScript event fires. During the event, JavaScript code reads the JSON data. When
Silverlight application methods are tagged with a [ScriptableMember] attribute, methods
can be called directly from JavaScript. This means that as the JSON data is read in,
Silverlight methods can be called, passing along the Sitefinity data. The relationship is
roughly:
Sitefinity API <-> Custom Control <-> ASCX Template <-> Silverlight Application
The New Game Plan
The example that follows creates a custom control that hosts a Silverlight control. The
Silverlight control display images using an interface that appears as a "book", complete
with turning pages, courtesy of the RadBook Silverlight control.
Figure 344 --Custom Control With RadBook
Working with Widgets 419
© 2012 Falafel Software
We will follow the path starting from the custom control all the way out to the Silverlight
application to update our solution:
Custom Control -> ASCX Template -> Silverlight Application
The steps that need to be added to our solution to populate Silverlight controls using
Sitefinity data are:
1) Modify the SimpleView custom control.
Add the [RequireScriptManager] attribute to the class that enables
JavaScriptSerializer functionality in the ascx JavaScript code.
Add a method to extract Sitefinity images from an album and place them in a
serialization-friendly Hashtable.
Override the InitializeControls() method to receive the extracted images, serialize
them and place them in a hidden field. The hidden field will be located in the Layout
Template ascx.
2) Modify the Layout Template ascx markup.
Add a hidden field tag.
Add a JavaScript method that reacts when the Silverlight plug-in is loaded. This
method gets the data out of the hidden field left by the custom control, de-serializes
the data and calls a method in the Silverlight control.
Add a parameter to the Silverlight plug-in that calls the JavaScript method when the
plug-in loaded.
3) Modify the Silverlight application.
Add a simple class used for storing data and binding.
Add a "scriptable" method to the Silverlight application that accepts an instance of the
data class.
Add XAML markup to define the Silverlight user interface.
Sitefinity 5420
© 2012 Falafel Software
Modify the Custom Control
1) In the Solution Explorer, right-click the References node and add references to Telerik.
Sitefinity.Model, Telerik.OpenAccess and System.Runtime.Serialization. The two
Telerik assemblies can be found under the Sitefinity installation directory. System.
Runtime.Serialization can be found in the .NET tab of the Add Reference dialog.
2) In your "using" statement (C#) or "Imports" (VB), make sure you are referencing the
following namespaces:
using System;using System.Collections;using System.Collections.Generic;using System.ComponentModel;using System.Web;using System.Web.Script.Serialization;using System.Web.UI.WebControls;using Telerik.Sitefinity;using Telerik.Sitefinity.GenericContent.Model;using Telerik.Sitefinity.Web.UI;
3) In the MyCustomCode.cs code-behind, add the RequireScriptManager attribute to the
custom control class.
[Telerik.Sitefinity.Modules.Pages.Web.UI.RequireScriptManager]public class MyCustomControl : SimpleView
4) Add the method below to extract images from an album.
private List<Hashtable> GetImages(){ List<Hashtable> results = new List<Hashtable>();
//get IQueryable of images from the Fluent API. var images = App.WorkWith().Images() .Where(i => i.Parent.Title == this.MyCustomProperty && i.Status == ContentLifecycleStatus.Live) .Get();
// get the base url string authorityUrl = this.Page.Request.Url.GetLeftPart(UriPartial.Authority); string authority = VirtualPathUtility.RemoveTrailingSlash(authorityUrl);
// Add each full url and title to the hash tab le foreach (Telerik.Sitefinity.Libraries.Model.Image v in images) { Hashtable table = new Hashtable(); table.Add("Url", authority + v.MediaUrl); table.Add("Title", v.Title.ToString()); results.Add(table); }
return results;}
Working with Widgets 421
© 2012 Falafel Software
5) Override the InitializeControls() method to receive and serialize the list of images.
Replace the code from the previous example with the code below.
The GetControl() method returns an instance of a HiddenField in the Template Layout
ascx. GetImages() returns a Hashtable of image data that is serialized into a JSON string
and assigned to the HiddenField Value.
protected override void InitializeControls(GenericContainer container){ HiddenField imagesField = container.GetControl<HiddenField>("imagesField", true); imagesField.Value = new JavaScriptSerializer().Serialize(GetImages()); ;}
Modify the Layout Template
1) In the Layout Template ascx (i.e. "MyLayoutTemplate.ascx"), replace the Label with a
HiddenField tag with an ID of "imagesField" so we can reference it later.
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MyLayoutTemplate.ascx.cs" Inherits="SitefinityWebApp.MyLayoutTemplate" %>
<%--Add HiddenField tag here--%><asp:HiddenField ID="imagesField" runat="server" />
<script type="text/javascript">. . .
2) Add a new JavaScript method that will react when the Silverlight plug-in is loaded.
The method retrieves the HiddenField data and re-hydrates it as an array of objects. For
each element in the array, a method in the Silverlight application called SetItem() is
called. SetItem() will be coded in an upcoming step.
function pluginLoaded(sender, args) { slCtl = sender.getHost(); var imagesField = $get('<%= imagesField.ClientID %>'); if (imagesField != null) { var imagesArr = Sys.Serialization.JavaScriptSerializer.deserialize(imagesField.value);
for (idx in imagesArr) { slCtl.Content.mainPage.SetItem(imagesArr[idx]['Title'], imagesArr[idx]['Url']); } }}
3) Add a parameter to the object tag for the Silverlight plug-in. The parameter specifies
what JavaScript method should be called when the plug-in loads. This parameter points
back up to the pluginLoaded() JavaScript method.
<object . . .> <param name="onLoad" value="pluginLoaded" />
Sitefinity 5422
© 2012 Falafel Software
Modify the Silverlight Application
1) Edit the App.xaml file of the Silverlight application. Replace the Startup event handler
with the code below.
This makes the main Silverlight page reachable through JavaScript code in the Layout
Template ascx file.
private void Application_Startup(object sender, StartupEventArgs e){ var mainPage = new MainPage(); this.RootVisual = mainPage;
HtmlPage.RegisterScriptableObject("mainPage", mainPage);}
2) Add a class file to the Silverlight project for storing Sitefinity image data:
public class SitefinityImage{ public string Url { get; set; } public string Title { get; set; }}
3) Add references to the Silverlight project for Telerik.Windows.Controls and Telerik.
Windows.Controls.Navigation assemblies.
Working with Widgets 423
© 2012 Falafel Software
4) Add XAML markup below to define the Silverlight user interface. First add a Resources
section to define the DataTemplate that paints each page of the RadBook. This markup
should be placed just below the Grid "LayoutRoot".
The "PageTemplate" has a light gradient border, an Image bound to a field named "Url"
and a TextBlock bound to a field named "Title".
<Grid.Resources> <DataTemplate x:Key="PageTemplate"> <Border BorderThickness="1" BorderBrush="LightGray"> <Border BorderThickness="5" Margin="10" Padding="5"> <Border.BorderBrush> <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5"> <GradientStop Color="#4B917835" Offset="0" /> <GradientStop Color="#77958787" Offset="1" /> <GradientStop Color="#2D8F8F8F" Offset="0.32" /> </LinearGradientBrush> </Border.BorderBrush> <StackPanel Margin="10">
<Image Width="200" Height="200" Source="{Binding Url}" Stretch="Uniform" />
<TextBlock Text="{Binding Title}" />
</StackPanel> </Border> </Border> </DataTemplate>
</Grid.Resources>
Sitefinity 5424
© 2012 Falafel Software
5) Add the XAML for the RadBook. Replace the Button control from the earlier example.
<telerik:RadBook x:Name="book" FoldSize="250,250" LeftPageTemplate="{StaticResource PageTemplate}" RightPageTemplate="{StaticResource PageTemplate}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" RightPageIndex="1" FontFamily="Comic Sans MS" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"></telerik:RadBook>
6) Add a "Scriptable" method to the Silverlight control code behind that can be fired from
JavaScript and executed on the Silverlight control.
The ScriptableMember attribute marks this method so that it can be called from
JavaScript. The method creates a new SitefinityImage data object, populates it with the
title and url passed in and adds it to the RadBook items.
[ScriptableMember]public void SetItem(string title, string url){ this.book.Items.Add( new SitefinityImage() { Title = title, Url = url });}
Working with Widgets 425
© 2012 Falafel Software
Test the Widget
1) Rebuild the application.
2) Run the application and navigate to your test page.
3) Click the Edit button of the widget. Enter the name of an Album that has images
loaded. You can use either the Custom Control Designer created in a previous lesson or
use the Advanced properties to enter a new value for MyCustomProperty. When the
Edit dialog closes, the widget will be reinitialized
Figure 345 --Setting MyCustomProperty
Sitefinity 5426
© 2012 Falafel Software
4) The Silverlight RadBook shows up in the Widget, complete with data that originated
from the Sitefinity API.
Figure 346 --RadBook in Sitefinity Widget
Working with Widgets 427
© 2012 Falafel Software
Custom Form Controls
The Form Builder comes out-of-the-box with form control widgets that appear on the
right-hand side of the Form Builder screen. While these basic widgets are functional, you
may need to store other information such as dates or use special purposes controls like
RadCaptcha.
Fortunately, Sitefinity makes it possible to create custom controls that show up in the
Form Builder and write data to the database. So for example, you could have an event
registration form that takes a name and email address. Forms can be submitted from
either the front-end (on a published page on the site) or from the back-end (from inside
the Dashboard in the Forms module).
This walk-through demonstrates creating a simple form custom control. The control is
automatically populated with the name of the currently logged-in user. This name can be
changed in the Textbox before submitting the form.
The Game Plan
Creating a custom form control involves the following steps:
1. Preparing a class library that will hold the ascx template, JavaScript file and a class file to
rule them all.
2. Populating a Control Template ascx file with the elements that will display in the form
control widget.
3. Populating the Client Script File so that Sitefinity will be able to write to the database
from the back-end user interface.
4. Populating the Class file is the largest chunk of code in the project and involves Building
a Class Skeleton, Implementing FieldControlProperties, Implementing the
InitializeControls() method and Adding FieldControl Script Properties.
5. Registering the Control.
6. Testing the Control.
Sitefinity 5428
© 2012 Falafel Software
Setting Up the Custom Control Project
To set up the project that contains the form custom control:
1. From the Sitefinity Project Manager, select the project to contain the new control and
click the Edit in Visual Studio button.
2. Add a new class library project and name it “CustomFormControls”.
3. Add a new class “NamedTextBox.cs”. This class will define the control’s behaviour.
4. Add a "Resources" folder to the "CustomFormControls" project.
5. Add a new template “NamedTextBox.ascx” to the Resources folder. The ascx file will
define the control template, setting the look and feel. Be aware that class library projects
don't allow adding new ascx files directly. Instead, add a new ascx file project item to
the "SitefinityWebApp" project and move it to the \Resources folder of the
"CustomFormControls" project.
6. In the Solution Explorer, right-click the "NamedTextBox.ascx" entry and select
Properties from the context menu. In the Properties pane, set the Build Action property
to "Embedded Resource".
7. Add a new Jscript file "NamedTextBox.js" in the Resources folder. This will define the
control’s client-side implementation. Set the Build Action to "Embedded Resource".
8. Your solution should now have two projects and look something like the screenshot
below.
Figure 347 --Custom Form Controls Project
Working with Widgets 429
© 2012 Falafel Software
9. Add all references highlighted in the screenshot below. These references will be needed
to create a custom form control.
Figure 348 --Adding References
10.Open the \Properties\AssemblyInfo.cs file for editing. Add a reference to the resource
JavaScript file to the end of the file.
[assembly: WebResourceAttribute("CustomFormControls.Resources.NamedTextBox.js", "text/javascript")]
11.While you're there, add a "using" reference to System.Web.UI in the AssemblyInfo.cs
file.
12.In the Sitefinity web application project, add a reference to the class library project
"CustomFormControls".
Populating the Control Template
1) Edit the NamedTextBox.ascx file.
· In the "CustomFormControls" project, open the \Resources\NamedTextBox.ascx file
for editing.
· Add the Telerik.Web.UI assembly to provide access to the RadControls. Add this line
to the bottom of the file.
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
Sitefinity 5430
© 2012 Falafel Software
· Add markup for Label and RadTextBox controls. Notice the CssClass attribute that
matches the Sitefinity styles.
<asp:Label runat="server" ID="Label1" CssClass="sfTxtLbl" Text="title label" /><telerik:RadTextBox ID="TextBox1" CssClass="sfTxt" runat="server" /><br /><asp:Label runat="server" ID="Label2" CssClass="sfExample" Text="example Label" /><br /><asp:Label runat="server" ID="Label3" CssClass="sfExample" Text="description Label" />
For reference, here is the entire NamedTextBox.ascx file:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="NamedTextBox.ascx.cs" Inherits="SitefinityWebApp.NamedTextBox" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<asp:Label runat="server" ID="titleLabel" CssClass="sfTxtLbl" Text="title label"></asp:Label>
<telerik:RadTextBox ID="TextBox1" CssClass="sfTxt" runat="server"></telerik:RadTextBox>
<br /><asp:Label runat="server" ID="exampleLabel" CssClass="sfExample" Text="example Label"></asp:Label><br /><asp:Label runat="server" ID="descriptionLabel" CssClass="sfExample" Text="description Label"></asp:Label>
Populating the Client Script File
JavaScript is required to save form control data to the database. Without JavaScript, users
can save control data from the front-end, but not from the back-end. The JavaScript code
below creates a client-side representation of the form control that Sitefinity can reference
and provides access to any elements in the control (such as the RadTextBox, in this
example).
1) As an absolute minimum to get the control to work, add the JavaScript below. The
JavaScript registers the control’s namespace/class and allows the control to be rendered
in the browser.
// register the client-side namespaceType.registerNamespace("CustomFormControls");
// Create the NamedTextBox client-side controlCustomFormControls.NamedTextBox = function (element) { // add control references here -->
Working with Widgets 431
© 2012 Falafel Software
CustomFormControls.NamedTextBox.initializeBase(this, [element]);}
// set control properties here -->
// register the control in the namespaceCustomFormControls.NamedTextBox.registerClass('CustomFormControls.NamedTextBox',Telerik.Sitefinity.Web.UI.Fields.FieldControl);
2) To provide access to the RadTextBox, replace the comment "add control references here
-->" with the code below. This code adds getter and setter method that support
RadTextBox client-side properties.
//set control propertiesCustomFormControls.NamedTextBox.prototype = { get_value: function () { return this._textbox.get_value(); }, set_value: function (value) { this._textbox.set_value(value); }, get_textbox: function () { return this._textbox; }, set_textbox: function (value) { this._textbox = value; }}
Populating the Class File
The class file pulls together all of the other pieces, including the JavaScript file and the ascx
template file. This is the largest set of code to complete and involves the following steps:
1. Building the Class Skeleton.
2. Implementing FieldControl Properties.
3. Implementing the InitializeControls() Method.
4. Adding the FieldControl Script Properties.
Sitefinity 5432
© 2012 Falafel Software
Building the Class Skeleton
1) Open the "NamedTextBox.cs" class file for editing.
2) To save time, add the following references to your "using" (C#) or "Imports" (VB)
statements:
System.Collections.Generic;System.ComponentModel;System.Web.UI;System.Web.UI.WebControls;Telerik.Sitefinity.Data.Metadata;Telerik.Sitefinity.Metadata.Model;Telerik.Sitefinity.Model;Telerik.Sitefinity.Modules.Forms.Web.UI.Fields;Telerik.Sitefinity.Security;Telerik.Sitefinity.Web.UI.Fields;Telerik.Sitefinity.Web.UI.Fields.Enums;Telerik.Web.UI;
3) Inherit from FieldControl, right-click "FieldControl" and select Implement Abstract
Class from the context menu. This step will create stub methods for the abstract class.
Figure 349 --Implementing FieldControl
4) Add IFormFieldControl to the declaration, right-click "IFormFieldControl" and select
Implement Interface > Implement Interface from the context menu.
Figure 350 --Implementing IFormFieldControl
Working with Widgets 433
© 2012 Falafel Software
Implement FieldControl Properties
1) Implement the DescriptionControl, ExampleControl and TitleControl properties.
· Add properties that retrieve the controls from the ascx file.
protected internal virtual Label TitleLabel{ get { return this.Container.GetControl<Label>("titleLabel", true); }}
protected internal virtual Label DescriptionLabel{ get { return Container.GetControl<Label>("descriptionLabel", true); }}protected internal virtual Label ExampleLabel{ get { return this.Container.GetControl<Label>("exampleLabel", this.DisplayMode == FieldDisplayMode.Write); }}
· Add DescriptionControl, ExampleControl and TitleControl properties below.
protected override System.Web.UI.WebControls.WebControl DescriptionControl{ get { return this.DescriptionLabel; }}
protected override System.Web.UI.WebControls.WebControl ExampleControl{ get { return this.ExampleLabel; }}
protected override System.Web.UI.WebControls.WebControl TitleControl{ get { return this.TitleLabel; }}
2) Add public properties to support Example, Title and Description in the property
editor.
public override string Example { get; set; }public override string Title { get; set; }public override string Description { get; set; }
3) Add support for the Value of the NamedTextBox form control.
· Add a property that retrieves the RadTextBox control from the ascx.
Sitefinity 5434
© 2012 Falafel Software
protected internal virtual RadTextBox TextBox1{ get { return this.Container.GetControl<RadTextBox>("TextBox1", true); }}
· Add a Value property to get and set using the RadTextBox Text property as storage.
public override object Value{ get { return this.TextBox1.Text; } set { this.TextBox1.Text = value.ToString(); }}
4) Replace the LayoutTemplateName property with the code below. The property should
return the path that points to the ascx file.
protected override string LayoutTemplateName{ get { return "CustomFormControls.Resources.NamedTextBox.ascx"; }}
Implement InitializeControls
1) Replace the InitializeControls implementation with the code below. This method fires
whenever the form displays or when the Edit dialog returns with changed values . The
controls in the form control widget for Example, Title and Description are fed from the
corresponding public properties. The RadTextBox is initialized from the
SecurityManager.GetCurrentUserName() method.
protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container){ this.ExampleLabel.Text = this.Example; this.TitleLabel.Text = this.Title; this.DescriptionLabel.Text = this.Description;
this.TextBox1.Text = SecurityManager.GetCurrentUserName();}
Working with Widgets 435
© 2012 Falafel Software
Add FieldControl Script Properties
1) Add the FieldControl methods overrides below to get client-side script references.
The first method, GetScriptDescriptors(), allows the front-end control to pass values
for back-end publishing. Descriptors are added for the client-side RadTextBox and the
DisplayMode property (determines if the mode is in Read or Write mode).
The second method, GetScriptReferences(), tells the control which script files it needs
to have access to in order to function correctly. A script reference is added to our
custom "NamedTextBox.js" stored in the Resources directory and to the Telerik
"FieldDisplayMode.js".
public override IEnumerable<ScriptDescriptor> GetScriptDescriptors(){ var descriptor = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID); descriptor.AddComponentProperty("textbox", this.TextBox1.ClientID); descriptor.AddProperty("displayMode", this.DisplayMode); return new[] { descriptor };}
public override IEnumerable<System.Web.UI.ScriptReference> GetScriptReferences(){ var scripts = new List<ScriptReference>(base.GetScriptReferences()) { new ScriptReference( "CustomFormControls.Resources.NamedTextBox.js", this.GetType().Assembly.FullName), new ScriptReference( "Telerik.Sitefinity.Web.UI.Fields.Scripts.FieldDisplayMode.js", "Telerik.Sitefinity"), }; return scripts;}
Sitefinity 5436
© 2012 Falafel Software
Register the Control
Now for the fun part where we add it to the Form Builder and see it in action.
1) First off, build the solution and then run the Sitefinity project.
2) Inside Sitefinity administration, add configuration settings for the new control.
· From the Administration menu select Settings > Advanced > Toolboxes > Toolboxes >
FormControls > Sections > Common > Tools
· Click the Create New button.
3) Enter the configuration settings for the form control.
· For the Control CLR Type or Virtual Path enter the assembly name followed by the
control type. In this example the Control CLR Type or Virtual Path is
CustomFormControls.NamedTextBox.
· Name = "NamedTextBox.
· Title = "Named TextBox".
Figure 351 --Configuring the Form Control
4) Build the solution.
Working with Widgets 437
© 2012 Falafel Software
Test the Control
1) Create a new form (Content > Forms > Create a form).
2) You should now see the custom form control at the bottom of the list of standard, out-
of-the-box controls.
3) Drag the new form control widget onto the form. Notice how the logged-in user’s name
gets added automatically to the Named TextBox control.
Figure 352 --Adding the New Form Control Widget
4) Click the Edit button and fill in a value for the "Title" property. This will become the
title above your control, as well as the column name that your control’s data will save to
in the database.
5) Put the form on a page to view the custom control. Press the Submit button to submit
the form and save the text box value.
Sitefinity 5438
© 2012 Falafel Software
6) View the form response you just created. In the Sitefinity administration, go to Content
> Forms and click on the "Responses" link for the form you're testing.
Figure 353 --Viewing Responses
7) Now you should see the value you submitted in the textbox. Notice also that the title for
the textbox value column is “Logged-In User”. You've now successfully saved form data
through the front-end.
8) Now to save form data through the back-end. On the same "Responses" screen you're
currently on, click the Create a Response button on the top-right of the page. This will
show you the same form as above, but using the Sitefinity administration instead of the
published site. Click the Submit button to save the form's data. You've now successfully
saved form data through the back-end.
Working with Widgets 439
© 2012 Falafel Software
Summary
This chapter stepped through how to create user and custom controls available from the
toolbox and usable within the page. You learned how to create designers for custom
controls to assist your users in configuring the control. You used RadControls
"RadComboBox" and "RadGrid" inside your page. You saw how to integrate a Silverlight
control and how to make the Silverlight control and page communicate. Finally, you
created a custom form control.
20Working with Modules
Working with Modules 441
© 2012 Falafel Software
20 Working with Modules
Sitefinity has numerous content modules right out of the box, e.g. "News", "Blogs",
"Events", etc. The built in types cover many standard scenarios, but your organization may
need to store custom data, for example "Press Releases", "Stock Quotes" or "Employee
Bio". You will need an administration back-end page to enter new data and a widget to
display the data in various formats in your pages. Modules allow you to extend Sitefinity
with custom content administration pages and front end page widgets.
Sitefinity 5442
© 2012 Falafel Software
Objectives
In this chapter you will work with modules to handle custom data. You will learn how to
create a custom module, add content to the module and add the module widget to a page
to view the data. You will also learn how to customize the backend table of module data.
Working with Modules 443
© 2012 Falafel Software
Create a Custom Module
The steps to create a custom module are:
Create a Custom Module
Add Module Content
Add the Module to a Page
In this example we will create a new module that lists quotations from famous people.
Each entry will have a "Quote", the "Source" author and a "Picture" of the author.
1. From the Sitefinity main menu select Administration > Module Builder.
2. Click the Create a Module link.
Figure 354 --Creating a Module
3. Enter a Name and Description for the module as a whole and click the Continue button.
Figure 355 --Naming the Module
Sitefinity 5444
© 2012 Falafel Software
4. In the Define a content type page that shows next, enter the singular name of the Content
type. In this example we're working with Quotations, so we enter "Quotation". The
Content type entry will automatically fill in the Developer name of this content type. You
can alter the developer name, but be sure to remove any spaces.
Figure 356 --Developer Names
Working with Modules 445
© 2012 Falafel Software
5. Below the Content type is an area for adding a list of fields used to store the content. By
default, the standard content Title is already in the list, but can be removed. Click the
Add a field... button. Enter the Name of the field (again without spaces). From the drop
down list, select the Type of data this field represents. Leave the Interface widget for
entering data at its default. Click the Continue button to finish defining the field.
Figure 357 --Adding a Field
Sitefinity 5446
© 2012 Falafel Software
Notes
There are at least two interface widgets listed for each type, the built-in editor for the
type and a Custom... option where you're expected to enter the virtual path to a
custom .ascx widget. If you want to prevent entry you can select the This is a hidden
field checkbox. The hidden field can be accessed programmatically but not through
the interface widget.
Working with Modules 447
© 2012 Falafel Software
6. To finish the field definition, provide a Label that will be shown in the widget and the
Instructional text that will be shown as a prompt. Select the This is a required field
checkbox to force entry in this field.
Figure 358 --Entering Label and Instructional Text
Sitefinity 5448
© 2012 Falafel Software
7. Click the Limitations link to place constraints on entry. You can set a simple Min and
Max number of characters that can be entered or define a Regular expression to exactly
define what kind of entry is allowed. Click the Done button to finish creating the field.
Figure 359 --Setting Field Limitations
8. Once all the fields are defined, select the field that will be used as the identifier of the
content from the drop down list. The drop down list will only show Short Text fields that
are marked as Required.
Figure 360 --Setting the Identifier
9. Click the Finish button to create the module. The module will now appear in three
locations in Sitefinity:
Administration > Module Builder: Use this option to add or change fields, edit the name
and description, make changes to the backend screens and to activate/deactivate the
module.
Content > [your module name]: Use this option to add, update and delete data for your
module, and to publish/unpublish rows of data.
Working with Modules 449
© 2012 Falafel Software
The Drag widgets list will include an icon that represents your module data. Drag the
widget to the page to present the new data.
Sitefinity 5450
© 2012 Falafel Software
Add Module Content
1. From the Content menu select your new content item. This example shows a new
"Quotations" menu item for module of the same name.
Figure 361 --Selecting the Module
2. The first time you enter the screen you will see a "Create a [my module type] item".
Click the link to create a new item.
Figure 362 --Creating a Module Item
Working with Modules 451
© 2012 Falafel Software
3. Enter the fields you defined when creating the module. When complete, click the
Publish button.
Figure 363 --Entering the Content Fields
4. After adding several entries, you can see the quotations column and stock columns
"Author" and "Publication Date" that come along with all content.
Figure 364 --Table of Module Data
Sitefinity 5452
© 2012 Falafel Software
Customizing the Backend Grid
The stock backend grid shows only the identifying field and built-in content fields
"Publication Date" and "Author". You can customize the backend grid to show the
columns from your module.
1. To customize this list to include the quotation source and picture, select the menu
Administration > Module Builder.
2. Select the link for your module.
3. Select the Backend screens tweaks link.
4. Click the Add / Remove columns in the table button.
Figure 365 --Editing the Table
Working with Modules 453
© 2012 Falafel Software
5. The "Author" column can be removed, so click the "x" icon to delete it.
Figure 366 --Removing the Author Column
6. Drag the columns from your module to the right end of the grid and drop them there.
Figure 367 --Adding a Custom Field
Sitefinity 5454
© 2012 Falafel Software
7. The table should now look something like the screenshot below. Click the Save Changes
button.
Figure 368 --The Table Layout
8. From the menu select Content > [your module]. The grid now shows the other columns
defined in your module.
Figure 369 --The Customized Backend Table
Working with Modules 455
© 2012 Falafel Software
Add the Module to a Page
1. Drag the widget for your new module onto the page.
Figure 370 --Adding the Quotations Widget
2. The module will be listed using the default configuration and layout. The example
below shows all published quotations in a list and the layout for each item shows the
picture, quote and published date.
Figure 371 --The Quotations Widget on the Page
Sitefinity 5456
© 2012 Falafel Software
3. The layout should be changed to show the quote source author instead of the published
date. Click the Quotations widget Edit button.
Figure 372 --Editing the Widget
4. Click the List Settings link.
5. In the List template drop down, select "List of quotations"
Figure 373 --Selecting the Template
6. Click the Edit selected template button.
7. In the Edit template screen, locate the line that starts '<sf:FieldListView
ID="PublicationDate"' and remove the entire line.
Figure 374 --Editing the Template
8. Leave the cursor just after the </h2> tag.
9. In the list to the right of the template, expand the Insert > Other data heading.
Working with Modules 457
© 2012 Falafel Software
10.Click the "Source" item. The How to insert... dialog should display.
Figure 375 --Inserting the Source Field
11.Click the Insert button.
12.The template should now look something like the screenshot below, with the TextField
for "Source" inserted right after the </h2> tag holding the quotation.
The Edited Template
13.Click the Save changes button of the Edit template page..
14.Click the Save button on the Edit dialog.
15.The page will update in a moment and display the source author under the quotation.
Figure 376 --The Templated Widget
Sitefinity 5458
© 2012 Falafel Software
Working with the Module in Code
You can build custom code against your new module starting from automatically
generated examples. Access the code sample snippets from the Code reference for [my
module] link found in the Module Builder.
Figure 377 --Showing Code Samples
The list on the left has starting points for all the critical areas you're likely to need: create,
delete, find by id, get a collection, filter, check in/out and integration with ASP.NET.
Select from the list to display the custom code on the right.
Figure 378 --Showing a Code Snippet
Working with Modules 459
© 2012 Falafel Software
The examples include a short explanation of the steps in the code and a list of the
namespaces to include that make the code work. Here's the code that creates a quotation:
// Creates a new quotation item public void CreateQuotation() { DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(); Type quotationType = TypeResolutionService.ResolveType( "Telerik.Sitefinity.DynamicTypes.Model.Quotations.Quotation"); DynamicContent quotationItem = dynamicModuleManager.CreateDataItem(quotationType); // This is how values for the properties are set quotationItem.SetValue("Quotation", "Some Quotation"); quotationItem.SetValue("Owner", SecurityManager.GetCurrentUserId()); quotationItem.SetValue("PublicationDate", DateTime.Now); quotationItem.SetValue("Source", "Some Source"); LibrariesManager libraryManager = LibrariesManager.GetManager(); var image = libraryManager.GetImages().FirstOrDefault(); if(image != null) { quotationItem.AddImage("Picture", image.Id); } // You need to call SaveChanges() in order for the items to be actually persisted to data store dynamicModuleManager.SaveChanges(); }
Sitefinity 5460
© 2012 Falafel Software
We can tweak this code a bit to bring in a particular image from the library and to publish
the module data so that its visible on a page. This example filters the images to look for a
"live" version of an image titled "winston". At the end of the method, the item is saved.
public void CreateQuotation(){ DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(); Type quotationType = TypeResolutionService.ResolveType( "Telerik.Sitefinity.DynamicTypes.Model.Quotations.Quotation"); DynamicContent quotationItem = dynamicModuleManager.CreateDataItem(quotationType);
// This is how values for the properties are set quotationItem.SetValue("Quotation", "Some Quotation"); quotationItem.SetValue("Owner", SecurityManager.GetCurrentUserId()); quotationItem.SetValue("PublicationDate", DateTime.Now); quotationItem.SetValue("Source", "Some Source"); LibrariesManager libraryManager = LibrariesManager.GetManager(); var image1 = libraryManager.GetImages() .Where(i => i.Title.Equals("winston")) .Where(i => i.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live) .FirstOrDefault();
if (image1 != null) { quotationItem.AddImage("Picture", image1.Id); }
dynamicModuleManager.Lifecycle.Publish(quotationItem); dynamicModuleManager.SaveChanges();}
Using this code as a basis, you can publish a series of quotes for a single author. Winston
Churchill authored more than his fair share of good quotes:
public void CreateQuotation(){ string[] quotations = { "Ending a sentence with a preposition is something up with which I shall not put.", "An appeaser is one who feeds a crocodile—hoping it will eat him last.", "If you are going to go through hell, keep going.", "History will be kind to me for I intend to write it.", "It has been said that democracy is the worst form of government except all the
Working with Modules 461
© 2012 Falafel Software
others that have been tried." };
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(); Type quotationType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Quotations.Quotation");
LibrariesManager libraryManager = LibrariesManager.GetManager(); var image = libraryManager.GetImages() .Where(i => i.Title.Equals("winston")) .Where(i => i.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live) .FirstOrDefault();
foreach (string quote in quotations) { DynamicContent quotationItem = dynamicModuleManager.CreateDataItem(quotationType);
quotationItem.SetValue("Quotation", quote); quotationItem.SetValue("Owner", SecurityManager.GetCurrentUserId()); quotationItem.SetValue("PublicationDate", DateTime.Now); quotationItem.SetValue("Source", "Winston Churchill");
if (image != null) { quotationItem.AddImage("Picture", image.Id); } dynamicModuleManager.SaveChanges(); }}
The quotations are added en-masse to the page.
Figure 379 --Programmatically Added Module Items
Sitefinity 5462
© 2012 Falafel Software
Summary
In this chapter you worked with modules to handle custom data. You learned how to
create a custom module, add content to the module and add the module widget to a page
to view the data. You also learned how to customize the backend table of module data.
21Sitefinity Web Services
Sitefinity 5464
© 2012 Falafel Software
21 Sitefinity Web Services
If you need your web site to "Talk to the outside world", then Sitefinity web services are
the tool you're looking for. Web services can be used for any platform clients that can send
and receive web traffic including iPhone, iPad, Winforms, Android and Windows Phone.
Sitefinity web services closely parallel the Sitefinity user interface and cover the major
areas of the product. Sitefinity web services are particularly suited to automating
administrative tasks from remote locations.
Sitefinity Web Services 465
© 2012 Falafel Software
Objectives
This chapter demonstrates how to work with both Forms Authentication and, the new
default, Claims Authentication. This chapter first shows how to get all the available web
services and method calls. You will learn the basic steps in common with all web service
method calls, how to log in and log out of Sitefinity from a web service and how to
retrieve and parse information from a web service call.
Sitefinity 5466
© 2012 Falafel Software
Getting Available Services and Methods
If you know the names of available services, you can query the service itself for the
methods that it supports. To view the available methods for a service, the browser path is:
http://localhost:<port>/<project name>/sitefinity/Services/<service folder>/<service>.svc/help
So for example, the methods for dealing with Pages for the project "WebServicesDemo" at
port 17968 can be viewed in the browser at this address:
http://localhost:17968/WebServicesDemo/sitefinity/Services/Pages/PagesService.svc/help
How do you find out the name of the web services? The best place to view the available
services is right from the project in Visual Studio.
1) From the Sitefinity Project Manager, note the base URL for the project. This particular
example is located on the local host, port 17968 where the project name is
"WebServicesDemo". The website you use will likely have a different URL.
Figure 380 --The Project URL
2) Click the Edit in Visual Studio button for any project.
3) In the Visual Studio Solution Explorer, expand the Sitefinity/Services node. There are
folders for each area that web services provides for.
Figure 381 --Webservices in Visual
Studio Project
Sitefinity Web Services 467
© 2012 Falafel Software
4) Expand the Security folder. Inside are "svc" files representing services for
MembershipSettings, Permissions, Roles and Users.
Figure 382 --Security Services
5) Add the path to the Pages service in the browser. Use the base url you noted from the
Sitefinity Project Manager earlier and tack on "/sitefinity/Services/Pages/PagesService.svc/
help".
http://localhost:17968/Quotations/sitefinity/Services/Pages/PagesService.svc/help
6) The browser will display a list of methods. Under each method, a table of text and links
explains what each method can do and basic information on how that can be
accomplished.
Figure 383 --Web Service Help
Sitefinity 5468
© 2012 Falafel Software
7) Scroll down to the GetPagesAsTree method and take a moment to explore the table and
the links.
UriTemplate defines how the request url should be formatted. UriTemplate may have
optional parameters surrounded in curly braces. The template tells us that the method
to pass in the uri is "tree".
Method is the HTTP method used to make the request. For example, a GET is used
when the entire request is contained in the URL. A POST is used when additional data
needs to be sent in the request stream. PUT is used to update a record with a
particular ID. DELETE is used to remove a record with a particular ID. The method for
the GetPagesAsTree is a POST.
Request Format and Response Format can be either XML or JSON (JavaScript Object
Notation). We will be working with JSON in upcoming examples. The
GetPagesAsTree method can make a request in JSON format, while a second method
GetPagesAsTreeInXml returns the equivalent XML document.
Request Schema and Response Schema describe the data layout of the data being
sent or received.
Request Example and Response Example show sample JSON or XML data.
8) Click the GetPagesAsTree Response Example to display an unformatted JSON string.
Figure 384 --Unformatted JSON String
Sitefinity Web Services 469
© 2012 Falafel Software
Using a formatter, the JSON looks like the snippet below.
{ "Context":[ { "Key":"String content", "Value":"String content" } ], "IsGeneric":true, "Items":[ { "AdditionalUrlsRedirectToDefaultOne":true, "AllowMultipleUrls":true, "AllowParameterValidation":true, "AvailableLanguages":[ "String content" ], "FullUrl":"String content", "HasChildren":true, . . .
Sitefinity 5470
© 2012 Falafel Software
Anatomy of a Web Service Call
Whatever the platform, you can perform these basic steps to make a web service call and
get the results:
1) Make a web request, passing the URL of the service method you want to call.
· Set the request method (e.g. "Post", "Get", etc.).
· Add the claims token to the request header.
· Optionally set the request content type.
· Add any POST or PUT data as a stream of bytes to the request.
2) Get the response.
· Read the response stream and consume the results.
Sitefinity Web Services 471
© 2012 Falafel Software
Using Claims Authentication
The following is a minimal representation of working with Claims Authentication. There is
clearly more to do in a production environment to check inputs, keep track of statuses
and react to exceptions. The example will demonstrate logging in and getting a token,
calling the GetPages REST api, passing the token and logging out.
Logging in
Logging in using Claims Authentication is a two stage process: finding out where the
security token service is and then actually authenticating through the service.
Finding the Security Token Service
The first step is to make a simple GET request to the Authenticate service. The request url
is the base url of your application, e.g. "http://localhost:12345/MySite" followed by "/
Sitefinity/Authenticate". The request will return a response status "200 - OK" if the issuer
or Security Token Service (STS) is on the same machine. If the status is "301 - Moved",
then we're dealing with an external STS or a Single Sign On. This example only
implements local authorization.
public void Login(){ // initial request to determine if security token service is on the same machine HttpWebRequest initialRequest = (HttpWebRequest)WebRequest.Create(_baseUrl + "/Sitefinity/Authenticate"); initialRequest.Method = "get";
using (HttpWebResponse initialResponse = initialRequest.GetResponse() as HttpWebResponse) { // "OK" indicates the security token service is on the same machine // "302", i.e. "Moved" indicates that the site is using an external // security token service or a single sign on. In this case you would have get the // token from the location parameter in the response headers. if (initialResponse.StatusCode == HttpStatusCode.OK) { LocalServiceAuth(); } else if (initialResponse.StatusCode == HttpStatusCode.Moved) { // not implemented in this example } }}
Sitefinity 5472
© 2012 Falafel Software
Authenticating With Security Token Service
Send out a second, POST request that includes "wrap_name" and "wrap_password" key/
value pairs passed in the request stream. If the user name or password is incorrect, the
response status code will be "401 - Unauthorized". If the status code is "OK", parse the
response and extract the token from the wrap_access_token key. You can use the
HttpUtility class (from the System.Web assembly and namespace) to convert the response
text into a NameValueCollection for easier handling.
private void LocalServiceAuth(){ // make a new request, passing the user name and password in the request stream HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_baseUrl + "/Sitefinity/Authenticate"); request.Method = "post"; request.ContentType = "application/x-www-form-urlencoded"; byte[] data = Encoding.UTF8.GetBytes("wrap_name=" + _name + "&wrap_password=" + _password); request.ContentLength = data.Length; using (var writer = request.GetRequestStream()) { writer.Write(data, 0, data.Length); }
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { // "OK" indicates we can retrieve the token. // You can also check for a "401", i.e. "Unauthorized" error that is // pass if the user name or password is incorrect. if (response.StatusCode == HttpStatusCode.OK) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { // The token will be held in an element "wrap_access_token", extract this token and // store it for later calls var queryString = reader.ReadToEnd(); NameValueCollection col = HttpUtility.ParseQueryString(queryString); _token = col.GetValues("wrap_access_token")[0]; } } }}
Sitefinity Web Services 473
© 2012 Falafel Software
Logging Out
Logout is also uses a GET request, but where the Url ends with "/Sitefinity/SignOut". The
token you saved during the login is added back into the request headers. The key to the
headers collection is the constant HttpRequestHeader.Authorization and the value is
'WRAP access_token="mytokencharacters"'. The token is surrounded by escaped quotes.
You can verify that the response status is "OK". In the example below, we're raising a
custom exception if the status is other than "OK".
public void Logout() { if (!_token.Equals(String.Empty)) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_baseUrl + "/Sitefinity/SignOut"); request.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + _token + "\""); request.Method = "get";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { if (response.StatusCode != HttpStatusCode.OK) { throw new ClaimsException("Logout failed."); } } }}
Listing Pages
The REST API calls follow a similar pattern to the Logout. A request is created to the
service URL and the token is popped back into the header. If the response comes back
with an "OK" status, you can use the JSON in the response stream to re-hydrate a plain old
.NET object.
public PageData GetPages(){ if (!_token.Equals(String.Empty)) { // setup the request to the pages service, defaults to the GetPages method HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_baseUrl + "/Sitefinity/Services/Pages/PagesService.svc"); request.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + _token + "\""); request.Method = "get"; request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { // everything's copacetic, keep going if (response.StatusCode == HttpStatusCode.OK) { using (StreamReader reader =
Sitefinity 5474
© 2012 Falafel Software
new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { // get the response stream using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))) { // rehydrate the JSON into a matching plain old ob ject DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(PageData)); return (PageData)serializer.ReadObject(stream);
} } } } } return null;}
The C# object mirrors the key properties of the JSON object. This object need only include
the properties of interest from the JSON object.
public class PageData{ public PageDataItem[] Items { get; set; }}
public class PageDataItem{ public PageTitle Title { get; set; } public string Owner { get; set; }}
public class PageTitle{ public string Value { get; set; }}
Sitefinity Web Services 475
© 2012 Falafel Software
Converting JSON to Objects
The response returns a serialized, JSON string, form. You can't directly iterate the string,
bind to the data to a control or do much else that's useful with it. To use JSON data, you
need to "deserialize", that is, convert the JSON string representation of a page into an
object representation of a page.
The screenshot below shows an example of the returned JSON displayed in Notepad.
Figure 385 --Returned JSON
JSON is returned unformatted from the web service and can be difficult to read. You can
use a JSON formatter to make the JSON intelligible (Google "JSON formatter", there are
many JSON formatters out there, such as http://jsonformatter.curiousconcept.com/).
From the formatter we get something that looks like the fragment below.
{ "Context":null, "IsGeneric":false, "Items":[ { "AdditionalUrlsRedirectToDefaultOne":true, "AllowMultipleUrls":false, "AvailableLanguages":[
], "FullUrl":"\/WebServicesDemo\/project-status", "HasChildren":false, "Id":"65b618f9-eb68-4795-b60a-58fcd33d13bd", . . .
Sitefinity 5476
© 2012 Falafel Software
You need a .NET object whose properties map to the properties of the JSON . Fortunately,
you don't need to map all the properties, just the properties you want to use. The full
JSON listing for a single page object is several full screens long. If we only want the Title
and the Owner of the page, then we're only looking at this part shown in a condensed
view of JSON below. In JSON, the curly braces denote an object and square brackets
enclose arrays. Each property is a name/value pair separated by a colon.
{ "Items":[ { "Title":{ "Value":"Project Status" }, "Owner":"Mr Telerik", }, }, ],}
Sitefinity Web Services 477
© 2012 Falafel Software
The .NET objects below map to the JSON string, where "PageData" represents the
outermost object, "Items" is an array where each item has a "Title" and an "Owner". "Title"
itself is another object that has a "Value" property.
public class PageData{ public PageDataItem[] Items { get; set; }}
public class PageDataItem{ public PageTitle Title { get; set; } public string Owner { get; set; }}
public class PageTitle{ public string Value { get; set; }}
How do you convert JSON into object form? DataContractJsonSerializer from the
System.Runtime.Serialization namespace has a ReadObject() method that munches
JSON and spits out an object.
The example below takes a string of JSON data, converts the JSON string to an array of
bytes and feeds the array of bytes to a MemoryStream. A new DataContractJsonSerializer
is created, passing the target object type to the constructor. The DataContractJsonSerializer
ReadObject() method accepts the memory stream of JSON data and returns the object.
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString))){ DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(PageData)); PageData pageData = (PageData)serializer.ReadObject(ms);}
Sitefinity 5478
© 2012 Falafel Software
Exception Handling
You will want to wrap your GetResponse() calls in try..catch blocks to trap exceptions in
the code and in the response headers. The example below shows the types of information
you can rip out of the response headers. WebException includes an HTTP Response where
you can interrogate the "X-Authentication-Error" value. The "ClaimsException" being
thrown is a custom exception descending from ApplicationException.
try{ using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { . . . }}catch (WebException ex){ string authError = ex.Response.Headers["X-Authentication-Error"]; if (authError != null) { if (authError.Equals("TokenExpired")) throw new ClaimsException("Your security token has expired"); else if (authError.Equals("UserAlreadyLoggedIn")) throw new ClaimsException("Already logged in."); else if (authError.Equals("UserLoggedFromDifferentComputer")) throw new ClaimsException("Account in use from another computer or browser."); else throw new ClaimsException(ex.Message, ex.InnerException); } else { throw new ClaimsException(ex.Message, ex.InnerException); } }
Sitefinity Web Services 479
© 2012 Falafel Software
Walk-Through
This walk-through will demonstrate using Claims Authorization to login, call a Sitefinity
REST API and log out.
Figure 386 --REST APIs and Claims
Building the Pages Object
1. First, create a Windows form application in Visual Studio.
2. Add a PageObject.cs class to your project and replace with the code below.
public class PageData{ public PageDataItem[] Items { get; set; }}
public class PageDataItem{ public PageTitle Title { get; set; } public string Owner { get; set; }}
public class PageTitle{ public string Value { get; set; }}
Sitefinity 5480
© 2012 Falafel Software
Building the Claims Object
Private Properties, Constants and Constructor
1. Add a new class "Claims.cs" to the project.
2. You will need the following references in the "using" clause.
using System;using System.Collections.Specialized;using System.IO;using System.Net;using System.Runtime.Serialization.Json;using System.Text;using System.Web;
3. Add private members to the Claims object that will store the base url, user name,
password and returned claims token.
private string _name;private string _password;private string _baseUrl;private string _token = String.Empty;
4. Add constants to represent the service urls we want to reach:
private const string AuthenticateUrl = "/Sitefinity/Authenticate";private const string SignOutUrl = "/Sitefinity/SignOut";private const string GetPagesUrl = "/Sitefinity/Services/Pages/PagesService.svc";
5. Add a constructor that takes the user name, password and base url and stores these to
the private members.
public Claims(string name, string password, string baseUrl) { _name = name; _password = password; _baseUrl = baseUrl;}
Helper Methods
Add a GetRequest() method that will create and initialize an HttpWebRequest with the
claims token and the HTTP method.
private HttpWebRequest GetRequest(string url, string method){ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_baseUrl + url); if (!_token.Equals(String.Empty)) { request.Headers.Add(HttpRequestHeader.Authorization, "WRAP access_token=\"" + _token + "\""); } request.Method = method; return request;}
Sitefinity Web Services 481
© 2012 Falafel Software
Login
Add a Login() method to the Claims object. This method will call the "Authenticate" url
the initial time to determine if this is a local security token service.
public void Login(){ // initial request to determine if security token service is on the same machine HttpWebRequest request = GetRequest(AuthenticateUrl, "get");
using (HttpWebResponse initialResponse = request.GetResponse() as HttpWebResponse) { // "OK" indicates the security token service is on the same machine // "302", i.e. "Moved" indicates that the site is using an external // security token service or a single sign on. In this case you would have get the // token from the location parameter in the response headers. if (initialResponse.StatusCode == HttpStatusCode.OK) { LocalServiceAuth(); } else if (initialResponse.StatusCode == HttpStatusCode.Moved) { // not implemented in this example } }}
Logout
Add a Logout() method to the Claims class. It should simply make a request to the
"SignOut" url.
public void Logout(){ if (!_token.Equals(String.Empty)) { GetRequest(SignOutUrl, "get").GetResponse(); }}
Sitefinity 5482
© 2012 Falafel Software
List Pages
Add a GetPages() method to Claims.cs that returns a PageData object. It should make a
call to the "GetPages" url and extract the PageData if the response status is "OK".
public PageData GetPages(){ if (!_token.Equals(String.Empty)) { // setup the request to the pages service, defaults to the GetPages method HttpWebRequest request = GetRequest(GetPagesUrl, "get"); request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { // everything's copacetic, keep going if (response.StatusCode == HttpStatusCode.OK) { using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { // get the response stream using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()))) { // re-hydrate the JSON into a matching plain old ob ject DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(PageData)); return (PageData)serializer.ReadObject(stream);
} } } } } return null;}
Sitefinity Web Services 483
© 2012 Falafel Software
Designing the Windows Form
Add the following components and properties to the design of the windows form.
1. Add three buttons named "btnLogin", "btnListPages" and "btnLogout". Set their Text
properties to "Login", "List Pages" and "Logout", respectively.
2. Add a Label and set the Text property to "Base Url of Sitefinity Application". Add a
TextBox below the Label and name it "tbBaseUrl".
3. Add another Label and set the Text property to "User Name". Add a TextBox below the
Label and name it "tbUserName".
4. Add a Label and set the Text property to "Password". Add a TextBox below the Label
and name it "tbPassword".
5. Add a TextBox to the bottom of the page and resize it to take up the remaining room on
the form. Name the TextBox "tbOutput" and set it's ScrollBars property to "Both" and
the MultiLine property to "True".
6. The finished design should look something like the screenshot below:
Figure 387 --Windows Form Design
Sitefinity 5484
© 2012 Falafel Software
Coding the Windows Form
1. Add a private member to represent the Claims object.
private Claims _claims;
2. In the constructor, create the Claims instance.
private void Form1_Load(object sender, EventArgs e){ _claims = new Claims(tbUserName.Text, tbPassword.Text, tbBaseUrl.Text); }
3. Add a helper method to print text to the "output" text box.
private void Log(string message){ tbOutput.Text += Environment.NewLine + message;}
4. Add a Click event to the "Login" button and code the event handler:
private void btnLogin_Click(object sender, EventArgs e){ _claims.Login(); Log("Logged in");}
5. Add a Click event to the "Logout" button and code the event handler:
private void btnLogout_Click(object sender, EventArgs e){ _claims.Logout(); Log("Logged out");}
6. Add a Click event to the "List Pages" button and code the event handler. The PageData
object returned from GetPages() will contain an Items array. Iterate the array and output
the Title value for each page.
private void btnListPages_Click(object sender, EventArgs e) { var pageData = _claims.GetPages(); if (pageData != null) { foreach (var item in pageData.Items) { Log(item.Title.Value); } }}
7. Add a FormClosed event to the form and code the event handler to automatically log
you out of Sitefinity when closing the form.
Sitefinity Web Services 485
© 2012 Falafel Software
private void Form1_FormClosed(object sender, FormClosedEventArgs e){ _claims.Logout(); }
Running the Application
Run the application and test out logging in, listing pages in the site and logging out. Also
try logging into the Sitefinity backend, run the Windows application and logout, then try
navigating to another page within the backend. Sitefinity should navigate out to the login
page.
Sitefinity 5486
© 2012 Falafel Software
Using Forms Authentication
Forms Authentication has been left in the product for backwards compatibility. Likewise,
this section has been left in the courseware, but Claims Authentication is the better choice
for all your projects going forward.
Logging in Via Web Service
We have to login to Sitefinity before we can do anything, so the AuthenticateUser method
is a good place to start.
1) Create a new Winforms application in Visual Studio. Open the default form for editing.
2) Add the members below to your form class. Modify the sitefinityHost string so that it
points to a running Sitefinity site. Remember that you can get this string from the
Sitefinity Project Manager URL column.
private const string sitefinityHost = "http://localhost:17968/WebServicesDemo";private const string usersServiceUrl = "/Sitefinity/Services/Security/Users.svc/";private static CookieCollection cookies;
3) Add a constant that will hold the JSON used to make the login request.
const string credentialsFormat = @"{{ ""MembershipProvider"":""{0}"", ""Password"":""{1}"", ""Persistent"":{2}, ""UserName"":""{3}""}}";
4) Create a new Login() method.
5) In the Login() method, add code to configure the web request. First, the segments of
the URL are assembled into a single string "url". Then an HttpWebRequest object is
created and passed the constructed URL. The method here is "POST" because we need
to add credential information later.
// configure and create the web requeststring url = String.Concat(sitefinityHost, usersServiceUrl, "Authenticate");HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);request.Method = "POST";request.ContentType = "application/json";
Sitefinity Web Services 487
© 2012 Falafel Software
6) Next, add code to handle cookies. If we have saved cookies that contain login
information from a previous request, add them back into the request. The key part is to
create the CookieContainer so that the response will have that available to store cookies
in.
// if saved cookies are availab le, add them to the requestrequest.CookieContainer = new CookieContainer();if (cookies != null){ foreach (Cookie cookie in cookies) if (!cookie.Expired) request.CookieContainer.Add(cookie);}
7) Create credential information in JSON format and write the JSON string to the request
stream. The "credentialsFormat" string provides a convenient way to populate the JSON
string using the String.Format() method. The MembershipProvider is left blank to use
the default provider. User name and password for the example Sitefinity site happens to
be "admin" and "password". The Persistent parameter is set true to indicate that a cookie
should be saved with the current authorization information.
// create JSON credential data and write to the request stream. string json = String.Format(credentialsFormat, String.Empty, "password", "true", "admin");byte[] credentials = Encoding.UTF8.GetBytes(json);request.ContentLength = credentials.Length;using (var writer = request.GetRequestStream()){ writer.Write(credentials, 0, credentials.Length);}
Sitefinity 5488
© 2012 Falafel Software
8) Get the response back and do something about it. Call the Request's GetResponse()
method. This needs to be cast to an HttpWebResponse so that it knows about things
like cookies. Speaking of cookies, you need to save off the response cookies into a
private variable, so that you can reuse them for another call.
// get the responseusing (HttpWebResponse response = request.GetResponse() as HttpWebResponse){ cookies = response.Cookies; using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { string result = reader.ReadToEnd(); Debug.WriteLine(result); }}
9) Add a button to the form, create a Click event handler and add the Login() method to
the button click event handler.
private void button1_Click(object sender, EventArgs e){ Login();}
Sitefinity Web Services 489
© 2012 Falafel Software
10)From the Sitefinity Project Manager, select the project that you want to reach with web
services and click the Go to Administration button. Verify that the URL in Sitefinity and
the "sitefinityHost" string you defined earlier are matching exactly.
11)Run the application, click the button and observe the result in the Output window. It
should return a "0". Other responses are failures of various types. You don't need to add
the following code, but it is a reference to the codes returned by the login response.
public enum LoginCodes{ Success = 0, UserLimitReached = 1, UserNotFound = 2, UserLoggedFromDifferentIp = 3, SessionExpired = 4, UserLoggedOff = 5, UserLoggedFromDifferentComputer = 6, Unknown = 7, NeedAdminRights = 8, UserAlreadyLoggedIn = 9, UserRevoked = 10, NotSet = 11}
Sitefinity 5490
© 2012 Falafel Software
Logging Out
Logging out is a variation on the same steps as Logging In. The changes to the Logout
method are:
A slightly different URL that ends with "Logout" instead of "Authenticate".
The http "GET" method is used instead of "POST".
No extra data is streamed into the request.
A different result code, "true", is returned on success.
Sitefinity Web Services 491
© 2012 Falafel Software
In fact, they're similar enough that even for this simple code, a little refactoring is in order.
Before we code a Logout() method, lets move the common features of Login() to another
method.
1) Create a new method called InvokeRequest() using the code below. The information
that differs are passed as parameters, i.e. the webMethod ("Authenticate" vs. "Logout"),
httpMethod ("POST", "GET"), and data (an arbitrary array of bytes for credentials and
unused by Logout()). This method returns the JSON response string.
private static string InvokeRequest(string webMethod, string httpMethod, byte[] data){ // configure and create the web request string url = String.Concat(sitefinityHost, usersServiceUrl, webMethod); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = httpMethod; request.ContentType = "application/json";
// if saved cookies are availab le, add them to the request request.CookieContainer = new CookieContainer(); if (cookies != null) { foreach (Cookie cookie in cookies) if (!cookie.Expired) request.CookieContainer.Add(cookie); }
// write to the request stream. if (data != null) { request.ContentLength = data.Length; using (var writer = request.GetRequestStream()) { writer.Write(data, 0, data.Length); } }
// get the response using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) { cookies = response.Cookies; using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { return reader.ReadToEnd(); } }}
Sitefinity 5492
© 2012 Falafel Software
2) Change the Login() method to use the code below. The Login() method now prepares
the credentials, calls the new InvokeRequest() method and writes out the result.
private static void Login(){ string json = String.Format(credentialsFormat, String.Empty, "password", "true", "admin"); byte[] credentials = Encoding.UTF8.GetBytes(json); string result = InvokeRequest(usersServiceUrl, "Authenticate", "POST", credentials); Debug.WriteLine(result);}
3) You will have to manually login to the site and then logout. Then retest the application.
4) Create a Logout() method using the code below. Add a second button to the form and
call Logout() from the Click event handler of the button.
private static void Logout(){ string result = InvokeRequest(usersServiceUrl, "Logout", "GET", null); Debug.WriteLine(result);}
5) Test the application. The result should return "true". You should be able to login and
logout multiple times. When you logout from the application, you should be able to
login directly to the Admin without a warning that another user is logged in.
Listing Pages
Returning a list of pages in Sitefinity is a representative example that you can adapt to
other methods in the Sitefinity web service API. The short story is that using the code
below with InvokeRequest() gets you a JSON string that represents an array of page
objects.
private void ListPages(){ const string pagesServiceUrl = "/Sitefinity/Services/Pages/PagesService.svc"; string result = InvokeRequest(pagesServiceUrl, "", "GET", null); Debug.WriteLine(result);}
Sitefinity Web Services 493
© 2012 Falafel Software
Walk-through
1) In the Solution Explorer, add a reference to the System.Runtime.Serialization
assembly. This assembly can be found on the .NET tab of the Add Reference dialog.
2) Add a new class file to the project and name it PageObject.cs. Add the code below to the
class file. Note that "PageData" is not the Sitefinity version of "PageData". This project
has no Sitefinity references, and these are our own custom objects.
public class PageData{ public PageDataItem[] Items { get; set; }}
public class PageDataItem{ public PageTitle Title { get; set; } public string Owner { get; set; }}
public class PageTitle{ public string Value { get; set; }}
3) In the code for the form, add a reference to the "using" (C#) or "Imports" (VB) section of
the code for the System.Runtime.Serialization.Json namespace.
4) Add a ListBox to the form and name it "PagesListBox". Set the Text property to "List
Pages".
5) Add a button to the form and name it "ListPagesButton". Double-click the button in the
designer to create a Click event handler.
6) In the Click event handler for the button, add the code below. The "GET" call to
PagesService returns a list of pages. The JSON string result is placed in a
MemoryStream. The DataContractJsonSerializer reads the stream and creates a
PageData object. The PageData Items array is used to populate the ListBox.
private void ListPagesButtonClick(object sender, EventArgs e){ const string pagesServiceUrl = "/Sitefinity/Services/Pages/PagesService.svc"; string result = InvokeRequest(pagesServiceUrl, "", "GET", null);
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(result))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(PageData)); PageData pageData = (PageData)serializer.ReadObject(ms); foreach (PageDataItem item in pageData.Items) { PagesListBox.Items.Add(item.Title.Value); }; }
Sitefinity 5494
© 2012 Falafel Software
}
7) Run the application and Login. Click the "List Pages" button. The pages in the site
should be displayed in the list box.
Figure 388 --Listing Pages
Sitefinity Web Services 495
© 2012 Falafel Software
What Next?
The code for this example is as simple as possible to demonstrate how the web services
work without burying you in code. Production level communication with the web service
will require additional infrastructure for robustness, and maintainability. You can build
your own framework around the web service API to handle common tasks such as
making web requests, handling cookies, deserializing responses, handling return codes
from failed logins, etc. You can also get ideas from the Sitefinity Starter Kits that include
code to wrap JSON calls and help with common tasks such as deserializing, logging in or
listing pages.
Sitefinity 5496
© 2012 Falafel Software
Summary
This chapter demonstrated how to work with both Forms Authentication and, the new
default, Claims Authentication. This chapter first showed how to get all the available web
services and method calls. You learned the basic steps in common with all web service
method calls, how to log in and log out of Sitefinity from a web service and how to
retrieve and parse information from a web service call.
22Content Classification - Taxonomy
Sitefinity 5498
© 2012 Falafel Software
22 Content Classification - Taxonomy
Sitefinity uses Categories and Tags to classify your content so that items can be found
easily. Categories are a hierarchical arrangement suited to tiered information, e.g. (CEO >
President > Vice President...), geographical areas (Europe > Eastern Europe > Bulgaria...) or
biologic classification (Family > Genus > Species). Tags are a "flat" organization where each
tag has no formal relationship to other tags.
The word "Taxonomy" comes from ancient Greek root words meaning essentially
"arrangement method". Telerik has chosen this word to describe a flexible way of
classifying content that's not locked down to just hard-coded Categories or Tags. While
Categories and Tags will handle most of your requirements, but you can also build your
own custom classification, i.e. an organization that is neither a Category or Tag.
Content Classification - Taxonomy 499
© 2012 Falafel Software
Objectives
This chapter introduces the basic terminology for Taxonomies and shows how to traverse
hierarchies of taxonomies and taxa. You'll learn about how to get statistics for a taxon,
retrieve items by a category or tag and how to programmatically add categories and tags.
Sitefinity 5500
© 2012 Falafel Software
Terminology
Taxonomy is the highest level "container" for classification information. "Categories"
and "Tags" for example are the two predefined taxonomies in the system. A Taxonomy
is represented in the Sitefinity system by the ITaxonomy interface and the Taxonomy
abstract implementation class, with properties that include TaxonName and Taxa (an
enumerable of individual categories, tags or custom taxa).
Taxon is an individual category, tag or some custom item. When a user adds a category
to a news item, they are adding Taxon. A Taxon is represented by the ITaxon interface
and the Taxon abstract implementation class.
Taxa is the plural of Taxon.
Content Classification - Taxonomy 501
© 2012 Falafel Software
Getting Started
The first step to working with taxonomies is to get a TaxonomyManager instance by
calling the GetManager() method. With a TaxonomyManager, you can perform CRUD
(Create, Read, Update, Delete) operations on taxonomies and individual taxon using
methods:
GetTaxonomy()
GetTaxon()
GetTaxa()
CreateTaxon()
CreateTaxonomy()
Delete(<taxon, taxonomy>)
Sitefinity 5502
© 2012 Falafel Software
Listing Taxonomies
You can retrieve either hierarchical or flat taxonomies. The code below retrieves all flat
taxonomies and displays the Title in a list box. The list box displays a single item "Tags".
You could also bind the DataTextField to the TaxonName property to display the singular
"Tag" instead.
TaxonomyManager taxonomyManager = TaxonomyManager.GetManager();IQueryable<FlatTaxonomy> taxonomies = taxonomyManager.GetTaxonomies<FlatTaxonomy>(); TaxonomyListBox.DataValueField = "Id";TaxonomyListBox.DataTextField = "Title";TaxonomyListBox.DataSource = taxonomies;TaxonomyListBox.DataBind();
To get all the possible tags in your system, make the GetTaxonomies() call twice, first
with FlatTaxonomy as the type, then with HierarchicalTaxonomy. Use the LINQ Union
() method to join the two lists together. The example below retrieves all taxonomies in the
system that are built in, using the TaxonomyManager static IsTaxonomyBuiltIn()
method.
TaxonomyManager taxonomyManager = TaxonomyManager.GetManager();var flat = taxonomyManager .GetTaxonomies<FlatTaxonomy>() .ToList() .Where(t => TaxonomyManager.IsTaxonomyBuiltIn(t)) .Select(t => new { Id = t.Id, Title = t.Title.Value });
var hierarchical = taxonomyManager .GetTaxonomies<HierarchicalTaxonomy>() .ToList() .Where(t => TaxonomyManager.IsTaxonomyBuiltIn(t)) .Select(t => new { Id = t.Id, Title = t.Title.Value });
var taxonomies = flat.Union(hierarchical);
Figure 389 --Listing
Taxonomies
The result of the union is bound to a ListBox in the
screenshot below and shows the flat "Tags"
taxonomy and the hierarchical "Categories"
taxonomy.
Content Classification - Taxonomy 503
© 2012 Falafel Software
Listing Taxa
This examples uses a sample set of data where the sample tags are "collecting" and
"classic". Sample Category Taxa form the following hierarchy:
"Europe"
"Eastern Europe"
"Bulgaria"
Using the previous example in Listing Taxonomies, try adding a handler for the
SelectedIndexChanged event to receive the SelectedValue. The SelectedValue is the Guid
string for the Taxonomy. Create a new Guid object, passing the SelectedValue into the
constructor. Call the TaxonomyManager GetTaxonomy() method and pass the Guid. Add
a second ListBox to the form and bind it's DataSource to the Taxonomy Taxa property.
protected void TaxonomyListBox_SelectedIndexChanged(object sender, EventArgs e){ TaxonomyManager taxonomyManager = TaxonomyManager.GetManager();
Guid taxonomyId = new Guid(TaxonomyListBox.SelectedValue); ITaxonomy taxonomy = taxonomyManager.GetTaxonomy(taxonomyId); TaxaListBox.DataValueField = "Id"; TaxaListBox.DataTextField = "Title"; TaxaListBox.DataSource = taxonomy.Taxa; TaxaListBox.DataBind();}
Selecting a Taxonomy from the first list box fires the SelectedIndexChanged event, the
bound Taxonomy Id is retrieved and used to get the Taxonomy object. The Taxonomy
Taxa collection is bound to the second list box.
Figure 390 --Listing Taxa
Sitefinity 5504
© 2012 Falafel Software
Finding Frequently Used Categories and Tags
TaxonomyManager has a nice little goody hidden away called the GetStatistics() method
that returns the MarkedItemsCount with the number of items marked with a given
taxon. Other properties with possibilities are:
The ApplicationName for the project that the statistic belongs to.
DataItemType determines the kind of content the particular Taxon is being used in.
StatisticType is the ContentLifecycleStatus used throughout Sitefinity to determine the
state of the content item, i.e. Master, Temp or Live.
The TaxonomyId and TaxonId Guids are both included so you can retrieve the
corresponding objects.
We can simply bind this information to a RadGrid in ASP.NET to see the bulk data.
Assign the GetStatistics() result to the RadGrid DataSource.
TaxonomyManager taxonomyManager = TaxonomyManager.GetManager();RadGrid1.DataSource = taxonomyManager.GetStatistics(); RadGrid1.DataBind();
The grid shows the raw statistic data.
Figure 391 --Statistics
If we filter and massage the data a bit with LINQ, we can get useful information to display.
Statistics can be used to populate a RadTagCloud with "weighted" links, where taxons
used in more places show in larger text.
Figure 392 --RadTagCloud with Statistics
Content Classification - Taxonomy 505
© 2012 Falafel Software
The code to accomplish this is listed below. Filter the results from GetStatistics() using
Where() and making sure that the StatisticType is "Live". Project the items into a new
anonymous type using Select(). You can save the TaxonId directly. To get the Title to
display in each link, call the TaxonomyManager GetTaxon() method and pass the TaxonId.
Get the Name property from the returned Taxon object. Finally, to get the comparative
weight of each item, use the MarkedItemsCount.
private void ListStatistics(){ TaxonomyManager taxonomyManager = TaxonomyManager.GetManager();
var statistics = taxonomyManager .GetStatistics() .Where(s => s.StatisticType == ContentLifecycleStatus.Live) .ToList() .Select(s => new { Id = s.TaxonId, Title = taxonomyManager.GetTaxon(s.TaxonId).Name, Weight = s.MarkedItemsCount, }) .OrderBy(s => s.Title).ToList();
StatisticsCloud.DataTextField = "Title"; StatisticsCloud.DataWeightField = "Weight"; StatisticsCloud.DataValueField = "Id"; StatisticsCloud.DataSource = statistics; StatisticsCloud.DataBind();}
Sitefinity 5506
© 2012 Falafel Software
Get Items by Category or Tag
What if I need to find all news items marked with the "Europe" Category or tagged
"collecting". You can get at that functionality through the content database provider. The
database provider can be reached through the manager of the particular content type
you're working with, for example NewsManager.Provider. The provider has a
GetItemsByTaxon() method that returns an IEnumerable of whatever content type you're
working with.
The steps are wrapped in the custom GetTaxonItems() method below that returns an
IEnumerable<T> for a particular Taxon.
The GetMappedManager() call returns the appropriate manager for the type you pass in.
For example, if we pass in NewsItem, GetMappedManager() will return a
NewsManager.
The manager's Provider property is a DataProviderBase type, so you need to cast up to a
ContentDataProviderBase that knows how to call GetItemsByTaxon() later in the
method.
You also need a TaxonomyPropertyDescriptor for the content type and taxon
combination.
Finally, you get to call GetItemsByTaxon(), passing in the information you've been
hoarding up to this point. The returned IEnumerable is cast to IEnumerable<T> and
returned from this method.
private static IEnumerable<T> GetTaxonItems<T>(ITaxon taxon){ // get the manager for the items, e.g. NewsManager var manager = ManagerBase.GetMappedManager(typeof(T)); // get the base content database provider ContentDataProviderBase contentProvider = manager.Provider as ContentDataProviderBase; // get a taxonomy property descriptor for this item type and taxon TaxonomyPropertyDescriptor prop = TaxonomyManager.GetPropertyDescriptor(typeof(T), taxon); int? totalCount = 0; // use the GetItemsByTaxon() method to return IEnumerable of items. var items = contentProvider.GetItemsByTaxon(taxon.Id, prop.MetaField.IsSingleTaxon, prop.Name, typeof(T), string.Empty, // filter string.Empty, // order by 0, // skip 100, // take ref totalCount); return items as IEnumerable<T>;}
Content Classification - Taxonomy 507
© 2012 Falafel Software
To call the method, set the type to be the content type you're looking for and pass in the
taxon to search on as a parameter. The example below is looking for all news items that are
marked with a particular taxon.
IEnumerable<NewsItem> items = GetTaxonItems<NewsItem>(taxon);
If you bind the items directly against a grid, you will see all the columns for the content
item type, in whatever life cycle status they happen to be in. The example below bridges
off the previous RadTagCloud example and displays the NewsItems for the selected cloud
tag.
Figure 393 --Listing Items for a Taxon
You can boil this data down a bit using lambda expressions to look only for Live items and
only showing certain columns.
The code below handles the RadTagCloud ItemClick event. The event args for the handler
include the Item.Value property that contains the Guid for the Taxon. You can use the
TaxonomyManager.GetTaxon() method to retrieve the Taxon corresponding to the item
the user clicked on. Now that you have the Taxon, call the custom GetTaxonItems()
method and pass the taxon as a parameter.
Sitefinity 5508
© 2012 Falafel Software
Next, a lambda expression filters for only "Live" Status items. Only the "Title" and "Url"
columns are selected.
protected void StatisticsCloud_ItemClick(object sender, RadTagCloudEventArgs e){ TaxonomyManager taxonomyManager = TaxonomyManager.GetManager(); ITaxon taxon = taxonomyManager.GetTaxon(new Guid(e.Item.Value));
IEnumerable<NewsItem> items = GetTaxonItems<NewsItem>(taxon);
var news = items .Where(n => n.Status == ContentLifecycleStatus.Live) .Select(n => new { Title = n.Title.Value, Url = n.Urls.FirstOrDefault().Url });
RadGrid1.DataSource = news; RadGrid1.DataBind();}
The data bound in the grid looks something like the screenshot below.
Figure 394 --News Item Data
Content Classification - Taxonomy 509
© 2012 Falafel Software
Adding Categories and Tags
To create a new taxon, use the TaxonomyManager CreateTaxon() method. Specify the
type of taxon you want to create, i.e. HierarchicalTaxon or FlatTaxon. For
HierarchicalTaxon, you need to specify the Parent. In the example below the Category
"Eastern Europe" is retrieved using the GetTaxa() method and assigned to the new taxon's
Parent property.
Also notice programmatic login as a user with permissions to create a taxon.
SecurityManager.AuthenticateUser(String.Empty, "admin", "password", false);
TaxonomyManager taxonomyManager = TaxonomyManager.GetManager();
// get the parent taxonHierarchicalTaxon EasternEuropeTaxon = taxonomyManager.GetTaxa<HierarchicalTaxon>() .ToList() .Where(t => t.Title.Value.Equals("Eastern Europe")) .SingleOrDefault();
// build a new taxon and place it underneath the parentHierarchicalTaxon HungaryTaxon = taxonomyManager.CreateTaxon<HierarchicalTaxon>();HungaryTaxon.Name = "Hungary";HungaryTaxon.Title = "Hungary";HungaryTaxon.UrlName = "hungary"; HungaryTaxon.Parent = EasternEuropeTaxon;HungaryTaxon.Taxonomy = EasternEuropeTaxon.Taxonomy;
taxonomyManager.SaveChanges();
SecurityManager.Logout();
Gotcha!
Notice that you need to assign the Taxonomy property, i.e. Category, Tag or a
custom Taxonomy. Not assigning the Taxonomy property leads to a difficult-to-
diagnose "Null reference object" exception.
Sitefinity 5510
© 2012 Falafel Software
Summary
This chapter introduced the basic terminology for Taxonomies and showed how to
traverse hierarchies of taxonomies and taxa. You learned about how to get statistics for a
taxon, retrieve items by a category or tag and how to programmatically add categories and
tags.
23Dynamic Data
Sitefinity 5512
© 2012 Falafel Software
23 Dynamic Data
Each type of content in Sitefinity has just about every property you need. Almost. For
example, news items have SourceName and SourceSite properties to track where the
news comes from originally. What if you needed a "SourceDate" property to denote the
date the source material was obtained? Sitefinity User objects have properties for
UserName, LastActivityDate and Email. What if your organization needs to track
"HireDate", "HireReason" and "NextReviewDate"?
Sitefinity allows you to create custom fields without having to register them in code-
behind or referencing libraries.
Dynamic Data 513
© 2012 Falafel Software
Objectives
In this chapter you'll learn how to add a new custom field to a content item from the
Sitefinity back end. Then you'll use the DynamicData facade to programmatically list
types and fields. Finally, you'll learn how to read and write custom field values.
Sitefinity 5514
© 2012 Falafel Software
Adding Custom Fields
You can create your own custom fields that "come along for the ride" when the user enters
data. Custom fields are associated with a specific type of data, for example, "NewsItem",
"SitefinityProfile", "Document" etc. Custom fields can be created directly in Sitefinity
administration.
1) In the Sitefinity Administration menu, select Content > News.
2) Before proceeding, make sure that at least one news item is already created. See the
Using Sitefinity > Content > News section for steps on creating news items.
3) Click the Custom Fields for news link.
Figure 395 --Selecting Custom
Fields Link
Notes
This link will only show when you have at least one news item created.
Dynamic Data 515
© 2012 Falafel Software
4) For this walk-through, choose Date and Time from the Type drop down list. Enter
"ReviewDate" as the Name for the custom field. Click the Continue button to accept the
custom field settings.
You can choose a predefined data type from the Type drop down list. You can prevent
the field from displaying in the editor by selecting the This is a hidden field check box.
The Interface widget... will list an appropriate editor for the type and Custom (to use a
custom control to edit the field). The Advanced section allows you to map the custom
field data type against database types.
Figure 396 --Adding a Field
Sitefinity 5516
© 2012 Falafel Software
5) In the Settings, Label and text tab, enter the Label "Review Date" and Instructional text
as "Enter the date when the news item should be reviewed". Click the Done button to
close the dialog.
You can also enter a default in the Predefined value space. Quite often you will want a
particular field filled out every time a content item is created, so check the Make required
box for ensure that the user can't save the item without making an entry.
The Limitations tab allows you to set minimum and maximum values and an error
message if the user entry falls outside the range. The Appearance tab determines where
the field will be shown in the backend.
Figure 397 --Custom Field Settings
Dynamic Data 517
© 2012 Falafel Software
6) The your new "ReviewDate" field should display in the list of custom fields for news
item. Notice that the list starts out with Tags and Category classification field types and
that these are considered to be custom fields.
Figure 398 --New Custom Field
7) Create a News Item. Scroll to the bottom of the news item to see your new custom
"Review Date" field label and instruction text.
Figure 399 --The Custom Field in the News Item
Sitefinity 5518
© 2012 Falafel Software
8) Click the entry box to see the popup calendar editor.
Figure 400 --Popup Calendar
Dynamic Data 519
© 2012 Falafel Software
Notes
The Type drop down list also includes Short text, Long text, Multiple choice, Yes /
No, Currency, Number and Classification. You can add multiple fields to a content
type. The screenshot below shows examples of Date-Time, Long text, Multiple
choice and Currency.
Figure 401 --Multiple Custom Fields
Sitefinity 5520
© 2012 Falafel Software
Using the DynamicData Facade
What custom fields have been created on your Sitefinity web site? You can find this out
programmatically using the Fluent API DynamicData facade. The DynamicData facade
has methods to work with:
Types: The item types that have custom fields, such as NewsItem or BlogPost.
Fields: The custom fields. Each field has a long list of information including the field
name and type.
Dynamic Data 521
© 2012 Falafel Software
Programmatically Listing Types
Use the code below to get the list of types. This example binds the list of types to a
RadComboBox, displays the "ClassName" and stores the "Id" column as the value.
// get types that can have custom fields and aren't dynamicvar itemTypes = App.WorkWith() .DynamicData() .Types() .Get() .Where(d => !d.IsDynamic) .ToList();
ItemTypeCombo.DataSource = itemTypes;ItemTypeCombo.DataTextField = "ClassName";ItemTypeCombo.DataValueField = "Id";ItemTypeCombo.DataBind();
Figure 402 --Item
Types
The screenshot shows the result. The entries
correspond not to custom field types, but to the types
of Sitefinity items that can have custom fields. The
check for !IsDynamic filters out types like
"sf_ec_prdct_software" already created by Sitefinity or
"sf_askcarconduitaquestion" which was created as a
by product of creating a form.
Sitefinity 5522
© 2012 Falafel Software
To retrieve this type from an item selected in this combo box, first get the Value property
that contains a Guid string. Feed the string into the constructor of a Guid object. Use the
Guid as a parameter to the Type() method. Use the Get() method to return a MetaType
that in turn has the ClrType. It's this ClrType that corresponds to a particular item class, e.
g. NewsItem, Event, BlogPost, etc. If the user selects "NewsItem" as in the screenshot
above, the ClrType will be equivalent to typeof(NewsItem).
protected void ItemTypeCombo_SelectedIndexChanged(object sender, Telerik.Web.UI.RadComboBoxSelectedIndexChangedEventArgs e){ Guid itemTypeId = new Guid(e.Value);
Type itemType = App.WorkWith() .DynamicData() .Type(itemTypeId) .Get() .ClrType;}
Dynamic Data 523
© 2012 Falafel Software
Programmatically Listing Fields
How can you query for all the custom fields in the entire system or for just a single item
type (e.g. news items)? To get at all fields, bridge off the DynamicData() facade and call
the Fields() method. The Get() method retrieves an IQueryable of MetaField. MetaField is
where all the good stuff is: the CLR type, the SQL type for the database, if the field is
hidden or not, limitations such as minimum and maximum value, its Guid ID and so on.
List All Fields
The code example below retrieves the metadata for all fields and all item types in the
system.
var fields = App.WorkWith() .DynamicData() .Fields() .Get() .ToList();
If you assign "fields" from the code example to a RadGrid, the result looks something like
the screenshot below. RadGrid generates columns automatically based on the data source
and can be a big help by displaying a quick snapshot of your query results. From this grid
we know that we have Id, FieldName and ClrType columns that we can work with.
Figure 403 --Fields Displayed in a Grid
Sitefinity 5524
© 2012 Falafel Software
List Fields for a Type
If you want only the fields for a particular item type (e.g. NewsItem), the query syntax
shifts slightly to use the Type() method and then the Fields property. The code example
below passes the NewsItem type to the Type() method and returns a DynamicTypeFacade.
The Get() method returns a MetaType and finally, the MetaType has a Fields collection.
The example uses a Select statement to return a smaller set of columns.
var fields = App.WorkWith() .DynamicData() .Type(typeof(NewsItem)) .Get() .Fields .Select(f => new { Id = f.Id, FieldName = f.FieldName, ClrType = f.ClrType, DbType = f.DBType });
The results in a grid look something like the screenshot below.
Figure 404 --Fields Displayed in Grid
Dynamic Data 525
© 2012 Falafel Software
Walk-through
You can put the Programmatically Listing Types example together with the List Fields for
a Type example to dynamically show all fields for a selected type.
1) In an ASP.NET web form, add a RadScriptManager, a RadComboBox and a RadGrid.
Set the RadComboBox AutoPostBack property to "true". The markup should look like
the example below. Note: be sure to drag these controls onto the page so that they are
registered properly.
<form id="form1" runat="server"><div>
<telerik:RadScriptManager ID="RadScriptManager1" runat="server"> </telerik:RadScriptManager> <telerik:RadComboBox ID="ItemTypeCombo" Runat="server" AutoPostBack="True" DropDownWidth="200px" MaxHeight="200px"> </telerik:RadComboBox>
<br />
<telerik:RadGrid ID="FieldsGrid" runat="server" > </telerik:RadGrid>
</div>
2) In the code-behind, add the code below to the Page_Load event handler.
protected void Page_Load(object sender, EventArgs e){ if (!IsPostBack) { // get types that can have custom fields and aren't internal var itemTypes = App.WorkWith() .DynamicData() .Types() .Get() .Where(d => !d.IsDynamic) .ToList();
ItemTypeCombo.DataSource = itemTypes; ItemTypeCombo.DataTextField = "ClassName"; ItemTypeCombo.DataValueField = "Id"; ItemTypeCombo.DataBind(); }}
3) In the page designer, double-click the RadComboBox to create a
SelectedIndexChanged event handler.
Sitefinity 5526
© 2012 Falafel Software
4) Replace the code for the SelectedIndexChanged event handler with the code below. The
event handler converts the selected combo box item value back into a Guid. Next, the
CLR type for the selected type is retrieved. Finally, all the fields for the selected item
type are retrieved, reshaped to only use a few columns and bound to the grid.
protected void ItemTypeCombo_SelectedIndexChanged(object sender, Telerik.Web.UI.RadComboBoxSelectedIndexChangedEventArgs e){ // convert the Type id string back into a Guid Guid itemTypeId = new Guid(e.Value);
// get the item CLR type, e.g. typeof(NewsItem) Type itemType = App.WorkWith() .DynamicData() .Type(itemTypeId) .Get() .ClrType;
// get all fields for the selected type var fields = App.WorkWith() .DynamicData() .Type(itemType) .Get() .Fields .Select(f => new { Id = f.Id, FieldName = f.FieldName, ClrType = f.ClrType, DbType = f.DBType });
// display fields in the grid FieldsGrid.DataSource = fields; FieldsGrid.DataBind();}
Dynamic Data 527
© 2012 Falafel Software
5) Run the application. Select an item type to see the fields for the type in the grid. In the
screenshot below, the SitefinityProfile type is selected and shows three custom fields
that have been manually added for "HireDate", "HireReason" and "ReviewDate".
Figure 405 --Fields for a Selected Type
Sitefinity 5528
© 2012 Falafel Software
Reading and Writing Custom Field Values
The most frequently asked question about custom fields is "how do I read or write my
custom field value"? The magic is in the DataExtensions class from the Telerik.Sitefinity.
Model namespace. As the name suggests, the class contains extension methods, so you
need to have Telerik.Sitefinity.Model in your "uses" (C#) or "Imports" (VB) section of code.
The three key methods of DataExtensions that can be used with Sitefinity content items
are:
GetValue(<field name>)
SetValue(<field name>, <value>)
DoesFieldExist(<value>)
For example, if we retrieve a particular NewsItem, we can call the SetValue() method from
that NewsItem. The example below retrieves a NewsItem where the Title property is
"Southern France Car Rally", then calls the SetValue() extension method, passing the field
name "ReviewDate" and a DateTime 30 days into the future.
App.WorkWith() .NewsItems() .Where(n => n.Title.Equals("Southern France Car Rally")) .ForEach(n => n.SetValue("ReviewDate", DateTime.UtcNow.AddDays(30))) .SaveChanges();
A variation on this example uses the GetValue() method to pick up only the news items
that have a null "ReviewDate" and sets the field values.
App.WorkWith() .NewsItems() .Where(n => !n.GetValue<DateTime?>("ReviewDate").HasValue) .ForEach(n => n.SetValue("ReviewDate", DateTime.UtcNow.AddDays(30))) .SaveChanges();
Dynamic Data 529
© 2012 Falafel Software
Summary
In this chapter you learned how to add a new custom field to a content item from the
Sitefinity back end. Then you used the DynamicData facade to programmatically list types
and fields. Finally, you learned how to read and write custom field values.
24About Falafel
About Falafel 531
© 2012 Falafel Software
24 About Falafel
Falafel Software Inc, an 8 time Microsoft Gold Certified Partner
providing consulting, training, and software development for
enterprise and small business customers. Falafel has designed and built
numerous high profile websites for major customers around the globe
and serves as Telerik's premier Sitefinity training partner. Falafel
Software offers a wide range of services to Sitefinity customers
including:
Complete website architecture, design and implementation services
Immediate assistance and troubleshooting through our Consulting
Express offering
Providing Sitefinity online and on-site training for individual
organizations
Hosting Telerik's monthly online training for new and advanced
Sitefinity users
Sitefinity 5532
© 2012 Falafel Software
Support and Services
Falafel Software has a strong presence in the Sitefinity space, including some very well-
known Sitefinity engineers in the Sitefinity community. Our offerings include training,
consultation, development, and we have released a host of custom modules and
integrations to the Sitefinity marketplace. We are the company of choice for migrating to
Sitefinity 5.
Training
Onsite Training: A highly knowledgeable Falafel
Software trainer will come to you and provide your
team with an enlightening 3-5 day class. This is the
best way to ramp up quickly.
Online Training: For companies that have team
members in multiple locations or in situations where
onsite training is not feasible, online training is a great
option.
Training Summit: If your team only has a few
individuals in need of training, this open-enrollment
option is the most cost effective solution.
Learn more about our current Sitefinity offerings at
http://www.falafel.com/Telerik/sitefinity/training.aspx.
Consulting
About Falafel 533
© 2012 Falafel Software
Our software consulting services cover the complete project lifecycle, from inception
to deployment, including project management, architecture, software development,
quality assurance, training, help desk and support. We can provide individual
consultants, or a complete team. We can also help with troubleshooting, proof of
concept pilot projects, technical due diligence, and evaluation of technology.
Our consultants are some of the most experienced in the industry, with hundreds of
man-years of combined consulting experience in many areas of expertise and several
vertical markets.
Consulting Express
Falafel Consulting Express is a ONE hour consulting
service with a Falafel team member via phone, email,
Skype or Instant messaging that enables any customer
worldwide to have access to the team for a quick
technical problem or a GotoMeeting session to help find
a resolution to a customer's blocking problem.
Sitefinity Web Design
Falafel Software's design team are experts in
setting up well designed, easy to navigate, and
easy to maintain websites using Sitefinity CMS.
Add to that our experience with UI design and
integration, and you can be sure that we are the
right solution for your design needs.
Learn more at http://design.falafel.com/index.
aspx.
Sitefinity 5534
© 2012 Falafel Software
SiteBoard
SiteBoard is the Sitefinity administrator’s mobile companion. Available on all the
major smart clients, it enables the busy administrator to perform critical tasks on the
fly, such as logging out users, publishing or un-publishing pages, and moderating
blog comments. SiteBoard allows you to manage multiple Sitefinity sites from one
easy-to-use mobile interface. SiteBoard uses the native Sitefinity REST API and
native mobile client user interfaces to deliver maximum usability, functionality and
performance.
About Falafel 535
© 2012 Falafel Software
Sitefinity Marketplace Items By Falafel
Falafel has been a very active contributor of modules to the
Sitefinity marketplace. Marketplace items by Falafel:
Events Map Plug-in
Orders Module
Events Rotator Plug-in
Falafel Contacts Module for Sitefinity
News Rotator Plug-in
FormBuilder Module
Falafel Content Slider Widget
Sitefinity Connector for Facebook
Sitefinity Connector for Twitter
Sitefinity CSS Editor
Falafel Twitter Feed Widget
Events Registration Module
Falafel Newsletter Group Importer
Other Resources
Go to http://blog.falafel.com/ for in-depth
blogs on CMS, Silverlight, Mobile, Telerik
controls and technology issues of the day.
Sitefinity 5536
© 2012 Falafel Software
Go to Falafel TV for video on variety of
technical subjects including CMS,
Silverlight, Mobile and Testing.
Mobilize your Sitefinity applications with
help from the Falafel Mobile team. Go to
http://www.falafel.com/
mobiledevelopment.aspx for more
information.
Contact Us Today!
For more info on Falafel Software, visit http://www.falafel.com or call 1-888-GOT-
FALAFEL (1- 888-468-3252).
Index 537
© 2012 Falafel Software
537
Index- . -.DynamicData() 523
- < -<form> tag 258
<head> tag 258
- 2 -2 levels of approval before publishing 178
- A -access_token 473
Actions 78
Add languages... 353
Add roles or users 173
Additional info 94
AddUserToRole() 308
Administration 443, 452
Administrators 168, 308
Advanced 94
Album 324, 327, 425
All content and pages 178
All pages under particular page 215
All published news 94
All published videos 123
Allow administrators to skip the workflow 178
Allow Comments 87, 133
Alternative Publishing 133
An item in the feed contains 133
Analytics 188
App.WorkWith() 315, 319, 327, 331, 332
App.xaml 422
App_Data 249, 376
App_Master 256, 260
Appearance 154, 514
ApplicationName 504
Applied To 198, 204
Apply Behavior 239
AppRoles 308
Approval before publishing 178
ASP.NET 244, 276, 278, 289
Aspect ratio 237
AssemblyInfo.cs 397, 407, 428
AuthenticateUser 466, 486
AuthenticateUser() 304
Authorization 473
Authors 168
AutoPostBack 409
Average pages per visit 191
Average time on site 191
- B -Backend screens tweaks 452
Backenduser 171
BackendUsers 168, 308
based on 210, 256
blog engine 133
blog post 133
Blog posts 133, 136
Blog Posts widget 142
Blogs 86, 132
Blogs Insert 202
Blogs Insert... 199
Bounce Rate 191
Browsable() 386
Build Action 384, 397, 399, 400, 402, 428
- C -Cascading Style Sheet 221
Categories 498
Categories and Tags 87
Categories Change 87
Category 380
Category attribute 380
Change Owner 78
Change Template 218
ChangeParent() 285
CheckIn() 322, 327
CheckOut() 316, 322, 327
Claims Authentication 302, 471, 486
Class Library 382
Class Library Project 382
Classes 62
Sitefinity 5
© 2012 Falafel Software
Classification 52, 265
Click to add a description 106
ClrType 521, 523
Code reference for modules 458
CompositeControl 386
Computed style 225
Configuration 279
Configuring the Google Analytics widget 188
Confirmation options 154
Contact information 101
Content 52
Content Block 87
ContentDataProviderBase 506
ContentItem 291, 293, 294
ContentLifecycleStatus 285, 332
ContentManager 291, 293, 295
ContentPlaceholder 256, 260, 263, 265
ControlDesigner 405, 407
ControlDesignerBase 404
ControlDesignerModes 404
Controls 346
ControlType 376, 391, 436
CookieCollection 486
CookieContainer 486
Copy content from another language 353
Copy in clipboard 188
Count() 332
Create a Blog 133
Create a child of the selected page 81
Create a child page 78
Create a content item 87
Create a form 154, 437
Create a group of rules 233
Create a library 146
Create a list item 128
Create a news item 94
Create a Page 44, 263
Create a post 136
Create a Response 437
Create a role 169
Create a Template 252, 260
Create a user 171
Create an Album 106
Create and return to templates 210, 260
Create as child page 112
Create New Template 202
Create this album 106
Create this list 128
Create this template 202
CreateContent() 291
CreateDataItem 458
CreateImage() 327
CreateNew() 319, 321
CreateNewStandardPage() 316
CreatePageData() 285
CreateTaxon() 501, 509
CreateTaxonomy() 501
CreateUser() 307
Credentials 304, 306
CRUD 273, 291
CSS 221, 225
CSS widget 222
Custom Control 369, 410
Custom Control Designer 425
Custom Controls 382, 406, 408
Custom Fields 514
- D -dashboard 191
Data 52
DataBind() 335
DataContractJsonSerializer 475, 482, 493
DataExtensions 528
DataFieldID 289
DataFieldParentID 289
DataItemType 504
DataSource 335, 341, 345
DataTextField 335
DataValueField 335, 341
Default 308
Delete() 291, 294
Descendants 325
Description and Keywords 44
Design 233
Designers 168
Different domains 353
Directories 353
directory structure 249
DirectoryInfo 329
Do() 319
Document Link widget 149
Document Manager 67
Document Object Model 225
documents 146
DoesFieldExist 528
Index 539
© 2012 Falafel Software
539
DOM 225, 400
Download from Publisher 248
DownloadData 327
Drag layout elements 62, 212
Drag widgets 52, 215
DropDownList 335
DynamicContent 458
DynamicData 520
DynamicData() 521, 523, 525
DynamicModuleManager 458
DynamicTypeFacade 524
- E -Edit layout element 222
Editors 168
Element 325
Elements 325
Embed link to this file 146
Embedded Resource 384, 397, 399, 400, 402, 407
Enable caching 44
Enable ViewState 44, 408
EnableViewState 386
Enter Content 52
Entries 346
Events 86, 87
Expandable list 131
Export CSV 160
Extension 329
- F -FieldControl 432
FieldName 435, 523
Fields 524
FileInfo 329
FileInfo.Extension 329
FileInfo.Open() 329
Find & Replace 67
Fine tune the selected type 112, 123
Firebug 225
First Time Setup and Configuration 188
First() 332
FirstOrDefault() 294
FlatTaxon 509
FlatTaxonomy 502
Fluent 316, 331, 332
Fluent API 273, 316, 324, 326, 331, 332
FluentSitefinity 315, 331
form 154
Form Builder 427
Format Stripper 52, 67
FormatString 215
FormDescription 341, 344, 346
FormEntry 344
FormsManager 341, 344
freecsstemplates.org 256
From already uploaded 52, 149
From selected library 123
From your computer 52
Frontend Themes 251, 259
FrontendRootNodeId 285
- G -Generate Thumbnails 119
Generic content list 87
Get Analytics Accounts 188
Get() 332
GetAlbum() 326, 327
GetBingResults() 325
GetContent() 291, 293
GetControl() 420
GetCurrentUserName() 434
GetFiles() 329
getfirebug.com 225
GetForm() 343
GetFormEntries() 344
GetForms() 341
GetItems() 291
GetItemsByTaxon() 506
GetManager() 276, 285, 291, 293, 307, 344, 458,
501
GetMappedManager() 506
GetPageDataList() 276
GetPageNode() 285
GetPageNodes() 285, 289
GetResponse() 486
GetRoles() 308
GetScriptDescriptors() 435
GetScriptReferences() 404, 407, 435
GetStatistics() 504
GetTaxa() 501, 509
GetTaxon() 501, 506
GetTaxonomies() 502
Sitefinity 5
© 2012 Falafel Software
GetTaxonomy() 501, 503
GetTemplates() 285
GetValue 528
GetValue() 344
Go to Analytics 188
Google Analytics 188
group other pages 44
Guid 285, 292
Guid.Empty 289
- H -HashTable 418, 420
HD2 236
HeaderText 347
hidden field 514
HiddenField 420
HierarchicalTaxon 509
HierarchicalTaxonomy 502
Host the Silverlight application... 411
HTC 236
HTC Incredible 236
HTML 225
HTML Editor 67
HTML included in the <head> tag 44
HtmlPage 422
HtmlTitle 285
HttpRequestHeader 473
HttpStatusCode 481
HttpUtility 471
HttpWebRequest 480, 482, 486
HttpWebResponse 481, 482, 486
Hyperlink 67
- I -IEnumerable 325, 327, 329
IFormFieldControl 432
Image gallery 112
Image Manager 52, 67, 128
Images 86
Images Gallery 112
Implement Abstract Class 404
Include RadScriptManager 44, 408
InitializeControls 434
InitializeControls() 386, 418
Insert a document or other file 149
Insert a video 123
Insert this Link 52
Instructional text 154
Interface Labels & Message 365
Interface Labels & Messages 6, 352, 365
Interface widget... 514
Invariant language 365
iPad 2 236
iPhone 236
iPhone 4 236
iPhone 4s 237
IQueryable 291, 293, 332, 341
IQueryable<T> 293
IsBackendPage 276
IsTaxonomyBuiltIn() 502
ITaxonomy 500
- J -JavaScript 188, 225, 396, 400, 406, 415, 418,
421, 428, 430
JavaScript Object Notation 418, 466
JavaScriptSerializer 418
JQuery 400
JScript 400, 428
JSON 418, 466, 473, 475, 486, 490, 495
- K -Keep all language versions synced 353
- L -Label 154, 372
Language Packs 365
Language selector widget 360
Languages 364
Last() 332
Layout 212, 225, 254
LayoutTemplateName 386, 404, 433
Levels to include 215
LibrariesManager 458
library 146
lightbox 112
Limit the items in the feed 133
Limitations 154, 514
Link to a CSS file 222
Index 541
© 2012 Falafel Software
541
LinkTo 52
LINQ 273, 285, 291
list 128
list item 128
List Items widget 131
List Settings 94, 142, 199
List template 94, 142
ListBox 344
Live 291, 293, 332
Localization 362
Location 101
Login 52
Login name widget 215
Logout 173
Logout() 306
Lstring 363
- M -Make required 154, 514
Manage 86
Manage backend languages 353
Manage Pages 80
MarkedItemsCount 504
Marketplace 247, 249
Master 258, 291, 293
Master Page 246, 256
master pages 244, 249
Match case 67
Match whole words 67
Media Manager 67
MembershipCreateStatus 307
MembershipProvider 486
MemoryStream 327, 493
meta tags 258
MetaField 346, 435, 523
MetaType 521
Method 466
Module Builder 443, 452
More actions 81
More formatting options 52
Multilingual URLs 353
Multiple choice widget 154
- N -Name for developers 154
NameValueCollection 471
Navigation 52
Navigation widget 215
NeedAdminRights 304
NeedDataSource 347
New visits rate 191
News 86, 87
NewsItem 319
Newsletters 52
No limit and paging 94
No Restrictions 154
Notify users by email 178
Number of daily visits 191
- O -One entry per IP 154
One entry per username 154
Open() 329
OrderBy() 332
OrderByDescending 332
OrderByDescending() 332
Orientation 237
Other data 202
Overlay 123
Owner 292
- P -page template 209
Page Templates 80, 210, 222, 252, 260
Page views 191
PageControls 374, 376, 391
PageData 276, 285, 289, 362
PageManager 276, 285
PageNode 285, 289
Pages() 317
PageTemplate 422
Paragraph box widget 154
Parent 289
Paste From Word 67
Paste Word 52
Permission 166
Permissions 166, 169, 173
Permissions for all pages 80
Persistent 304, 486
pluginLoaded() 421
Sitefinity 5
© 2012 Falafel Software
Predefined value 514
PreRender 347
Properties.AssemblyInfo.cs 397
PublicationDate 319
Publish 79
Publish() 291, 292, 316, 322, 327
- R -RadBook 410, 418, 422, 425
RadComboBox 409
RadControls 52
RadGrid 345, 347
RadScriptManager 44, 408
RadTagCloud 504, 506
RadTreeView 289, 317
Range 154
ReadObject() 475
Really Simple Syndication 132
Rebind() 347
RecompileItemUrls() 292
RecompileItemUrls<T>() 291
Redirect to a page... 154
RegisterScriptableObject 422
Remove Link 67
Request Example 466
Request Format 466
Request Schema 466
Require SSL 44
RequireScriptManager 418, 420
Resize images... 106
Resize the image width to... 215
Resolution 237
ResolveUrl() 415
ResourceClassId 374
ResourceFile 397
ResourceLinks 402
Response Example 466
Response Format 466
Response Schema 466
Responses for... 160
Responsive and Mobile design 233
REST 273, 324, 473
Restore template to default 202
Restrictions 154
role 166, 169
Role Providers 308
RoleManager 308
Roles 168
RSS 132, 141, 324
RSS feed 141
RSS or Atom to generate 133
rules 233
- S -Samsung Galaxy Tab 236
Save a Draft 87
Save as Draft 79
SaveChanges() 285, 291, 292, 295, 307, 316, 319,
327
Schedule Publish 136
ScriptableMember 418, 422
ScriptManager 408
Scripts and Styles 52, 222
Search 52
Search Engine Optimization 87
search engines 44
Search Options 67
Search... 81
Sections 374, 376, 391
Security Token Service 471
SecurityManager 304, 306, 434
Select a masterpage 260
Select a template 254
Select another Template 210, 260, 263
Select another template... 254
Select documents or other files 146
Select image gallery type 112
Select roles or users 178
Select() 289, 333
Selected Album... 112
SelectedIndexChanged 335
SelectedValue 335
Send for Approval 183
SEO 87
Services 466
SessionExpired 304
Set approvers 178
Settings 374, 391
Settings & configurations 178
SetValue 528
Show in Navigation 44
Silverlight 411
SimpleView 386
Single Item Settings 94, 142
Index 543
© 2012 Falafel Software
543
Single Sign On 471
Sitefinity API 273, 291
Sitefinity Marketplace 247
Sitefinity REST services 273
Sitefinity Starter Kits 495
Sitefinity Template 246, 256
SitefinityWebApp 274, 384, 402, 428
SiteInitializer 285
Skip() 332
Smart phone 233
Smartphones 233
SolarFlare 247, 248, 252, 254
Sort blog posts 142
Sort news 94
SourceName 512
SourceSite 512
Spell Check 67
Static 402
StatisticType 504
Stream 327
StreamReader 482, 486
STS 471
Style Sheet 399
Success 304
SuppressSecurityChecks 285, 289, 292, 316
Symbols 67
System.Runtime.Serialization 420, 475, 493
System.Runtime.Serialization.Json 493
System.Web 471
System.Web.Extensions 404
System.Web.UI 404
- T -Tables 67
TagKey 404
Tags 265, 498
Take() 332
Taxa 500, 503
Taxon 500, 506
TaxonId 504
TaxonName 502
Taxonomy 498, 500, 503
TaxonomyId 504
TaxonomyManager 501, 506, 509
TaxonomyPropertyDescriptor 506
Telerik OpenAccess 420
Telerik.Sitefinity 382, 402
Telerik.Sitefinity.Abstractions 285
Telerik.Sitefinity.Data.Metadata 432
Telerik.Sitefinity.Metadata.Model 432
Telerik.Sitefinity.Model 420, 432, 528
Telerik.Sitefinity.Modules.Forms.Web.UI.Fields
432
Telerik.Sitefinity.Security 432
Telerik.Sitefinity.Security.Model 292
Telerik.Sitefinity.Web.UI.ControlDesign 404
Telerik.Sitefinity.Web.UI.Fields 432
Telerik.Sitefinity.Web.UI.Fields.Enums 432
Telerik.Web.UI 429, 432
Telerik.Windows.Controls 422
Telerik.Windows.Controls.Navigation 422
Temp 291, 293
Template 246, 260, 263, 285
Template name 199, 202
Text box size 154
Textbox widget 154
Theme 246, 252, 256, 260
themes 221, 249
This is a hidden field 514
This user can access site backend 171
Thumbnail 119
Thumbnail strip 112
Thumbnails + Detail page 112, 123
Thumbnails + Overlay 112, 123
Title & Properties 51, 285
Title for Search Engines 44
Titles and dates 198, 199, 202
ToList() 332
Toolboxes 374, 376, 391
ToolboxesConfig.config 376
Total Map Points 191
Traffic origin 191
Transform the layout 239
Type() 524
TypeResolutionService 458
- U -UICulture 362, 363
UnauthorizedAccessException 306
Union() 502
Unknown 304
Unlock 78
Unpublish 136
Upload documents or other files 146
Sitefinity 5
© 2012 Falafel Software
Upload images 106
Upload new videos 123
UploadContent 327
UploadContent() 321, 322, 329
UriTemplate 466
Url name 133
Use limit 94
Use paging 94
Use template 210, 260, 263
Use the selected template as a default template...
218
Use your own .master file 260
User 171, 292, 307
User Control 369, 410
User Controls 371, 408
UserAlreadyLoggedIn 304
UserLimitReached 304
UserLoggedFromDifferentComputer 304
UserLoggedFromDifferentIp 304
UserLoggedOff 304
UserLoggingReason 304
UserManager 292, 307
UserNotFound 304
UserRevoked 304
- V -val() 400
Video gallery 123
View a page 173
Visual Studio 274, 278
- W -Web Form 274
Web User Control 372, 384
WebClient 322, 327
WebException 478
WebRequest 397
WebResource 397, 399
WebResource() 407
Where() 276, 293, 294, 332, 335
Which image to upload 215
Who can View a page? 173
widget templates 198, 204, 249
workflow 178
WorkWith() 315, 319, 327, 331, 332
'WRAP 473
Wrapper 62
Write CSS 222
- X -XAML 422
X-Authentication-Error 478
XDocument 324, 325
XDocument.Load() 325
XNamespace 325