Sitecore : Getting image field in code behind
This is just a quick post to show how to get image URL via code behind.
This is mostly useful when you are binding children items to a repeater or returning image URL in a JSON webservice
public static string GetImageURL(Item currentItem)
{
string imageURL = string.Empty;
Sitecore.Data.Fields.ImageField imageField = currentItem.Fields["Image"];
if (imageField != null && imageField.MediaItem != null)
{
Sitecore.Data.Items.MediaItem image = new Sitecore.Data.Items.MediaItem(imageField.MediaItem);
imageURL = Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(image));
}
return imageURL;
}
Cheers
Sitecore vs Umbraco – A developer’s view
One Friday afternoon, I was sitting at my desk and fixing bugs (as usual), a member of sales team came up to me and said
“Hey Naveed, we have this interesting new client and they are not sure about which CMS to go for, they have finalised Sitecore and Umbraco as the last two, can you help”
I replied: “Sure, why not, what are their business requirements ?”
Sales person: “They are medium to large size organisation and have usual requirements like news, events, forums, blogs, video content etc, they want a simple to use CMS with multiple authors and security levels”
I replied: “Ok, Sitecore and Umbraco are both equally powerful in content generation and management, they both are based on .NET stack (.NET,C#,SQL) and both are highly customisable, so far they both can be their potential CMS, do you have more specific requirements ?”
Sales person: “Yes, in future, they would like to integrate with Sharepoint and their back-end CRM system”
I replied :”Sitecore comes with a sharepoint connector out-of-box whereas for Umbraco we have to custom build one. As long as their back end CRM exposes API, we can integrate any of the CMS system with their back end, this will be custom build in both cases, do you have any other requirements ?”
Sales person: “It is not a requirement but in their wish list to have personalised content for different regions or profile history”
I replied: “Sitecore comes with Customer Engagement Platform (CEP) and Online Marketing Suite (OMS) which can make their life easy in future, however, Umbraco lacks these customised modules. So it looks like Sitecore can be their potential candidate for CMS, also do you have any idea about their budget for the website?”
Sales person: “Yes, it’s a five figure sum, not sure what exactly their budget is”
I replied: “If they are tight on budget and can compromise on add-ons then Umbraco would be good to start off with but will have high maintenance cost if they go down the route implementing customised modules. However, paying for Sitecore licenses up front will give them added benefit to use some of the modules out of the box and will have low maintenance cost, I guess best would be to give them a demo of both CMS systems to the client and let them make informed decision”
Sales person: “Sounds like a plan, ok I will let them know, cheers”
Conclusion:
No CMS is right or wrong for your business out of the box, you have evaluate them against your own business requirements for the website. Open source may be cheaper to start off with but will have maintenance costs down the line.
Disclaimer: I have worked with both CMS systems and hold them up in same respect for what they do, I am not a sales person or work for either of the CMS systems, this is just my opinion as a third party developer
EPiServer : Dynamic Data Store
If you are reading this post, then I can assume you are curios about EPiServer dynamic data store and want to know how to use it. In this post, I am going to do exactly the same. I will create, update and delete from DDS using EPiServer API.
1- Create a new dynamic data store
Imagine you have to dynamically store landing page ids for certain products or sections and then read them back from dynamic data store
private void CreateLandingPageDDS(PageData myPage)
{
//create a propertybag
PropertyBag landingProperties = new PropertyBag();
//add your custom properties
landingProperties.Add("LandingPageKey", myPage.PageLink.ID.ToString());
landingProperties.Add("LandingPageProductName", myPage.PageName);
//add more properties if you like, but there is a limit that you can add upto, or
//create a custom object and add that object
//create a new store for DDS
DynamicDataStore store = DynamicDataStoreFactory.Instance.CreateStore("DDS", landingProperties.GenerateTypeBag());
//store DDS in database
Identity id = store.Save(landingProperties);
}
pretty simple
2- Get dynamic data store
Now let say you want to query the same DDS and would like to get pageName if you pass in the pageID
public static string GetLandingPageName(string currentPageID)
{
//get the store from database
DynamicDataStore store = (DynamicDataStore)DynamicDataStoreFactory.Instance.GetStore("DDS");
if (store != null)
{
//find all the properties for that key/value pair
IEnumerable<PropertyBag> landingProperties = store.FindAsPropertyBag("LandingPageKey", currentPageID);
//iterate through each property and return only where key matches
if (landingProperties != null)
{
foreach (PropertyBag item in landingProperties)
{
string pageName = item["LandingPageProductName"] as string ?? string.Empty;
return pageName;
}
}
}
return string.Empty;
}
Although pageName is a trivial property, this is just an example how to go about using DDS.
3- Update dynamic data store
Now let say you want to update pageName using pageID
private void UpdateLandingPage(string currentPageID)
{
DynamicDataStore store = (DynamicDataStore)DynamicDataStoreFactory.Instance.GetStore("DDS");
if (store != null)
{
IEnumerable<PropertyBag> landingProperties = store.FindAsPropertyBag("LandingPageKey", currentPageID);
if (landingProperties != null)
{
foreach (PropertyBag item in landingProperties)
{
item["LandingPageProductName"] = "New name";
store.Save(item);
}
}
}
}
4- Delete dynamic data store
That is very strait forward, just use
DynamicDataStoreFactory.Instance.DeleteStore("DDS",true);
5-Important note
If during development, you have to change your dynamic data store by adding more properties to property bag object, it will result in exception.
There are two ways to get round this
1.If you are in development, delete your previous DDS entries and start fresh
2.If you are in production, then you have to re-map/re-link the property bag.
Have fun coding DDS
EPiServer : CustomProperty for Radio Button List
EPiServer has lots of in-built properties, but one major property that it is missing is ‘radio button list’ , sometimes user wants to select just one option from give 4 or 5 options.
In this post, I will guide you through making a very basic custom property for EPiServer for ‘Radio Button List’
Step1: In your VS project, right-click and new EPiServer custom property control as show below, i will rename this control is ‘PropertyMyPicker’
Step2: Inherit it from ‘PropertyString’ as shown below
Step3: This will create two code files in your project as following
PropertyMyPicker.cs
PropertyMyPickerControl.cs
You do not need to do anything in ‘PropertyMyPicker.cs’ class, and all your logic will be implemented in ‘PropertyMyPickerControl.cs’.
Step4: In this code snippet, we create 3 radio buttons, if their value is selected, that text is stored in the database and when the page is re-visited/re-loaded the value is read back from the database. Change the code of the ‘PropertyMyPickerControl.cs’ as shown below and make necessary namespace and variable changes. You have overwrite some of the methods and implement your own if necessary.
/// <summary>
/// PropertyControl implementation used for rendering PropertyMyPicker data.
/// </summary>
public class PropertyMyPickerControl : EPiServer.Web.PropertyControls.PropertyStringControl
{
RadioButton radioButton1 = null;
RadioButton radioButton2 = null;
RadioButton radioButton3 = null;
// Value that will be stored in db,
string desc = string.Empty;
// group name for all radio buttons to make them behave as radiobuttonlist
readonly string groupName = "MyPicker";
/// <summary>
/// Gets the PropertyMyPicker instance for this IPropertyControl.
/// </summary>
/// <value>The property that is to be displayed or edited.</value>
public PropertyMyPicker PropertyMyPicker
{
get
{
return PropertyData as PropertyMyPicker;
}
}
/// <summary>
///creates radio button list and pre-select if the value
///has been saved in database
/// </summary>
public override void CreateEditControls()
{
//add radioButton1 radio button
radioButton1 = new RadioButton();
radioButton1.Text = "Radio 1 Text";
radioButton1.GroupName = groupName;
radioButton1.Checked = IsRadioChecked(radioButton1.Text);
//add radioButton2 radio button
radioButton2 = new RadioButton();
radioButton2.Text = "Radio 2 Text"
radioButton2.GroupName = groupName;
radioButton2.Checked = IsRadioChecked(radioButton2.Text);
//add radioButton3 radio button
radioButton3 = new RadioButton();
radioButton3.Text = "Radio 3 Text";
radioButton3.GroupName = groupName;
radioButton3.Checked = IsRadioChecked(radioButton3.Text);
this.Controls.Add(radioButton1);
this.Controls.Add(radioButton2);
this.Controls.Add(radioButton3);
}
/// <summary>
/// Saves it to the database
/// </summary>
public override void ApplyEditChanges()
{
desc = GetMyDescription();
base.SetValue(desc);
}
/// <summary>
/// Get selected radio button text
/// </summary>
/// <returns></returns>
private string GetMyDescription()
{
string selectedMyPicker = string.Empty;
if (radioButton1.Checked)
selectedMyPicker = "Radio 1 Text";
else if (radioButton2.Checked)
selectedMyPicker = "Radio 2 Text";
else if (radioButton3.Checked)
selectedMyPicker ="Radio 3 Text";
return selectedMy;
}
/// <summary>
/// Check if the controls contain value for any of the radio button in database
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private bool IsRadioChecked(string name)
{
if (this.PropertyData.Value != null)
{
string selectedMy = this.PropertyData.Value.ToString();
if (selectedMy.ToLower() == name.ToLower())
return true;
}
return false;
}
}
Step 5: Next you need to create the property for the page template, you will see your new property in the dropdown list
Step 6: You can use this property as a page string property and output your custom logic
//assuming MyPicker is the page property name
var myPicker = CurrentPage["MyPicker"] as string;
if (!String.IsNullOrEmpty(myPicker))
{
//add your custom logic here
}
Thats it, job done!
Sitecore : Extending OnItemSave Handler
In a recent project, I have to update certain fields of sitecore item when the item is saved in sitecore.
The solution I went for involved extending item:saved event and adding my own handler to do certain actions based upon template type
If you are in a similar situation, here are the steps to do
1. Create you custom class with a public method to perform your logic
2. In web.config under <events> find , <event name=”item:saved”> and append your handler at the end.
Here is basic class code
public class ItemSaveEventHandler
{
//master database name
public static readonly string Master = "master";
//sample template id
public static readonly string TemplateIdItem = "{67B44133-70CD-405C-BDAF-B93E5AEA2682}";
public void OnItemSaved(object sender, EventArgs args)
{
Item temp = Event.ExtractParameter(args, 0) as Item;
//make sure you are in edit mode and not in publish mode
if (temp != null && temp.Database.Name.ToLower() == Master)
{
//check if the template is what you are looking for
if (temp.TemplateID.ToString() == TemplateIdItem )
{
//do your stuff with the item, this is just a sample
temp.Editing.BeginEdit();
temp.Fields["Title"] = "new item saved title";
temp.Editing.EndEdit();
temp.Editing.AcceptChanges();
}
}
}
Complie and debug code, when you are ready change the web.config
<event name="item:saved"> <handler type="Sitecore.Links.ItemEventHandler, Sitecore.Kernel" method="OnItemSaved"/> <handler type="Sitecore.Globalization.ItemEventHandler, Sitecore.Kernel" method="OnItemSaved"/> <handler type="Sitecore.Rules.ItemEventHandler, Sitecore.Kernel" method="OnItemSaved"/> <!-- add the namespace name and assembly dll name as per your site --> <handler type="<MyWebsite.Handlers.ItemSaveEventHandler>, <MyWebsite.Hanlders>" method="OnItemSaved"/> </event>
Thats it, if everything is correct the event handler will be called when someone saves an item in sitecore
Cheers
Sitecore : Adding schedule jobs via agents
This is a really short and sweet post. Sometimes you have to add scheduled jobs to query sitecore items at regular intervals and perform some custom logic.
The easiest way to do it is by adding your code as an agent to the web.config and setting up the interval
First, create your custom class, this could either be within the main website or a separate class library project something like
namespace Website.AgentsNamespace
{
public class MyAgentClass
{
public static void Run()
{
//add your custom logic here
//call sitecore, services, database whatever
//its up to you
}
}
}
Compile and make sure there are no bugs.
Navigate to web.config and find
<scheduling>
node. Add your class as an agent and set the time interval like
<agent type="[name.of.your.class.including.namespace], [name.of.dll.where.the.class.is.compiled]" method="Run" interval="00:05:00" />
Thats it, job done.
Check the logs, and see when sitecor adds the job to scheduler.
SQL Tips – Back up and restore
Here are some SQL bits that I user over and over again
If you try to manually restore the MS SQL server database via console app, it might say, ‘exclusive access could not be obtained’
This is probably there are some connections which have been left hanging or they are actually trying to do some stuff with the database.
I use this script to kill all un-wanted connections
use master
declare @vcdbname varchar(50)
Set @vcdbname = 'DatabaseName'
set nocount on
declare Users cursor for
select spid
from master..sysprocesses
where db_name(dbid) = @vcdbname
declare @spid int, @str varchar(255)
open users
fetch next from users into @spid
while @@fetch_status <> -1
begin
if @@fetch_status = 0
begin
set @str = 'kill ' + convert(varchar, @spid)
exec (@str)
end
fetch next from users into @spid
end
deallocate users
Just change the name to your own database name and run the script
Imagine you have to backup and restore 5-10 database on adhoc bases, going through console app is very pain full and takes lot of time
I normally use scripts and run them in a go which back them up and restore them in a flash
For backups
DECLARE @BackupLocation AS NVARCHAR(250); DECLARE @BackupDate AS NVARCHAR(8); DECLARE @BackUpName AS NVARCHAR(350); SET @BackupLocation = 'E:\SQLBackup\'; SET @BackUpDate = CONVERT(NVARCHAR(8), GETDATE(), 112) -- replace MyDatabase with your database name SET @BackUpName = @BackupLocation + 'MyDatabase_' + @BackUpDate + '.Bak'; USE master; BACKUP DATABASE MyDatabase TO DISK = @BackUpName;
To resotre simply use the following script
USE [master]; ALTER DATABASE MyDatabaseNew SET SINGLE_USER WITH ROLLBACK IMMEDIATE; ALTER DATABASE MyDatabaseNew SET SINGLE_USER; RESTORE DATABASE MyDatabaseNew FROM DISK = 'E:\SQLBackup\<you-file-name>.Bak' WITH REPLACE; ALTER DATABASE MyDatabaseNew SET MULTI_USER; GO
I would normally create these scripts for each of the databases and when required just run them in SQL



