Friday 4 March 2016

Drop down on page (DD4T MVC)should be in sync with Custom database. Create Keywords update Component and publish page

Requirement :- All filter drop down on DD4T MVC page should be in sync real-time with custom database






All the above drop-down are populating based on category and keywords.So we need to read client database create  keyword update the component presentation of filter component and publish the page.


Here, I have created the C# console application which keep on running and making sure that the SQL database and tridion taxonomies are in sync.


I have escaped the code of SQL connectivity and loops to iterate the data :)  
  1. Create core service ISessionAwareCoreService Client
public static class CoreServiceConnectionScheme
    {
        public const String netTcp = "net.tcp";
        public const String wsHttp = "http";
        public const String undefined = "undefined";
    }

    public static class CoreServiceFactory
    {
        public static ICoreServiceFrameworkContext GetCoreServiceContext(Uri endpointUri, NetworkCredential windowsNetworkCredentials)
        {
            switch (endpointUri.Scheme.ToLower())
            {
                case CoreServiceConnectionScheme.wsHttp:
                    return GetWsHttpContext(endpointUri, windowsNetworkCredentials);
                case CoreServiceConnectionScheme.netTcp:
                    return GetNetTcpContext(endpointUri, windowsNetworkCredentials);
                default:
                    throw new ArgumentException("The uri connection scheme specified [{0}] is invalid; a valid scheme (ie. http for WsHttp, or net.tcp for NetTcp must be specified).");
            }
        }
public static ICoreServiceFrameworkContext GetWsHttpContext(Uri endpointUri, NetworkCredential windowsNetworkCredentials)
        {
return new CoreServiceFrameworkWsHttpContext(endpointUri, windowsNetworkCredentials);
        }
public static ICoreServiceFrameworkContext GetNetTcpContext(Uri endpointUri, NetworkCredential windowsNetworkCredentials)
        {
return new CoreServiceFrameworkNetTcpContext(endpointUri, windowsNetworkCredentials);
        }
    }


   2. Go to Main method 


static void Main(string[] args)
{
Logger.WriteLog(Logger.LogLevel.INFO, "Calling Keyword creation process");           
CreateKeywords.Process();
Logger.WriteLog(Logger.LogLevel.INFO, "Calling Keyword creation process End"); 
}

    3. Create a class

public class CreateKeywords

