Wednesday, December 19, 2018

Passing Context Item Information as hidden field values with Sitecore 9 Forms

Recently I was working with Sitecore Forms in Sitecore 9 installation and needed to pass context item information (Item Name, Item ID) where a given form is implemented.

After investigating, there were no default way/field to achieve this and had to implement custom field type for that.

Following is the code implementation to get the hidden field and to populate the hidden field.

public class FormDataSubmitAction : SubmitActionBase<string>
{
        public FormDataSubmitAction(ISubmitActionData submitActionData) : base(submitActionData)
        {
        }
        protected override bool Execute(string data, FormSubmitContext formSubmitContext)
        {
            Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));
          
            if (!formSubmitContext.HasErrors)
            {
                StringBuilder message = new StringBuilder();
                var parameters = new NameValueCollection();
              
                foreach (IViewModel field in formSubmitContext.Fields)
                {
                    if(field.FieldTypeItemId.Equals(<CustomHiddenFieldTemplateID>, StringComparison.InvariantCultureIgnoreCase))
                    {
                        AddExtraAttributes(parameters, GetValue(field));
                        continue;
                    }
                    parameters.Add(field.Name, GetValue(field));
                }
                PostData(parameters);
            }
            else
            {
                Logger.Warn(Invariant($"Form {formSubmitContext.FormId} submitted with errors: {string.Join(", ", formSubmitContext.Errors.Select(t => t.ErrorMessage))}."), this);
            }
            return true;
        }
      
        protected override bool TryParse(string value, out string target)
        {
            target = string.Empty;
            return true;
        }
        protected virtual NameValueCollection AddExtraAttributes(NameValueCollection parameters, string contextItemId)
        {
            var contextItem = ItemHelper.GetItem(contextItemId);
            if(contextItem == null)
            {
                return parameters;
            }
            parameters.Add("referring_page", SiteHelper.GetUrl(contextItem));  //You can add more parameters here
            return parameters;
        }
        protected void PostData(NameValueCollection parameters)
        {
            //POST Data to Third-party system
        }
        private static string GetValue(object field)
        {
            return field?.GetType().GetProperty("Value")?.GetValue(field, null)?.ToString() ?? string.Empty;
        }
}


/Views/FormBuilder/FieldTemplates/ContextItemId.cshtml

@using Sitecore.ExperienceForms.Mvc.Html
@model Sitecore.ExperienceForms.Mvc.Models.Fields.StringInputViewModel

@if (!Html.Sitecore().IsExperienceForms())
{
    <input id="@Html.IdFor(m => Model.Value)" name="@Html.NameFor(m => Model.Value)" type="hidden" value="@Sitecore.Context.Item.ID.ToString()" data-sc-field-name="@Model.Name" />
}
else
{
    <div class="form-group">
        <p class="form-control">
            Hidden Sitecore Context Item ID Field
        </p>
    </div>
}


NOTE:
Special thanks to Kamruz Jaman (@jammykam) and Mike Reynolds (@mike_i_reynolds) for pointing me to correct direction.


Friday, August 3, 2018

Sitecore Glass Mapper Experience Editor Error with Incorrect Glass Base Class ID Property Type

I was trying to get the Glass Mapper working with Sitecore 9 in Experience Editor mode and it returned following error.


Failed item resolve - You cannot save a class that does not contain a property that represents the item ID. Ensure that at least one property has been marked to contain the Sitecore ID. Type: Castle.Proxies.IPageBaseProxy
at Glass.Mapper.Sc.Configuration.SitecoreTypeConfiguration.ResolveItem(Object target, Database database) in C:\TeamCity\buildAgent\work\66b8bb468d084f35\Source\Glass.Mapper.Sc\Configuration\SitecoreTypeConfiguration.cs:line 214
at Glass.Mapper.Sc.GlassHtml.MakeEditable[T](Expression`1 field, Expression`1 standardOutput, T model, Object parameters, Context context, Database database, TextWriter writer) in C:\TeamCity\buildAgent\work\66b8bb468d084f35\Source\Glass.Mapper.Sc\GlassHtml.cs:line 560




I found an issue created for the same for Glass Mapper and it has mention following as a solution
https://github.com/mikeedwards83/Glass.Mapper/issues/113


Reason

In my Glass base class, I have defined the "Id" property of an item as follows


IGlassBase.cs  
[SitecoreInfo(SitecoreInfoType.OriginatorId)]
Guid Id { get; set; }


But once I have changed the "Id" property use "ID" attribute as follows, everything started to work as expected with a possibility of Experience Editor edits.

IGlassBase.cs   
[SitecoreId]
ID Id { get; set; }




NOTE: Credit of finding the solution should go to the @zbecknell who has written the final answer for that GitHub issue.

Monday, June 25, 2018

Securing Access to Your MongodDB Databases

Recently I needed to setup authentication to my mongodb databases which used by Sitecore xDB.

I found following article written by @ankitjoshi2409 which was very helpful and informative.
https://ankitjoshi2409.wordpress.com/2017/05/30/mongodb-authentication-in-sitecore/


Below i'm trying to mention the extra steps and some improvements that I did to fully secure our mongoDB instance.

To achieve that, first you need to open Windows Powershell in your MongoDB installed server and run the following commands as necessary.

#Connect to mongo server
> mongo

 #Switch database to "admin" database
> use admin

#Create root user
> db.createUser({
    user:"admin",
    pwd:"adminPwd",
    roles:[
      {
        role:"userAdminAnyDatabase",
        db:"admin"
      },
      {
        role:"root",
        db:"admin"
      }
    ]
  });

#Verify user with given password created correctly. This command should return "1" if authentication successful
> db.auth("admin", "adminPwd")
1


