Archive for the ‘C#’ Category
Get TcmId from web dav url
Many of tridion developer would have tried to get tcm id from web dav. This might be one of the common scenarios where we are using web dav when we are rendering embedded components (in another component template).
I think this is simple scenario so I’m just sharing C# code snippet for this. I’m posting this snippet becoz somebody was googling this yesterday
))
IdentifiableObject identifiableObject = engine.GetObject("<<Web dav url>>");
package.PushItem("TCMID", package.CreateStringItem(ContentType.Text, identifiableObject.Id));
Publication URL TBB
In most cases, you will not be publishing the binary files (images/css/js) in the same location of where you publish pages. As a good practice, these external files will be stored in separate folders. In such cases, you will need to specify path (relative) in the page DWT template.
Generally external css files will be declared like
<link href="/styles/main.css" rel="stylesheet" type="text/css"/>
This would work only if you have styles folder immediately after server path.
http://<server>/styles/main.css
In Tridion, default publication URL is “/” but if you have specified any path in the Publication, you will need to append that path also. It should be accessed like.
http://<server>/<pub url>/styles/main.css
The below C# TBB will get the publication URL of the current publication.
//gets the current session object
Session session = engine.GetSession();
//gets page object from the package
Item item = package.GetByType(ContentType.Page);
//gets TcmUri object of Page
TcmUri tcmObj = new TcmUri(item.GetValue("ID"));
//generate tcm string format with publication id
string publicationId = string.Format("tcm:0-{0}-1", tcmObj.PublicationId);
//gets publication object from the current session
Publication publication = new Publication(new TcmUri(publicationId), session);
//writes the publication URL into the package
package.PushItem("PublicationUrl", package.CreateStringItem(ContentType.Text, publication.PublicationUrl));
As you aware, variable “PublicationUrl” will be included in the package so this variable is accessible when you include this TBB on your page template.
Now you need to call this variable on the page DWT like below,
<link href="@@PublicationUrl@@/styles/main.css" rel="stylesheet" type="text/css"/>
Validate Web service in C#
I’ve got many web services to read IMDB content. Some of them are failed to access while testing. So I needed to check whether they are really active before accessing them.
Here’s the code snippet to check any website/web services are active.
public bool IsWebServiceActive(string webServicePath)
{
try
{
WebRequest request = WebRequest.Create(webServicePath);
return ((HttpWebResponse)request.GetResponse()).StatusCode == HttpStatusCode.OK;;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
Update registry files using C#
When I was doing my IMDB app, I found some of the code snippets are frequently used for desktop applications. Here’s the one code sample.
I was having all my registry settings in .reg file instead of adding each entry through code. All we need to do is run this reg file through code.
string filePath = "IMDBSettings.reg";
.
.
.
Process.Start("regedit.exe", "/s " + filePath).WaitForExit();
Get object types in C#/Tridion 2009
In C#, the general usage to identify the object type is using “is” keyword. This is okay to some extent but you have to write “switch” of “if”, for multiple types. If there are more object types, code will be lengthy. Recently I came across a easy way of checking the object’s type. This is helpful when the object is of COM type.
Just add the below reference in your project and call its TypeName method.
using Microsoft.VisualBasic;
.
.
.
.
.
public string GetTypeOf(object obj)
{
return Microsoft.VisualBasic.Information.TypeName(obj);
}
Output:
This was very handy for me in my migration project where I needed to write all the object details in log file.
Iterate all Inner Exceptions in C#
In simple applications or pages, handling an exception will not be a difficult task. But when your application is using any web services or threading, most of the time, actual exception details will be stored in InnerException of the main Exception object. In such cases, we need to iterate all the inner exceptions to get the actual error message.
Here is a code snippet to iterate all inner exceptions from the root Exception object.
private List<string> GetAllErrMessages(Exception ex)
{
List<string> messages = new List<string>();
//assign the current exception as first object and then loop through its
//inner exceptions till they are null
for(Exception eCurrent = ex.Exception; eCurrent != null; eCurrent = eCurrent.InnerException)
{
messages.Add(eCurrent.Message);
}
}
My team said they never saw any code like handling Exception objects using for loop. I don’t know but I learnt this from my lead when I was working on Adrenalin HRMS product. Just sharing the code for your review
Get CData from XML using C#
<?xml version="1.0" ?>
<tcm:Error xmlns:tcm="http://www.tridion.com/ContentManager/5.0" ErrorCode="80040327" Category="19" Source="Kernel" Severity="2">
<tcm:Line ErrorCode="80040327" Cause="false" MessageID="16137">
<![CDATA[
Unable to save Keyword (tcm:0-0-0).
]]>
<tcm:Token>tcm:0-0-0</tcm:Token>
</tcm:Line>
<tcm:Line ErrorCode="80040327" Cause="true" MessageID="15176">
<![CDATA[
XML validation error. Reason: enumeration constraint failed. The element: '{uuid:FAC1CA6A-C5BC-4CEA-AA98-D11E5EE4CD3C}State' has an invalid value according to its data type."; Source: <State>TAMILNADU</State>;
]]>
<tcm:Token>enumeration constraint failed." The element: '{uuid:FAC1CA6A-C5BC-4CEA-AA98-D11E5EE4CD3C}State' has an invalid value according to its data type. "</tcm:Token>
<tcm:Token><State>TAMILNADU</State></tcm:Token>
</tcm:Line>
<tcm:Details>
<tcm:CallStack>
<tcm:Location>XMLValidation.ValidateXML</tcm:Location>
<tcm:Location>XMLValidation.ValidateXML</tcm:Location>
<tcm:Location>XMLValidation.ValidateCustom</tcm:Location>
<tcm:Location>KeywordBL.Create</tcm:Location>
<tcm:Location>XMLState.Save</tcm:Location>
<tcm:Location>Keyword.Save</tcm:Location>
</tcm:CallStack>
</tcm:Details>
</tcm:Error>
public List<string> GetCDataFromXML(string xmlFilePath)
{
//initialize output object
List<string> result = new List<string>();
//initialize XElement object with xml file path
XElement nodes = XElement.Load(xmlFilePath);
// In case of xml string instead of file path
//XElement nodes = XElement.Parse(xmlFilePath);
//navigates only CData elements
foreach (var cData in nodes.DescendantNodes().OfType<XCData>())
{
result.Add(cData.Value);
}
//returns collection of CData<string>
return result;
}
public List<string> GetCDataFromXML(string xmlFilePath)
{
//initialize output object
List<string> result = new List<string>();
//initialize xml reader object with xml file path
XmlReader reader = new XmlTextReader(xmlFilePath);
// In case of xml string instead of file path
// XmlReader reader = XmlReader.Create(new StringReader(xmlFilePath));
reader.MoveToContent();
//navigates only CData elements
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.CDATA:
result.Add(reader.Value);
break;
}
}
//returns collection of CData<string>
return result;
}
public class TCMError
{
List<string> _messages = null;
public string Message
{
get
{
//this is as per my requirement
return this._messages[this._messages.Count - 1];
}
}
public TCMError(string exception)
{
this._messages = new List<string>();
XmlReader reader = new XmlTextReader(exception);
reader.MoveToContent();
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.CDATA:
this._messages.Add(reader.Value);
break;
}
}
}
}
TCMError tcmError = new TCMError(exception);
Console.WriteLine("Message : {0}", tcmError.Message);
Get SID from LDAP Account Name
During my migration we came across a situation where we need SID but all we had only LDAP user name. So after few trail and error googling, below code snippet helped us to get SID from LDAP user name.
/// <summary>
/// Gets the name of the SID by account.
/// <summary>
/// <param name="accountName"> Name of the account.</param>
/// <returns>SID</returns>
public string GetSIDByAccountName(string accountName)
{
//name should be in the format of domain\username
WindowsIdentity userIdentity = new WindowsIdentity(accountName);
if (userIdentity == null)
throw new Exception(string.Format("{0} : User does not exists", accountName));
return userIdentity.User.AccountDomainSid.ToString();
}
Output : S-1-5-21-789336058-507921405-854245398-9938
Convert/Copy ICollection to Array
This is just a code sample to copy the values from any ICollection type to array. I don’t know why some methods in .Net still expects only array type of input, why not ICollection type!!! So I had to convert every time to array type. This is really boring
so this helper method is handy for me.
/// <summary>
/// Arrays from ICollection object.
/// </summary>
/// <param name="collection">ICollection object</param>
/// <returns>String array type</returns>
public string[] GetArrayFromICollection(ICollection collection)
{
string[] array = new string[collection.Count];
collection.CopyTo(array, 0);
return array;
}
LINQ : Looping through ArrayList/List
In C#, we generally use for/foreach/while to loop through an array or any collection object. Now LINQ is providing an easy way of navigating through a collection. I use this for simple condition checking J
List<Employee> employees = new List<Employee>();
employees.Add(new Employee("E001", "Bala", 10000));
employees.Add(new Employee("E002", "Arun", 15000));
employees.Add(new Employee("E003", "Ashok", 20000));
employees.Add(new Employee("E004", "Thiru", 25000));
employees.Add(new Employee("E005", "Ugi", 10600));
employees.Add(new Employee("E006", "VRS", 11000));
employees.Add(new Employee("E007", "Naren", 11200));
var emps = employees.Where((emp, index) => emp.Salary >= 20000);
foreach (var e in emps)
{
Console.WriteLine(e.Name);
}
LINQ provides an extension method, Where which will fetch each item in emp object with index of an collection.
var emps = employees.Where((emp, index) => emp.Salary >= 20000);
You don’t need to declare emp and index variables. For more details, you need to look into predicate feature in LINQ.
This can also be done in LINQ without using extension method which is more like SQL statements.
var emps = from emp in employees where emp.Salary >= 15000 select emp;
Below is the traditional way of looping which is really boring and thank god I got something to try new.
foreach (Employee e in employees)
{
if(e.Salary >= 15000)
Console.WriteLine(e.Name);
}

