Welcome to the Sitefinity 13.2 training course! PLEASE DOWNLOAD: https://github.com/Sitefinity/Telerik.Sitefinity.Samples.Quantum https://sitefinitystore.blob.core.windows.net/files/Telerik.Sitefinity.Samples.Quantum/QuantumDB_v_132.zip **Terminology** Page Page Template Page Editor -Zone editor -Toolbox Widgets -Content Widget -Grid Widget ----------------------- **People who have VS, SQL Server and Sitefinity** Abdullah S Aljaiban Doha A Alawdah Ruwaida I Mirdad Abdullah M Mogren Abdulrahman F Alloaihan Khalil I Shehab Maha R Onaizi Riaz Ebrahim Pagarkar Sahar S Khogeer Ghada S Sundbul **People who don't have development environment locally** Monirah M Aldraiweesh Maha A Almaneea Mark Jamieson C Leonardo Fatima Althuwaiqeb Alaa Garni ---------- DRY principle Do Not Repeat Yourself principle Home Page -1.1. Footer with breadcrumbs Page Template -1.2. Header and footer Page Template -1.3. Header Page Template -1.4. Base Page Template -........ i.e. the same as inheritance in C# ---------- http://23.100.229.188:8088 http://23.100.229.188:8088/Sitefinity U1: user1@admin.com - Monirah M Aldraiweesh U2: user2@admin.com - Mark Jamieson C Leonardo U3: user3@admin.com - Maha A Almaneea U4: user4@admin.com - Fatima Althuwaiqeb U5: user5@admin.com - Alaa Garni P: admin@2 NuGet package sources ----------- Nuget Office https://api.nuget.org/v3/index.json Sitefinity Nuget https://nuget.sitefinity.com/nuget ----- https://dotnet.microsoft.com/download/dotnet-framework/thank-you/net48-developer-pack-offline-installer --- https://drive.google.com/file/d/1NwHBSsp-VXpKRjn5fdKwe9IDTimrgiAP/view?usp=sharing ------ "https://api.spacexdata.com/v3/launches/latest" ---------- using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; namespace SitefinityWebApp.Mvc.Models { public class FlightDataModel { public LaunchViewModel GetViewModel() { var getNextLaunchTask = System.Threading.Tasks.Task.Run(() => this.GetLaunchAsync()); getNextLaunchTask.Wait(); return getNextLaunchTask.Result; } private async System.Threading.Tasks.Task<LaunchViewModel> GetLaunchAsync() { using (var client = new System.Net.Http.HttpClient()) { var jsonString = await client.GetStringAsync("https://api.spacexdata.com/v3/launches/latest"); return Newtonsoft.Json.JsonConvert.DeserializeObject<LaunchViewModel>(jsonString); } } } } ----------- using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace SitefinityWebApp.Mvc.Models { public class LaunchViewModel { [Newtonsoft.Json.JsonProperty(PropertyName = "details")] public string Details { get; set; } [Newtonsoft.Json.JsonProperty(PropertyName = "mission_name")] public string MissionName { get; set; } } } ---------- using SitefinityWebApp.Mvc.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Telerik.Sitefinity.Mvc; namespace SitefinityWebApp.Mvc.Controllers { [ControllerToolboxItem(Name = "SpaceX_MVC", Title ="SpaceX", SectionName ="Aramco")] public class FlightDataController : Controller { public ActionResult Index() { var model = new FlightDataModel(); var viewModel = model.GetViewModel(); return View("Index", viewModel); } public string Message { get; set; } } } --------------- @model SitefinityWebApp.Mvc.Models.LaunchViewModel <div class="jumbotron"> <h1>@Model.MissionName</h1> <p>@Model.Details</p> </div>Welcome --------------- <p>@Model.Item.Fields.PublishedFirstIn</p> ------------- Helpulf materials: https://www.progress.com/documentation/sitefinity-cms/install-sitefinity https://www.progress.com/documentation/sitefinity-cms/configure-and-start-a-project https://www.progress.com/documentation/sitefinity-cms/licenses https://www.progress.com/documentation/sitefinity-cms/login https://www.progress.com/documentation/sitefinity-cms/dashboard-and-navigation --------------- REMEBER to change the name of the namespace!! using System; using System.Collections.Generic; using System.Linq;using SitefinityWebApp.Mvc.Models; using System; using System.Web; using Telerik.Microsoft.Practices.Unity; using Telerik.Sitefinity.Abstractions; using Telerik.Sitefinity.Data; using Telerik.Sitefinity.Frontend; using Telerik.Sitefinity.Frontend.Mvc.Infrastructure.Routing; using Telerik.Sitefinity.Frontend.News.Mvc.Models; using Telerik.Sitefinity.Mvc; using Telerik.Sitefinity.Services; namespace SitefinityWebApp { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { Bootstrapper.Initialized += Bootstrapper_Initialized; Bootstrapper.Bootstrapped += Bootstrapper_Bootstrapped; } private void Bootstrapper_Initialized(object sender, ExecutedEventArgs e) { if (e.CommandName == "Bootstrapped") { FrontendModule.Current.DependencyResolver.Rebind<INewsModel>().To<CategoryFilterNewsModel>(); } } protected void Bootstrapper_Bootstrapped(object sender, EventArgs e) { FeatherActionInvokerCustom.Register(); } } } using System.Web; namespace SitefinityWebApp.Controllers { public class TimeController: System.Web.Mvc.Controller { public string Index() { return DateTime.UtcNow.ToShortDateString(); } } } ----- REMEBER to change the name of the namespace!! using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.SessionState; namespace SitefinityWebApp { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { Telerik.Sitefinity.Abstractions. Bootstrapper.Bootstrapped += Bootstrapper_Bootstrapped; ; } private void Bootstrapper_Bootstrapped(object sender, EventArgs e) { System.Web.Mvc.RouteCollectionExtensions.MapRoute( System.Web.Routing.RouteTable.Routes, "AramcoClassic", "aramco/{controller}/{action}", new { controller = "Time", action = "Index" }); } protected void Session_Start(object sender, EventArgs e) { } protected void Application_BeginRequest(object sender, EventArgs e) { } protected void Application_AuthenticateRequest(object sender, EventArgs e) { } protected void Application_Error(object sender, EventArgs e) { } protected void Session_End(object sender, EventArgs e) { } protected void Application_End(object sender, EventArgs e) { } } } ---- using System; using System.Collections.Generic; using System.Linq; using System.Web; using Telerik.Sitefinity.Frontend.Mvc.Models; using Telerik.Sitefinity.Model; using Telerik.Sitefinity.News.Model; namespace SitefinityWebApp.Mvc.Models { public class AramcoNewsModel: Telerik.Sitefinity.Frontend.News.Mvc.Models.NewsModel { protected override IQueryable<IDataItem> GetItemsQuery() { var items = base.GetItemsQuery(); var baselineDate = DateTime.UtcNow.AddMinutes(-30); var filteredItems = items.Cast<NewsItem>() .Where(n => n.DateCreated > baselineDate); return filteredItems; } } } ------ using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; using System.Web.SessionState; namespace SitefinityWebApp { public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { Telerik.Sitefinity.Abstractions. Bootstrapper.Bootstrapped += Bootstrapper_Bootstrapped; ; } private void Bootstrapper_Bootstrapped(object sender, EventArgs e) { System.Web.Mvc.RouteCollectionExtensions.MapRoute( System.Web.Routing.RouteTable.Routes, "AramcoClassic", "aramco/{controller}/{action}", new { controller = "Time", action = "Index" }); Telerik.Sitefinity.Frontend. FrontendModule.Current. DependencyResolver. Rebind<Telerik.Sitefinity.Frontend.News.Mvc.Models.INewsModel>(). To<Mvc.Models.AramcoNewsModel>(); } protected void Session_Start(object sender, EventArgs e) { } protected void Application_BeginRequest(object sender, EventArgs e) { } protected void Application_AuthenticateRequest(object sender, EventArgs e) { } protected void Application_Error(object sender, EventArgs e) { } protected void Session_End(object sender, EventArgs e) { } protected void Application_End(object sender, EventArgs e) { } } } ----- |||IMPORTANT API!!! @Html.StyleSheet(Url.WidgetContent("assets/magnific/magnific-popup.css"), "head", true) @Html.Script(Url.WidgetContent("assets/magnific/jquery.magnific-popup.min.js"), "bottom", true) @Html.Script(Url.WidgetContent("Mvc/Scripts/ImageGallery/overlay-gallery.js"), "bottom", true) ----- FEATHER PROJECT https://github.com/Sitefinity/feather - This repository contains the core infrastructure related to the Feather project. https://github.com/Sitefinity/feather-widgets - This repository contains custom MVC widgets which are part of the Feather project. https://github.com/Sitefinity/feather-packages - This repository contains front-end packages for the Feather project. https://github.com/Sitefinity/mvc-samples - This repository contains code samples related to the Feather project. ------- using SitefinityWebApp.Mvc.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Telerik.Sitefinity.Mvc; namespace SitefinityWebApp.Mvc.Controllers { [ControllerToolboxItem(Name = "SpaceX_MVC", Title ="SpaceX", SectionName ="Aramco", CssClass = "sfMvcIcn")] public class FlightDataController : Controller { public ActionResult Index() { var model = new FlightDataModel(this.SpacexServiceUrl); var viewModel = model.GetViewModel(); if (string.IsNullOrWhiteSpace(this.ListTemplateName)) { this.ListTemplateName = "Index"; } var fullTemplateName = "List." + this.ListTemplateName; return View(fullTemplateName, viewModel); } public string Message { get; set; } public string SpacexServiceUrl { get; set; } public string ListTemplateName { get; set; } } } ------------------- @using Telerik.Sitefinity.Frontend.Mvc.Helpers; <uib-tabset class="nav-tabs-wrapper"> <uib-tab heading="SpaceX"> <span>Web service url</span> <input ng-model="properties.SpacexServiceUrl.PropertyValue" type="text" /> <div class="row"> <select id="flightDataTemplateName" ng-model="properties.ListTemplateName.PropertyValue" class="form-control"> @foreach (var viewName in Html.GetViewNames("FlightData", @"List\.(?<viewName>[\w\s]*)$")) { <option value="@viewName">@viewName.SplitCamelCase()</option> } </select> </div> </uib-tab> </uib-tabset> ------------- using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Web; namespace SitefinityWebApp.Mvc.Models { public class FlightDataModel { public FlightDataModel(string spacexServiceUrl) { this.spacexServiceUrl = spacexServiceUrl; } public LaunchViewModel GetViewModel() { var getNextLaunchTask = System.Threading.Tasks.Task.Run(() => this.GetLaunchAsync()); getNextLaunchTask.Wait(); return getNextLaunchTask.Result; } private async System.Threading.Tasks.Task<LaunchViewModel> GetLaunchAsync() { if (string.IsNullOrWhiteSpace(this.spacexServiceUrl)) { return new LaunchViewModel(); } else { using (var client = new System.Net.Http.HttpClient()) { var jsonString = await client.GetStringAsync(this.spacexServiceUrl); return Newtonsoft.Json.JsonConvert.DeserializeObject<LaunchViewModel>(jsonString); } } } private string spacexServiceUrl; } } ----------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Telerik.Sitefinity.Modules.News; using Telerik.Sitefinity.Mvc; namespace SitefinityWebApp.Mvc.Controllers { [ControllerToolboxItem(Name ="NewsCounter_MVC", Title ="News Counter", SectionName ="Aramco")] public class NewsCounterController : Controller { public string Index() { var nManager = NewsManager.GetManager(); var newsCount = nManager.GetNewsItems() .Where(n => n.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live) .Count(); return newsCount.ToString(); } } } ---------- public override ContentDetailsViewModel CreateDetailsViewModel(IDataItem item) { var nManager = NewsManager.GetManager(); using (ElevatedModeRegion elRegion = new ElevatedModeRegion(nManager)) { var newsItem = item as NewsItem; var hCount = newsItem.GetValue("HitsCount"); if (hCount == null) { hCount = 0; } var hitsCount = Convert.ToInt32(hCount); hitsCount += 1; newsItem.SetValue("HitsCount", hitsCount); nManager.SaveChanges(); } return base.CreateDetailsViewModel(item); } ---------- using System; using System.Collections.Generic; using System.Linq; using System.Web; using Telerik.Sitefinity.Localization; namespace SitefinityWebApp.Localization { public class FlightDataResource: Telerik.Sitefinity.Localization.Resource { [ResourceEntry("NextFlights", Value ="Upcomming flights", Description = "This label is used by the FlightData widget", LastModified = "2021/02/03")] public string NextFlights { get { return this["NextFlights"]; } } } } --------- [Localization(typeof(FlightDataResource))] [ControllerToolboxItem(Name = "SpaceX_MVC", Title ="SpaceX", SectionName ="Aramco", CssClass = "sfMvcIcn")] public class FlightDataController : Controller { ...... } --------- @using Telerik.Sitefinity.Frontend.Mvc.Helpers; @Html.Resource("NextFlights") --------- Sample: OData https://www.progress.com/documentation/sitefinity-cms/tutorial-call-odata-services-in-browser-based-javascript-applications https://github.com/IdentityModel/oidc-client-jsA2 --------- https://www.geeksforgeeks.org/analysis-algorithms-big-o-analysis/ --------- private async System.Threading.Tasks.Task<LaunchViewModel> GetLaunchAsync() { if (string.IsNullOrWhiteSpace(this.spacexServiceUrl)) { var flightConfig = Telerik.Sitefinity.Configuration.Config.Get<FlightConfig>(); this.spacexServiceUrl = flightConfig.SpacexUrl; } using (var client = new System.Net.Http.HttpClient()) { var jsonString = await client.GetStringAsync(this.spacexServiceUrl); return Newtonsoft.Json.JsonConvert.DeserializeObject<LaunchViewModel>(jsonString); } } --------- using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Web; namespace SitefinityWebApp { public class FlightConfig: Telerik.Sitefinity.Configuration.ConfigSection { [ConfigurationProperty("SpacexUrl", DefaultValue = "https://api.spacexdata.com/v3/launches")] public string SpacexUrl { get { return (String)this["SpacexUrl"]; } set { this["SpacexUrl"] = value; } } } } -------- protected void Application_Start(object sender, EventArgs e) { Telerik.Sitefinity.Abstractions. Bootstrapper.Bootstrapped += Bootstrapper_Bootstrapped; } private void Bootstrapper_Bootstrapped(object sender, EventArgs e) { Telerik.Sitefinity.Configuration.Config.RegisterSection<FlightConfig>(); } -------- Questions: 1- How to send an item for approval using already configured workflow in the code A: WorkflowManager.MessageWorkflow(item.Id, typeof(NewsItem), null, "Publish", false, new Dictionary<string, string>()); More info: https://www.progress.com/documentation/sitefinity-cms/for-developers-default-workflow 2- Uploading docuements using API outside Sitefinity? can we have a real example A: https://knowledgebase.progress.com/articles/Article/Sitefinity-REST-to-upload-an-image More info: https://www.progress.com/documentation/sitefinity-cms/tutorial-postman-sample-odata-queries?_ga=2.9189367.395345776.1612140318-800962634.1612039386 3- What type of application is Sitefinity good at other than content based applications? is it good for dashboards for example. A: Not that it can't be used for dashboards, but the question is what will be the value for the development team to use it as a dashboard. Usually Sitefinity is for building corporate websites, web business systems (e.g. we have built such systems for large insurance providers and they use these systems to run their run their business, e.g. to enable insurance brokers to manage their insurance policies quotas). It is also good for building portals and as a headless CMS. 4- When it's not recommoneded to use Sitefinity A: It's not recommended to use it in case you have not through a traning and/or the documentation. 5- What's the best practice in Sitefinity to read items with the same concept of details/list Widget from a database outside sitefinity. I have used a query string but sometime the widget data get cached and not updated even when the query string is changed. A1 (cache integration so it varies by query string): https://www.progress.com/documentation/sitefinity-cms/configure-cache-variation-by-query-string A2: look at the Details action method => https://github.com/Sitefinity/feather-widgets/blob/master/Telerik.Sitefinity.Frontend.News/MVC/Controllers/NewsController.cs More information: https://www.progress.com/documentation/sitefinity-cms/implement-master-detail-content-controllers-mvc Even more information: https://www.progress.com/documentation/sitefinity-cms/82/feather-use-the-relative-routes-api 6- What previelages should we grant content editor? A: They usually need permissions only to create/update/delete content (i.e. content and pages - pages should be restricted)/ 7- is it recommended to customize adding an item from front-end? is there a way to minimize it? A: Use the backend pages and extend the backend by creating a backend page with custom widgets. 8- Where is the best place to trigger search indexing? A: The place is http://localhost:8088/Sitefinity/Administration/Search A2; To index data from external data source you should extend the Sitefinity SearchService class in Sitefinity so your custom code will trigger indexing when user hirs the "Reindeixng" button from the link above A3: The best practice is to use external search egnine service. I would recommend going with http://hawksearch.com as it has the best integration with Sitefinity. It supports multi-source indeixng out of the box and also many other features (plus it can find results in millions of records for milisenconds). Contact me in case you want to prepare a demo for you. 9- is there a way to have approval for adding taxonomy? A: This is not supported OOB. Eventually you can try to build your workflow where to itnegrate the processing of taxonomies. This will take decent amount of development time and it will be complex as a solution. A2: Better send feature request to Porgress asap. 10- we face razor generator error when build the application hosted in the developement server A: I can't recall somehing. It will be best to contact the Progress support via ticket. ![](https://i.imgur.com/rT92FHH.jpg) A2: https://knowledgebase.progress.com/articles/Article/RazorCodeGen-error 11 - can we do an example of scheduled tasks in sitefinity A: https://www.progress.com/documentation/sitefinity-cms/for-developers-scheduled-tasks 12- web service to create and update dynamic content via jQuery or other frameworks A: https://www.progress.com/documentation/sitefinity-cms/tutorial-call-odata-services-in-browser-based-javascript-applications https://github.com/IdentityModel/oidc-client-js 13-can we configure approvals requests workflow? A: We are going to have a session for configuring the approval workflow via the UI. 14- Do we have design tool for website before implemented ? and can we design a full website without coding ? A: No, there is no design tool that can be used to generated a design for Sitefinity website and to integrate it. You will neeed to use third-party software to generated designs, then to turn them to HMTL/CSS/JavaScript and then integrate them by hand in Siteifnity. 1- How to send an item for approval using already configured workflow in the code 2- Uploading docuements using API outside Sitefinity? can we have a real example 3- What type of application is Sitefinity good at other than content based applications? is it good for dashboards for example. 4- When it's not recommoneded to use Sitefinity 5- What's the best practice in Sitefinity to read items with the same concept of details/list Widget from a database outside sitefinity. I have used a query string but sometime the widget data get cached and not updated even when the query string is changed. 6- What previelages should we grant content editor? 7- is it recommended to customize adding an item from front-end? is there a way to minimize it? 8- Where is the best place to trigger search indexing? 9- is there a way to have approval for adding taxonomy? 10- we face razor generator error when build the application hosted in the developement server 11 - can we do an example of scheduled tasks in sitefinity 12- web service to create and update dynamic content via jQuery or other frameworks 13-can we configure approvals requests workflow? 14- Do we have design tool for website before implemented ? and can we design a full website without coding ?