#Adding user to access other databases collections. We are creating the user in the "admin" database and give read/write permission to access all 4 xDB databases for this user.

> db.createUser(
  {
    user: "mongouser",
    pwd: "mongoPwd",
    roles: [
      {
        role: "readWrite",
        db: "Sitecore_analytics"
      },
      {
        role: "readWrite",
        db: "Sitecore_tracking_live"
      },
      {
        role: "readWrite",
        db: "Sitecore_tracking_history"
      },
      {
        role: "readWrite",
        db: "Sitecore_tracking_contact"
      }
    ]
  });

Note:
As you can see, we created the user in the "admin" database and gave necessary read/write permission for sitecore xDB databases for that user. This approach is recommended by MongoDB instead of creating the same user on each and every database.
Quote:
https://docs.mongodb.com/manual/core/security-users/#user-authentication-database
If you intend to have a single user with permissions on multiple databases, create a single user with roles in the applicable databases instead of creating the user multiple times in different databases.  


So, now we have created users and assign correct database permissions for those users, its time to adjust our Sitecore connection string.

<add name="analytics" connectionString="mongodb://mongouser:mongoPwd@localhost:27017/Sitecore_analytics?authSource=admin" />
  <add name="tracking.live" connectionString="mongodb://mongouser:mongoPwd@localhost:27017/Sitecore_tracking_live?authSource=admin" />
  <add name="tracking.history" connectionString="mongodb://mongouser:mongoPwd@localhost:27017/Sitecore_tracking_history?authSource=admin" />
  <add name="tracking.contact" connectionString="mongodb://mongouser:mongoPwd@localhost:27017/Sitecore_tracking_contact?authSource=admin" />



Note that "?authSource=admin" at the end of each connection string. This is to inform mongoDB server that the authentication user is created under "admin" database and use that user for the authentication.


Securing MongoDB Server Access by Disabling Anonymous Access


Once you have confirmed your sites are running with new mongoDB users/passwords, its time to disable anonymous access to your mongoDB database.

To do that,

1. Open you mongoDB configuration file (usually named as mongod.conf OR mongod.cfd) under your mongoDB installed folder and add following link
security:
             authorization: enabled

2. Restart your MongoDB service to changes to take effect


Happy Sitecore !!!

Monday, May 28, 2018

Sitecore User Group Conference - India - 2018

It was the first User Group Conference in Asia, "SUGCON India - 2018" - http://www.sugcon.in/

Organized by Sitecore and sponsored by Microsoft & Horizontal Integration, around 200 participated for the event. As the first time organized in Asia region, it was a huge success.

I was given the task of doing the first technical presentation of the conference to start the technical track. (http://www.sugcon.in/speaker/chaturanga-ranatunga/)



Note: Special thanks to Akshay Sura for encouraging me to do this presentation and to Akshay, Pieter Brinkman and Rob Earlam for all the hard work put to organized the event.




My session was titled "Taking Sitecore Headless with Sitecore JSS", where I discussed newly introduced module in Sitecore - Sitecore JavaScript Services. It is the first step by Sitecore to implement/provide Headless CMS architecture features into Sitecore Experience Management System.

You can find presentation slides from my presentation from here

Also, there were other great presentations which provided valuable information to all the participants. You can find all those events slides from below link.
http://www.sugcon.in/2018-session-slides/



All and all, it was a great experience. Meeting all the great & friendly people from India...

Hope to see you all next time...

Wednesday, January 31, 2018

SitecoreFootsteps Chaturanga Ranatunga Wins Sitecore “Most Valuable Professional” Award 2018



Elite distinction awarded for exceptional contributions to the Sitecore ecosystem

COLOMBO, SRI LANKA — 31, January, 2018 — Chaturanga Ranatunga also know as SitecoreFootsteps, today announced that Chaturanga Ranatunga, Independent Sitecore Consultant has been named a “Most Valuable Professional (MVP)” in the Technology by Sitecore®, the global leader in experience management software. Chaturanga Ranatunga was one of only 208 Technology MVPs worldwide to be named a Sitecore MVP this year.


Now it its 12th year, Sitecore’s MVP program recognizes individual technology, strategy, and commerce advocates who share their Sitecore passion and expertise to offer positive customer experiences that drive business results. The Sitecore MVP Award recognizes the most active Sitecore experts from around the world who participate in online and offline communities to share their knowledge with other Sitecore partners and customers.


This is 3rd consecutive year that I received Sitecore Technology MVP award and the only person from Sri Lanka to win Sitecore MVP award. - SitecoreFootsteps, Chaturanga Ranatunga


“The Sitecore MVP awards recognize and honor those individuals who make substantial contributions to our loyal community of partners and customers,” said Pieter Brinkman, Sitecore Senior Director of Technical Marketing. “MVPs consistently set a standard of excellence by delivering technical chops, enthusiasm, and a commitment to giving back to the Sitecore community. They truly understand and deliver on the power of the Sitecore Experience Platform to create personalized brand experiences for their consumers, driving revenue and customer loyalty.”


The Sitecore Experience Platform™ combines web content management, omnichannel digital delivery, insights into customer activity and engagement, and strategic digital marketing tools into a single, unified platform. Sitecore Experience Commerce™ 9, released in January 2018, is the only cloud-enabled platform that natively integrates content and commerce so brands can fully personalize and individualize the end-to-end shopping experience before, during, and after the transaction. Both platforms capture in real time every minute interaction—and intention—that customers and prospects have with a brand across digital and offline channels. The result is that Sitecore customers are able to use the platform to engage with prospects and customers in a highly personalized manner, earning long-term customer loyalty.


More information can be found about the MVP Program on the Sitecore MVP site: http://www.sitecore.com/mvp