Professional Documents
Culture Documents
Sitefinity 5 Nuts & Bolts PDF
Sitefinity 5 Nuts & Bolts PDF
Welcome to Sitefinity 5 We hope you enjoy the book as much as we, at Falafel Software, enjoyed creating it.
Sitefinity 5
2012 Falafel Software
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
Publisher Falafel Software Inc. Falafel Sitefinity Team Noel Rice Basem Emara Alain "Lino" Tadros Bary Nusz Gary Campbell Scott Frolich Matt Kurvin Technical Editors Basem Emara George Saddeh Alain "Lino" Tadros Cover Designer Matt Kurvin Team Coordinator Alain "Lino" Tadros Administration Sean Samuel Production Falafel Software Inc.
Special 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
Sitefinity 5
Table of Contents
1 Introduction 2
What .......................................................................................... You Need to Know Before Reading This Courseware 2 What Do You Need to Have Before Reading This Courseware .......................................................................................... 3 How .......................................................................................... This Courseware is Organized 4 What .......................................................................................... is a CMS and why do you need one? 7 Sitefinity .......................................................................................... 3.7 vs. 5.x 8
10
Objectives .......................................................................................... 10 Installing .......................................................................................... Sitefinity 5 11 Installing .......................................................................................... the SDK 14 Summary .......................................................................................... 17
3 Getting Started
19
Objectives .......................................................................................... 19 Sitefinity .......................................................................................... Project Manager 20 Dashboard .......................................................................................... 22 About .......................................................................................... Pages and Content 23 Front .......................................................................................... End vs. Back End 24 Creating .......................................................................................... Projects 25 Summary .......................................................................................... 40
4 Pages
42
Contents
Editing .......................................................................................... the Page 51 Tour .......................................................................................... of Page Administration 77 Summary .......................................................................................... 82
5 Content
84
Objectives .......................................................................................... 85 Tour .......................................................................................... of the Content Menu 86 Content .......................................................................................... Block 87 News .......................................................................................... 94 .......................................................................................... Events 101 .......................................................................................... Images and Albums 106 .......................................................................................... Video 118 .......................................................................................... Lists 127 .......................................................................................... Blogs 132 .......................................................................................... Documents 145 .......................................................................................... Forms 153 .......................................................................................... Social Sharing Options 162 .......................................................................................... Summary 164
6 Permissions
166
.......................................................................................... Objectives 167 .......................................................................................... Built-In Roles 168 .......................................................................................... Creating a Role 169 .......................................................................................... Creating a User 171 .......................................................................................... Test the New User 173 .......................................................................................... Summary 174
7 Workflow
176
Sitefinity 5
8 Analytics
186
.......................................................................................... Objectives 187 .......................................................................................... Setup 188 .......................................................................................... Using Analytics in the Administrator 191 .......................................................................................... Summary 194
9 Widget Templates
196
.......................................................................................... Objectives 197 .......................................................................................... Accessing Widget Templates 198 .......................................................................................... Changing a Template 199 .......................................................................................... Creating a New Template 202 .......................................................................................... Managing Widget Templates 204 .......................................................................................... Summary 205
10 Page Templates
207
.......................................................................................... Objectives 208 .......................................................................................... Creating and Using a Page Template 209 .......................................................................................... Stying 221 .......................................................................................... Debugging CSS 225 .......................................................................................... Summary 229
231
.......................................................................................... Objectives 232 .......................................................................................... Creating Rules 233 .......................................................................................... Previewing the Results 236 .......................................................................................... Device Characteristics 237 .......................................................................................... Adding New Behaviors 239
2012 Falafel Software
Contents
244
.......................................................................................... Objectives 245 .......................................................................................... Masterpage Overview 246 .......................................................................................... Using a MasterPage from the Marketplace 247 .......................................................................................... Editing 3rd Party Templates 256 .......................................................................................... Master Page Surgery Tips 265 .......................................................................................... Summary 269
13 Developing in Sitefinity
271
.......................................................................................... Objectives 272 .......................................................................................... What Flavor API? 273 .......................................................................................... Getting Started with Sitefinity Development 274 .......................................................................................... Sitefinity Projects in Visual Studio 278 .......................................................................................... Developing with Thunder 280 .......................................................................................... Summary 281
283
.......................................................................................... Objectives 284 .......................................................................................... Working with Pages 285 .......................................................................................... Working with Content Items 291 .......................................................................................... Publishing 297 .......................................................................................... Summary 298
300
.......................................................................................... Objectives 301 .......................................................................................... Claims vs Forms Authentication 302 .......................................................................................... Setting the Authentication Type 303 .......................................................................................... Login Programmatically 304
2012 Falafel Software
Sitefinity 5
.......................................................................................... Logout Programmatically 306 .......................................................................................... Create a User 307 .......................................................................................... Roles and Permissions 308 .......................................................................................... Summary 311
313
.......................................................................................... Objectives 314 .......................................................................................... Fluent API Facades 315 .......................................................................................... Working with Pages 316 .......................................................................................... Working with Content Items 319 .......................................................................................... Summary 337
339
.......................................................................................... Objectives 340 .......................................................................................... Getting a List of All Forms 341 .......................................................................................... Retrieve a Single Form 343 .......................................................................................... Retrieving Form Entry Values 344 .......................................................................................... Summary 349
18 Localization
351
.......................................................................................... Objectives 352 .......................................................................................... Localizing Front End Pages 353 .......................................................................................... User Language Selection 360 .......................................................................................... Localizing In Code 362 .......................................................................................... Localizable Strings 363 .......................................................................................... Localizing Back End Pages 364 .......................................................................................... Summary 367
369
Contents
.......................................................................................... User Controls 371 .......................................................................................... Custom Controls 382 .......................................................................................... Custom Control Designers 394 .......................................................................................... Using RadControls for ASP.NET AJAX with Sitefinity 408 .......................................................................................... Silverlight Controls 410 .......................................................................................... Communication between Custom Control and Silverlight 418 .......................................................................................... Custom Form Controls 427 .......................................................................................... Summary 439
441
.......................................................................................... Objectives 442 .......................................................................................... Create a Custom Module 443 .......................................................................................... Add Module Content 450 .......................................................................................... Customizing the Backend Grid 452 .......................................................................................... Add the Module to a Page 455 .......................................................................................... Working with the Module in Code 458 .......................................................................................... Summary 462
464
.......................................................................................... Objectives 465 .......................................................................................... Getting Available Services and Methods 466 .......................................................................................... Anatomy of a Web Service Call 470 .......................................................................................... Using Claims Authentication 471 .......................................................................................... Using Forms Authentication 486 .......................................................................................... What Next? 495 .......................................................................................... Summary 496
498
10
Sitefinity 5
.......................................................................................... Getting Started 501 .......................................................................................... Listing Taxonomies 502 .......................................................................................... Listing Taxa 503 .......................................................................................... Finding Frequently Used Categories and Tags 504 .......................................................................................... Get Items by Category or Tag 506 .......................................................................................... Adding Categories and Tags 509 .......................................................................................... Summary 510
23 Dynamic Data
512
.......................................................................................... Objectives 513 .......................................................................................... Adding Custom Fields 514 .......................................................................................... Using the DynamicData Facade 520 .......................................................................................... Programmatically Listing Types 521 .......................................................................................... Programmatically Listing Fields 523 .......................................................................................... Reading and Writing Custom Field Values 528 .......................................................................................... Summary 529
24 About Falafel
531
Index
537
1
Introduction
Sitefinity 5
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 site
Introduction
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/a sp-net-cms-fea tures/systems-requirements.a spx NOTE 1: You ca n run Sitefinity with Windows XP, only when using the Sitefinity integra ted web server. NOTE 2: It is not required to use IIS. If you wa nt to use IIS, you must configure it for Silverlight Applica tion. For more informa tion, see Configuring IIS for Silverlight a pplica tion below. NOTE 3: If you a re using Windows XP or Windows Server 2003 ma ke sure you ha ve upda ted your Windows Insta ller to version 4.5.
Sitefinity 5
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
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.
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.
Sitefinity 5
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.
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
Sitefinity 5
2
Setting Up Your Environment
10
Sitefinity 5
11
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.
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.
12
Sitefinity 5
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.
13
5. The Sitefinity Project Manager provides quick access to creating and configuring Sitefinity projects.
14
Sitefinity 5
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.
15
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.
16
Sitefinity 5
5. The SDK Browser includes a rich set of resources for getting started with Sitefinity, starter kits, code samples, widgets, blogs, documentation and links.
17
Summary
In this Chapter you learned how to install Sitefinity.
3
Getting Started
Getting Started
19
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.
20
Sitefinity 5
Getting Started
21
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.
22
Sitefinity 5
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.
Getting Started
23
24
Sitefinity 5
Getting Started
25
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.
26
Sitefinity 5
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.
2. The Create New Project Wizard displays. Enter the Project Name "CarConduit". Click the Next button to continue.
Getting Started
27
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.
Notes
If you have already created a project, then you will be able to select from existing licenses.
28
Sitefinity 5
4. Select the Sitefinity edition that fits the requirements of your project.
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
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.
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.
30
Sitefinity 5
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.
Getting Started
31
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.
32
Sitefinity 5
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.
Getting Started
33
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.
34
Sitefinity 5
Creating a Page Now you will create a "Welcome" page for your website. 1. From the administration site, click the Pages menu option.
Getting Started
35
3. The Create a Page entry form will display. Enter "Welcome" in the Name field.
4. Scroll further down the form and enter "Welcome to CarConduit" in the Title for Search Engines field.
36
Sitefinity 5
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.
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.
Getting Started
37
8. In the Edit dialog that displays, enter the text "Welcome to CarConduit!". Click the Save button to close the Edit dialog.
38
Sitefinity 5
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.
10.In Pages administration locate the Welcome page in the list and click the View link.
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.
Getting Started
39
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.
2. Notice that the "Home" icon appears in the icon next to the page name.
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.
40
Sitefinity 5
Summary
In this Chapter you created a simple Sitefinity website. The website contains a single "Welcome" page populated with text.
4
Pages
42
Sitefinity 5
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
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.
44
Sitefinity 5
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
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.
46
Sitefinity 5
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.
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
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.
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.
48
Sitefinity 5
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.
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
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.
50
Sitefinity 5
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.
8) Click the Create and go to add content button to create and edit the page.
Pages
51
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.
52
Sitefinity 5
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.
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.
Pages
53
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:info@carconduit.com">info@carconduit.com</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 .
54
Sitefinity 5
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
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.
Notes
56
Sitefinity 5
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 "info@carconduit.com", 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:".
Pages
57
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.
14)Click the Save button to close the editor. The content block should now look something like the screenshot below.
58
Sitefinity 5
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.
Pages
59
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.
60
Sitefinity 5
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.
18)Now the image shows at a reasonable size and is proportionate to the content block.
Pages
61
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.
62
Sitefinity 5
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.
3) From the right side, titled Drag layout elements, drag the 25% + 75% layout element into the top box.
Pages
63
4) Now the top box is sub-divided into two areas, one with 25% width and the other with 75%. Click the Edit button.
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%.
64
Sitefinity 5
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%".
Pages
65
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.
66
Sitefinity 5
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.
Pages
67
68
Sitefinity 5
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.
Pages
69
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.
70
Sitefinity 5
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.
Pages
71
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.
72
Sitefinity 5
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.
Pages
73
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.
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.
74
Sitefinity 5
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.
Pages
75
The Media Manager button displays a dialog that works exactly like Insert an Image except that the Insert a Video dialog accepts *.wmv files.
76
Sitefinity 5
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 .
Pages
77
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.
78
Sitefinity 5
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
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.
80
Sitefinity 5
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
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.
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.
82
Sitefinity 5
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.
5
Content
84
Sitefinity 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
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.
86
Sitefinity 5
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.
Content
87
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.
88
Sitefinity 5
3. Enter a Title. Below the title area, enter any text or HTML content in the HTML Editor.
Content
89
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.
Q & A...
Question : Do categories have to do with Search Engine Optimization (SEO)? Answ er : 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.
90
Sitefinity 5
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.
Content
91
10.In the Edit dialog that displays, click the Select from existing shared content button.
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.
92
Sitefinity 5
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
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.
94
Sitefinity 5
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.
Content
95
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.
96
Sitefinity 5
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.
Content
97
11)Click the List Settings option to configure how multiple news items will be displayed by the News widget on a page. 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.
98
Sitefinity 5
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.
Content
99
Q & A...
Question : What does the Advanced button do? Answ er : 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.
100
Sitefinity 5
14)Click the Publish button for the "Welcome" page. 15)Click the View button for the "Welcome" page.
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.
Content
101
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.
102
Sitefinity 5
5) In the Location section, enter the event Street, City , Country and State.
6) In the Contact information section, enter details for the person acting as the main contact for the event.
Content
103
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.
104
Sitefinity 5
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.
11)Click the Publish button for the "Welcome" page. 12)Click the View button for the "Welcome" page.
Content
105
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.
106
Sitefinity 5
4. In the Default image size section, click the Resize images... option and select "Small: 240 px width" from the drop down list.
Content
107
Notes
If you choose to "Resize images...", you can select from the predefined dimensions Thumbnail , Small , Medium, Large, or Extra Large.
108
Sitefinity 5
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 .
Content
109
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.
110
Sitefinity 5
9. In the Windows Open file dialog that displays, navigate to image file location. Select and open one or more image files.
10.In the Upload images Page, open the select an album drop down, select the new "Cars" 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.
Content
111
112
Sitefinity 5
Content
113
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.
7) The Images Gallery dialog should now look like the screenshot below.
114
Sitefinity 5
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.
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
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.
116
Sitefinity 5
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.
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
10)Try each of the gallery types, save your settings for the Image Gallery, Publish the page and view the results.
118
Sitefinity 5
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
120
Sitefinity 5
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.
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.
Content
121
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.
122
Sitefinity 5
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.
12)Click the Publish button for the video. The published video now displays the new thumbnail.
Content
123
124
Sitefinity 5
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.
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
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.
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.
126
Sitefinity 5
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.
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? Answ er: 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
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".
128
Sitefinity 5
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.
Content
129
6) Enter the Title as "High", and content in the HTML editor as "High Priority". Click the Publish button.
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.
130
Sitefinity 5
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.
Content
131
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.
132
Sitefinity 5
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
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.
134
Sitefinity 5
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. 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
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.
7) Click the Create this blog button. This will bring you to the Blog Posts page.
136
Sitefinity 5
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.
2) In the Create a post page, enter a Title, then text to the HTML editor.
Content
137
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.
138
Sitefinity 5
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.
Content
139
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.
6) We will want to see this blog immediately, so click Publish from the Actions menu. 7) Click the All blogs link.
140
Sitefinity 5
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.
Content
141
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.
142
Sitefinity 5
Content
143
5) Click the Select a blog button. Select the blog you created earlier and then click the Done selecting button.
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".
144
Sitefinity 5
Content
145
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.
146
Sitefinity 5
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.
Content
147
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.
148
Sitefinity 5
12)Click the View all items button. Sitefinity detects the type of files that are uploaded and places the matching icon.
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.
Content
149
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 .
150
Sitefinity 5
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.
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
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.
152
Sitefinity 5
11)Click the Save button to close the Download list dialog. 12)Publish and view the "Welcome" page.
Content
153
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.
154
Sitefinity 5
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.
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.
Content
155
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.
156
Sitefinity 5
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.
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
Click the Save button. The Multiple choice widget on the page should now look something like the example below.
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.
158
Sitefinity 5
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.
Content
159
160
Sitefinity 5
Viewing Reponses
1) Click the administration menu Content > Forms. Notice the link to 1 responses.
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.
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.
Content
161
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.
162
Sitefinity 5
The screenshot below shows a Content Block with the social share buttons included.
Content
163
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.
164
Sitefinity 5
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.
6
Permissions
166
Sitefinity 5
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
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.
168
Sitefinity 5
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.
Permissions
169
Creating a Role
1. Click the Create a role button. In the Role text box that appears, enter "Bloggers" and click the Create button.
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.
170
Sitefinity 5
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.
7. Click the Done button to close the dialog. 8. Click the Back to all items link.
Permissions
171
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.
172
Sitefinity 5
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.
5. Click the Create this user button. 6. The new user shows up in the Users list.
Permissions
173
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.
174
Sitefinity 5
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.
7
Workflow
176
Sitefinity 5
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
Objectives
In this chapter you'll learn how to define and test a workflow.
178
Sitefinity 5
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.
Workflow
179
3) Now the Properties page of the workflow definition displays. Enter a Name for the workflow.
180
Sitefinity 5
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.
Workflow
181
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.
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.
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.
182
Sitefinity 5
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
184
Sitefinity 5
Summary
In this chapter you learned how to define and test a workflow.
8
Analytics
186
Sitefinity 5
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
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.
188
Sitefinity 5
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.
2) Enter your Google Analytics user name and password and click the Get Analytics Accounts button.
Analytics
189
3) Select an available Google Analytics account from the drop down list and then click the Save Settings button.
4) Click the Copy in clipboard button to get the JavaScript to be used in the Google Analytics widget.
190
Sitefinity 5
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.
Analytics
191
Move the mouse cursor over the data points to get fly-over tooltips with more detail information.
192
Sitefinity 5
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
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.
194
Sitefinity 5
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.
9
Widget Templates
196
Sitefinity 5
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
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.
198
Sitefinity 5
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.
Widget Templates
199
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.
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.
200
Sitefinity 5
The Template name not displayed on the page, but used by Sitefinity to identify the template.
6) Place your cursor in the HTML just below the "PublicationDate" field, on line 23 shown in the screenshot below.
Widget Templates
201
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.
8) Click the Save changes button. 9) Click the Save button. 10)Now the "Tags" are listed below the "Title" and "Publication date'.
202
Sitefinity 5
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.
Widget Templates
203
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.
16)Click the Save button. 17)The widget with the new template shows the modified date.
204
Sitefinity 5
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.
Widget Templates
205
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.
10
Page Templates
Page Templates
207
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.
208
Sitefinity 5
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
210
Sitefinity 5
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
Select the Use template option. Click the Select another Template button to choose the "1 Column, Header, Footer" template.
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.
212
Sitefinity 5
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.
Page Templates
213
4) Now the layout should look something like the screenshot below, where the top row is divided into proportions of 25% and 75%.
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.
214
Sitefinity 5
6) Now the layout has a top row of 25% x 75% followed by three full rows.
Page Templates
215
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.
216
Sitefinity 5
5) Open the Drag widgets Login section and drag the Login name widget to the top row, right side.
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.
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
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.
218
Sitefinity 5
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.
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
3) Select the new custom template. Notice the warning that the template change may break the existing layout for the page.
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.
Notes
You can return to an earlier version of the page, before the template was changed, using the Actions menu Revision History item.
220
Sitefinity 5
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.
Page Templates
221
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.
222
Sitefinity 5
Page Templates
223
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.
224
Sitefinity 5
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".
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.
Page Templates
225
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.
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.
226
Sitefinity 5
4) The HTML tab highlights parts of the web page as your mouse hovers above the HTML elements.
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.
Page Templates
227
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.
Tip!
When you pass the mouse over a color or image path, Firebug automatically displays the color or image.
228
Sitefinity 5
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.
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
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.
11
Responsive Web Design
231
11
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.
232
Sitefinity 5
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 handheld 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.
233
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.
234
Sitefinity 5
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.
4. Select device characteristics using the presets from the drop down list. For this example step, choose the "Smartphones" option.
5. Leave the defaults for Apply behavior to... and Specific CSS file options.
235
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".
7. Leave the This group of rules is active checkbox selected and click the Done button.
236
Sitefinity 5
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.
237
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.
238
Sitefinity 5
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.
239
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.
240
Sitefinity 5
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.
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.
241
242
Sitefinity 5
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 handheld 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.
12
Working with Master Pages
244
Sitefinity 5
12
245
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-anddice" third party templates to integrate them in your web site.
246
Sitefinity 5
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.
247
248
Sitefinity 5
4) Save the "SolarFlare.zip" file to a location on your local drive. 5) Unzip the "SolarFlare.zip" file.
249
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".
250
Sitefinity 5
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.
Gotcha!
Make sure you're in the \App_Data\Sitefinity folder, not the \Sitefinity folder in the root of the project.
251
252
Sitefinity 5
9) Back in the Create a template screen, click the Create and go to add content button.
253
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.
254
Sitefinity 5
6) Click the Create and go to add content button. 7) The SolarFlare graphics should now display in the page.
255
256
Sitefinity 5
257
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.
258
Sitefinity 5
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>
259
Gotcha!
260
Sitefinity 5
8) Click the Use Selected button to close the dialog and return to the Create a template page.
261
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.
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.
262
Sitefinity 5
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.
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.
14)Click the Publish button to make the template available for use in pages.
263
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> .
264
Sitefinity 5
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.
265
266
Sitefinity 5
<!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>
267
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.
268
Sitefinity 5
Tip!
The titles in the footer for "Testimonials", "Recent Comments", etc., have been hardcoded 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.
269
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-anddice" third party templates to integrate them in your web site.
13
Developing in Sitefinity
Developing in Sitefinity
271
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.
272
Sitefinity 5
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
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
274
Sitefinity 5
Developing in Sitefinity
275
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".
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.
276
Sitefinity 5
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.
Developing in Sitefinity
277
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.
278
Sitefinity 5
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.
Developing in Sitefinity
279
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.
280
Sitefinity 5
Developing in Sitefinity
281
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.
14
Using the Sitefinity API
283
14
284
Sitefinity 5
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.
285
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.
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.
286
Sitefinity 5
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 node PageNode 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(); // pub lish through the workflow WorkflowManager.MessageWorkflow(pageNode.Id, typeof(PageNode), null, "Publish", false, new Dictionary<string, string>());
287
6) Run the application, then navigate to the Sitefinity Administrator Pages to view 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.
288
Sitefinity 5
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.
289
290
Sitefinity 5
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.
291
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-anddicing" 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.
292
Sitefinity 5
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 properties item.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" changes contentManager.RecompileItemUrls<ContentItem>(item); // has b een in draft till now, so pub lish contentManager.Lifecycle.Publish(item); // commit to datab ase contentManager.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 Ow ner property.
293
294
Sitefinity 5
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();
295
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();
296
Sitefinity 5
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?
297
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);
298
Sitefinity 5
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.
15
Authentication and Security
300
Sitefinity 5
15
301
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.
302
Sitefinity 5
303
For all projects going forward, Claims Authentication is the stronger choice.
304
Sitefinity 5
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 Succe ss Use rLimitRe ache d Description Use r was succe ssfully re giste re d as logge d in The limit of maximum simultane ous logge d in use rs is re ache d Use r not found in any provide r Use r is alre ady logge d in from a diffe re nt IP addre ss Indicate s that the use r logical se ssion has e xpire d Use r has the authe ntication cookie but is not logge d in the database or use r is alre ady logge d out. More than one use r trying to login from the same IP but from diffe re nt compute rs. Invalid use rname or password spe cifie d.
Use rNotFound Use rLogge dFromDiffe re ntIp Se ssionExpire d Use rLogge dOff
Unknown
305
Description Use r is not administrator to logout othe r use rs Use r alre ady is logge d in. We ne e d to ask the use r to logout or to logout some one e lse . Use r was re voke d: the use r was de le te d or use r rights and role me mbe rship was change d.
306
Sitefinity 5
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.
307
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 = "ayamda@mydomain.net"; 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 "ayamda@mydomain.net", // 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(); }
308
Sitefinity 5
Get a specific Role, e.g. "BackendUsers" or "Authors". Add the User to a Role. Save changes.
309
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", "ayamda@mydomain.net", "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 b uilt in roles RoleManager roleManager = RoleManager.GetManager(SecurityManager.ApplicationRolesProviderName); // retrieve the "BackendUsers" role Role backendUserRole = roleManager.GetRoles() .Where(r => r.Name.Equals(SecurityManager.BackendUsersRoleName)))) .Single(); // retrieve the "Authors" role Role authorRole = roleManager.GetRoles() .Where(r => r.Name.Equals("Authors")) .Single(); // add the user to b oth roles roleManager.AddUserToRole(user, backendUserRole); roleManager.AddUserToRole(user, authorRole); // save the new role settings roleManager.SaveChanges();
310
Sitefinity 5
3) Run the application, then find the user in the Sitefinity Administration > Users list. Notice that the "BackendUsers" and "Authors" roles have been added.
311
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.
16
Using the Fluent API
313
16
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.
314
Sitefinity 5
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.
315
316
Sitefinity 5
2) Run the application, then navigate to the Sitefinity Administrator Pages to view the new page.
317
318
Sitefinity 5
319
320
Sitefinity 5
The Title and Properties for the news item reflect the property settings set in the Do() method.
321
322
Sitefinity 5
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.
323
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 alb um Album album = fluent.Albums() .Where(a => a.Title == "Default Library") .Get() .SingleOrDefault(); // download the image b yte stream WebClient webClient = new WebClient(); byte[] bytes = webClient.DownloadData(url); Stream stream = new MemoryStream(bytes); // upload the b ytes to the alb um 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.
324
Sitefinity 5
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.
325
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; }
326
Sitefinity 5
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 alb um with a given title Album album = App.WorkWith() .Albums() .Where(a => a.Title.Equals(title)) .Get() .SingleOrDefault(); // if the alb um 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.
327
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 Web Client 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); } }
328
Sitefinity 5
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.
329
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 stream using (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();
330
Sitefinity 5
The uploaded documents are displayed in the library with the appropriate icons for each file type.
331
332
Sitefinity 5
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 />"); }
333
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<MyNew sItem> new s in the example above could be stated as var new s. The longer syntax is used here for learning purposes so you can easily see what kind of objects we're working with.
334
Sitefinity 5
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 });
335
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 DropDow nList 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.
336
Sitefinity 5
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.
337
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.
17
Working with Forms
339
17
340
Sitefinity 5
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.
341
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; } } }
342
Sitefinity 5
The screenshot below shows the titles for each form in a RadComboBox.
343
344
Sitefinity 5
Running in the browser, the ListBox displays the values for each entry.
345
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.
346
Sitefinity 5
When the returned columns are bound to a grid, the result looks like the screenshot below.
347
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.
348
Sitefinity 5
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" checkb ox 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(); }
349
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.
18
Localization
Localization
351
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.
352
Sitefinity 5
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
5) Click the Done button. Now the new "Spanish" language entry shows up under the default "English" entry.
354
Sitefinity 5
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.
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
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.
356
Sitefinity 5
11)Create a page (ES) displays so you can supply a new page Name, URL and Title in the appropriate language.
Tip!
To test your pages without performing a production level translation, use Google's translation service at http://translate.google.com.
Localization
357
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.
358
Sitefinity 5
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.
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
19)View the page. Notice the Url in the address bar uses the culture code "es". The translated
360
Sitefinity 5
Localization
361
5) Publish and view the page. Use the drop down language selection to show both translations of the page.
362
Sitefinity 5
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.
Localization
363
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.
364
Sitefinity 5
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.
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
Refresh the page to see all the resourced items in the system display in the corresponding language.
366
Sitefinity 5
Click on an item in the list to edit the "Invariant" (default) language, and for each language you have defined.
Localization
367
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.
19
Working with Widgets
369
19
370
Sitefinity 5
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.
371
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.
372
Sitefinity 5
373
4) Drag a Label control from the Toolbox to either the Design or Source view of the MyControl.ascx control.
5) Using the Properties pane, change the Label properties to the following: ID: "MyLabel" Text = "Hello Sitefinity!" 6) Build the project.
374
Sitefinity 5
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.
375
376
Sitefinity 5
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.
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"
377
378
Sitefinity 5
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.
379
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.
380
Sitefinity 5
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.
381
9) Notice the "My Properties" category has appeared with "MyProperty" underneath it. Enter some text into MyProperty and click the Save button.
382
Sitefinity 5
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.
Notes
As a convention, projects are often named akin to a namespace, in roughly the form shown below:
<Organization name>.<Functional category>.<specific control>
383
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.
384
Sitefinity 5
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".
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.
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.
385
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.
386
Sitefinity 5
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.
387
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; }
388
Sitefinity 5
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.
389
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? Answ er : 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; } }
390
Sitefinity 5
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:
391
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
392
Sitefinity 5
Name: "MyCustomControl" Title: "My Custom Control" Description : "My Custom Control Description"
393
394
Sitefinity 5
395
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.
396
Sitefinity 5
397
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.
398
Sitefinity 5
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.
399
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 backgroundimage 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; }
400
Sitefinity 5
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 namespace Type.registerNamespace("MyOrganization.MyControls"); // create an instance of the designer class MyOrganization.MyControls.MyDesigner = function (element) { MyOrganization.MyControls.MyDesigner.initializeBase(this, [element]); } // add designer logic here --> // register the designer class MyOrganization.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 class MyOrganization.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 b utton applyChanges: function () { var controlData = this._propertyEditor.get_control(); controlData.MyCustomProperty = jQuery("#MessageText").val(); } }
401
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.
402
Sitefinity 5
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.
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.
403
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.
404
Sitefinity 5
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; }
405
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.
406
Sitefinity 5
5) When the designer dialog closes, the custom control should display the value entered in the designer.
407
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?
408
Sitefinity 5
409
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(); } }
410
Sitefinity 5
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 walkthrough, see the Communication between Custom Control and Silverlight example that displays Sitefinity information in a RadBook control.
411
412
Sitefinity 5
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.
413
4) In the "MainPage.xaml" editor, drag a Silverlight Button control from the Toolbox.
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.
7) Right click the new Click attribute and select Navigate to Event Handler from the context menu.
414
Sitefinity 5
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:
At this point you have a very simple Silverlight control hosted by the Silverlight application.
415
\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.
416
Sitefinity 5
<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") %>' />
417
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.
418
Sitefinity 5
419
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.
420
Sitefinity 5
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
421
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" />
422
Sitefinity 5
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.Window s.Controls and Telerik. Window s.Controls.Navigation assemblies.
423
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>
424
Sitefinity 5
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 }); }
425
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
426
Sitefinity 5
4) The Silverlight RadBook shows up in the Widget, complete with data that originated from the Sitefinity API.
427
428
Sitefinity 5
429
9. Add all references highlighted in the screenshot below. These references will be needed to create a custom form control.
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".
430
Sitefinity 5
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" />
431
CustomFormControls.NamedTextBox.initializeBase(this, [element]); } // set control properties here --> // register the control in the namespace CustomFormControls.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 properties CustomFormControls.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; } }
432
Sitefinity 5
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.
4) Add IFormFieldControl to the declaration, right-click "IFormFieldControl" and select Implement Interface > Implement Interface from the context menu.
433
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); } }
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.
434
Sitefinity 5
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(); }
435
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; }
436
Sitefinity 5
437
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 controls 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.
438
Sitefinity 5
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.
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.
439
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.
20
Working with Modules
441
20
442
Sitefinity 5
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.
443
3. Enter a Name and Description for the module as a whole and click the Continue button.
444
Sitefinity 5
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.
445
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.
446
Sitefinity 5
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.
447
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.
448
Sitefinity 5
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.
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 .
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.
449
The Drag widgets list will include an icon that represents your module data. Drag the widget to the page to present the new data.
450
Sitefinity 5
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.
451
3. Enter the fields you defined when creating the module. When complete, click the Publish button.
4. After adding several entries, you can see the quotations column and stock columns "Author" and "Publication Date" that come along with all content.
452
Sitefinity 5
453
5. The "Author" column can be removed, so click the "x" icon to delete it.
6. Drag the columns from your module to the right end of the grid and drop them there.
454
Sitefinity 5
7. The table should now look something like the screenshot below. Click the Save Changes button.
8. From the menu select Content > [your module]. The grid now shows the other columns defined in your module.
455
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.
456
Sitefinity 5
3. The layout should be changed to show the quote source author instead of the published date. Click the Quotations widget Edit button.
4. Click the List Settings link. 5. In the List template drop down, select "List of quotations"
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.
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.
457
10.Click the "Source" item. The How to insert... dialog should display.
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.
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.
458
Sitefinity 5
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.
459
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 b e actually persisted to data store dynamicModuleManager.SaveChanges(); }
460
Sitefinity 5
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 crocodilehoping 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
461
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(); } }
462
Sitefinity 5
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.
21
Sitefinity Web Services
464
Sitefinity 5
21
465
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.
466
Sitefinity 5
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.
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.
467
4) Expand the Security folder. Inside are "svc" files representing services for MembershipSettings, Permissions, Roles and Users.
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.
468
Sitefinity 5
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.
469
470
Sitefinity 5
471
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.
472
Sitefinity 5
473
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 =
474
Sitefinity 5
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; } }
475
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", ...
476
Sitefinity 5
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", }, }, ], }
477
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); }
478
Sitefinity 5
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); } }
479
Walk-Through
This walk-through will demonstrate using Claims Authorization to login, call a Sitefinity REST API and log out.
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; } }
480
Sitefinity 5
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;
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; }
481
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(); } }
482
Sitefinity 5
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; }
483
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:
484
Sitefinity 5
Coding the Windows Form 1. Add a private member to represent the Claims object.
private Claims _claims;
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.
485
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.
486
Sitefinity 5
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 request string url = String.Concat(sitefinityHost, usersServiceUrl, "Authenticate"); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/json";
487
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 request request.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); }
488
Sitefinity 5
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 response using (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(); }
489
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 }
490
Sitefinity 5
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.
491
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 w ebMethod ("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(); } } }
492
Sitefinity 5
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); }
493
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); }; }
494
Sitefinity 5
7) Run the application and Login. Click the "List Pages" button. The pages in the site should be displayed in the list box.
495
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.
496
Sitefinity 5
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.
22
Content Classification - Taxonomy
498
Sitefinity 5
22
499
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.
500
Sitefinity 5
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.
501
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>)
502
Sitefinity 5
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);
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.
503
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.
504
Sitefinity 5
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.
505
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(); }
506
Sitefinity 5
507
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.
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.
508
Sitefinity 5
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.
509
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-todiagnose "Null reference object" exception.
510
Sitefinity 5
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.
23
Dynamic Data
512
Sitefinity 5
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 codebehind or referencing libraries.
Dynamic Data
513
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.
514
Sitefinity 5
Notes
This link will only show when you have at least one news item created.
Dynamic Data
515
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.
516
Sitefinity 5
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.
Dynamic Data
517
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.
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.
518
Sitefinity 5
Dynamic Data
519
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.
520
Sitefinity 5
Dynamic Data
521
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.
522
Sitefinity 5
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
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.
524
Sitefinity 5
Dynamic Data
525
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.
526
Sitefinity 5
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 b ack 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
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".
528
Sitefinity 5
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
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.
24
About Falafel
About Falafel
531
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
532
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
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.
534
Sitefinity 5
SiteBoard
SiteBoard is the Sitefinity administrators 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
Other Resources
Go to http://blog.falafel.com/ for in-depth blogs on CMS, Silverlight, Mobile, Telerik controls and technology issues of the day.
536
Sitefinity 5
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-GOTFALAFEL (1- 888-468-3252).
537
Index
537
Index
-..DynamicData() 523
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
-BBackend 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
-Aaccess_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
2012 Falafel Software
-CCascading 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
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
-Ddashboard 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
2012 Falafel Software
539
Index
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
-EEdit 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
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
-GGenerate 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
-FFieldControl 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
2012 Falafel Software
Sitefinity 5
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
-HHashTable 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
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
-JJavaScript 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
-LLabel 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
2012 Falafel Software
-IIEnumerable 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
541
Index
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
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
-OOne 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
-MMake 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
-Ppage 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
154
Sitefinity 5
Predefined value 514 PreRender 347 Properties.AssemblyInfo.cs 397 PublicationDate 319 Publish 79 Publish() 291, 292, 316, 322, 327
Roles 168 RSS 132, 141, 324 RSS feed 141 RSS or Atom to generate rules 233
133
-RRadBook 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
-SSamsung 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
2012 Falafel Software
543
Index
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
-TTables 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
2012 Falafel Software
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
-UUICulture 362, 363 UnauthorizedAccessException 306 Union() 502 Unknown 304 Unlock 78 Unpublish 136 Upload documents or other files 146
Sitefinity 5
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
-XXAML 422 X-Authentication-Error 478 XDocument 324, 325 XDocument.Load() 325 XNamespace 325
-Vval() 400 Video gallery View a page Visual Studio 123 173 274, 278
-WWeb 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
2012 Falafel Software