{   
public static ICoreServiceFrameworkContext coreService = null;
public static void Process()
{
XmlDocument doc = new XmlDocument();
coreService = CoreServiceFactory.GetCoreServiceContext(new Uri(ConfigurationManager.AppSettings["CoreServiceURL"].ToString()), new NetworkCredential(ConfigurationManager.AppSettings["UserName"].ToString(), ConfigurationManager.AppSettings["Password"].ToString(), ConfigurationManager.AppSettings["Domain"].ToString()));

#region Creating Keywords and updating component
Logger.WriteLog(Logger.LogLevel.INFO, "Checking keyword already exist in tridion or not");  
TridionObjectInfo obj = Helper.GetTridionObject(coreService, ItemType.Keyword, "tcm:1-440-512", "Test");
var tcmID = obj.ObjectCount == 0 ? TridionKeyword.GenerateKeyword(coreService, "3 Test", "Test", "tcm:1-440-512") : "";
Logger.WriteLog(Logger.LogLevel.INFO, "Returned Tcmuri of keyword " + tcmID);

ComponentData component = (ComponentData)coreService.Client.Read(ConfigurationManager.AppSettings["CompId"].ToString(), new ReadOptions());

4. Create new element in component.Content XML 

doc.LoadXml(component.Content);
XmlElement createchild = doc.CreateElement("Filter1");
createchild.InnerText = 3 Test;
doc.DocumentElement.AppendChild(createchild);
component.Content=doc.InnerXml;

component.Id = ConfigurationManager.AppSettings["CompId"].ToString();
Logger.WriteLog(Logger.LogLevel.INFO, "Updating Component " + component.Id);
component = (ComponentData)coreService.Client.Update(component, new ReadOptions());


 Logger.WriteLog(Logger.LogLevel.INFO, "Updating Component done " + component.Id + "Sending page for publishing " + ConfigurationManager.AppSettings["PageId"].ToString());

}

5.To Generate Keywords


public static string GenerateKeyword(ICoreServiceFrameworkContext coreService, string value, string key, string CategoryID)
        {
            try
            {
                KeywordData keyword = (KeywordData)coreService.Client.GetDefaultData(ItemType.Keyword, CategoryID);
                keyword.Id = "tcm:0-0-0";
                keyword.Title = value;
                keyword.Key = key;

                keyword = (KeywordData)coreService.Client.Create(keyword, new ReadOptions());
                Logger.WriteLog(Logger.LogLevel.INFO, "KeyWord TcmID :" + keyword.Id.ToString() + " Under category ID" + CategoryID);
                return keyword.Id.ToString();
            }
            catch(Exception ex)
            {               
                Logger.WriteLog(Logger.LogLevel.ERROR, "GenerateKeyword :" + ex.Message);             
                return "";
            }
           
6. To Publish Use

coreService.Client.Publish(new[] { PageId}, pubData, new[] { target.ToString() }, PublishPriority.High, null);


7. On your DD4T Mvc App you can bind dropdown with keywords

<select id="Filter1">                    
@if (Model.Fields.ContainsKey("Filter1"))
{
foreach (var value in Model.Fields["Filter1"].Keywords)
{
<option value="@value.Key">@value.Title</option>                       
}
}
</select>



Happy Coding and keep Sharing !!!!

Tuesday 2 February 2016

Create component in Tridion 2013 using core service and SQL data feed

We have this requirement to consume data from SQL and create Tridion components and automate this process as well like schedule this in task scheduler and run periodically  

Create WCF RestFull service
·         Create Service contract which are exposed by the service to the outside world
In IRestService.cs
[ServiceContract]
    public interface IRestService
    {

        [OperationContract(Name = "CallServiceData")]
        [WebGet(UriTemplate = "/CallServiceData")]
        string CallServiceData();
        
    } 
·         Implement interface member .Here we will call our Business layer SQL stored procedure and serializing the data
  
    public class RestService : IRestService
    {
        public string CallServiceData ()
        {

            try
            {                
             NameSearchGeneration.Process();
             Logger.WriteLog(Logger.LogLevel.ERROR, " Successfully executed CallServiceData ");
                    Output = "True";              
            }
            catch (Exception ex)
            {
                Logger.WriteLog(Logger.LogLevel.ERROR, ex.Message + "Error While Calling CallServiceData ");

            }
            return Output;
        }

    }
·         In Business layer create a class NameSearchGeneration and method process() from here we will import sql data
List<Articles> Articles = Helper.GetImportXmlData();
·         Create model for Article get all the SQL data and bind in article model
    [DataContract]
    [Serializable]
    public class Articles
    {
         
        [XmlElement("title")]
        [DataMember]
        public string Title { getset; }

        [XmlElement("Description")]
        [DataMember]
        public string Description { getset; }
    }
·         Serialize article data using Serialize using System.Xml.Serialization;
foreach (Articles p in ArticlesList)
            {
                    string serializeXml = "";
                    bool bln = Serialize<Articles>(p, ref serializeXml);
                }
          And return the list to List<Articles> Articles

·         Create your core service client ISessionAwareCoreService

coreService = CoreServiceFactory.GetCoreServiceContext(new Uri(ConfigurationManager.AppSettings["CoreServiceURL"].ToString()), new NetworkCredential(ConfigurationManager.AppSettings["UserName"].ToString(), ConfigurationManager.AppSettings["Password"].ToString(), ConfigurationManager.AppSettings["Domain"].ToString()));


       public static class CoreServiceFactory
       {
public static ICoreServiceFrameworkContext GetCoreServiceContext(Uri endpointUri, NetworkCredential windowsNetworkCredentials)
        {
            switch (endpointUri.Scheme.ToLower())
            {
                case CoreServiceConnectionScheme.wsHttp:
                    return GetWsHttpContext(endpointUri, windowsNetworkCredentials);
                case CoreServiceConnectionScheme.netTcp:
                    return GetNetTcpContext(endpointUri, windowsNetworkCredentials);
                default:
                    throw new ArgumentException("The uri connection scheme specified [{0}] is invalid; a valid scheme (ie. http for WsHttp, or net.tcp for NetTcp must be specified).");
            }
        }

        public static ICoreServiceFrameworkContext GetWsHttpContext(Uri endpointUri, NetworkCredential windowsNetworkCredentials)
        {
            return new CoreServiceFrameworkWsHttpContext(endpointUri, windowsNetworkCredentials);
        }

        public static ICoreServiceFrameworkContext GetNetTcpContext(Uri endpointUri, NetworkCredential windowsNetworkCredentials)
        {
            return new CoreServiceFrameworkNetTcpContext(endpointUri, windowsNetworkCredentials);
        }
    }


·         Read schema using coreservic client
SchemaFieldsData schemaFieldData = coreService.Client.ReadSchemaFields(ConfigurationManager.AppSettings["SchemaID"].ToString(), truenew ReadOptions());
·         Using foreach on article list we will create component in Tridion using coreservice client and publish them .
foreach (Articles p in Articles)
                    {
                        string serializeXml = "";
                        bool bln = Helper.Serialize<Articles>(p, ref serializeXml);
                        string xml = serializeXml;

                        string tcmuri = TridionComponent.GenerateComponent(coreService, xml, Helper.SetPublication(ConfigurationManager.AppSettings["FolderLocation"].ToString(), ConfigurationManager.AppSettings["SchemaID"].ToString()), Helper.SchemaType.Component, ConfigurationManager.AppSettings["FolderLocation"].ToString);
                        try
                        {
                            TridionComponent.Publish(tcmuri, ConfigurationManager.AppSettings["PublicationFolderLocation"].ToString(), coreService);
                            Logger.WriteLog(Logger.LogLevel.ERROR, "Component is published successfully");
                        }
·        In GenerateComponent method we will first check if component exist or not
o   If exist we will update and re-publish
o   If not then we will create and publish

·        Here I am searching component based on its title
TridionObjectInfo tridionObjectInfo = Helper.GetTridionObject(coreService, ItemType.Component, folderUri, Title);

if (tridionObjectInfo.TcmUri != null)
                { componentData = (ComponentData)coreService.Client.Update(componentData, new ReadOptions());
}
  else
                {
                    componentData = (ComponentData)coreService.Client.Create(componentData, new ReadOptions());return componentData.Id.ToString();}
·         You need to have following configurable values in your config files
<appSettings>
   
    <!--Tridion User credentials UserName/Password to run the core service-->
    <add  key="UserName" value="" />
    <add  key="Password" value=" " />
    <add  key="Domain" value=" " />
    <add  key="CoreServiceURL" value="http://domain/webservices/CoreService2011.svc/wsHttp" />
    <!-- publication ID is requried-->
    <add  key="PublicationID" value="21" />
    <!-- publication target ID is requried-->
    <add  key="PublicationFolderLocation" value="tcm:0-1-65538" />
    <!-- Connection String is requried-->
    <add key ="ConnectionString" value="Data Source=localhost;Initial Catalog=SQLTridionData;User ID=article;Password=123456;"/>
    <!-- Name of the SP requried-->
    <add  key="SqlProcedureTogetData" value="spName" />   
    <!--Folder TcmId where components gets saved/created-->
    <add  key="FolderLocation" value="tcm:0-111-2" />   
    <!--Schema Id of Article Schema-->
    <add  key="SchemaID" value="tcm:1-1111-8" />
  </appSettings>
This way you can automate the process of creating component and publish from SQL data feed 
Happy Coding and keep Sharing !!!!