29 September 2014

AD module - Reset Password and Port Number


Active Directory Module. This is a nice module to play with. It is quite powerful and quite easy to configure following the documentation provided.

On a recent project we had the situation where we needed to allow the user to change their password. That sounds like the easiest task in the world and somehow whatever we tried we ended up with the following issue:


Exception: System.Reflection.TargetInvocationException
Message: Exception has been thrown by the target of an invocation.
Source: System.DirectoryServices
   at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)
   at System.Web.Security.ActiveDirectoryMembershipProvider.ChangePassword(String username, String oldPassword, String newPassword)
   at Sitecore.Security.Accounts.MembershipUserWrapper.ChangePassword(String oldPassword, String newPassword)
   at Sitecore.Shell.Applications.Security.SetPassword.SetPasswordPage.OK_Click()

Nested Exception

Exception: System.Runtime.InteropServices.COMException
Message: Configuration information could not be read from the domain controller, either because the machine is unavailable or access has been denied. (Exception from HRESULT: 0x80070547)

This error was logged from the front end but also when trying to change the user password from the Sitecore Desktop Interface. We have tried quite a few things with user permission... nothing work until we added the port number to the connection string:

  < add connectionstring="LDAP://adconnection:389/OU=Users,DC=mycomany,DC=external" name="MyAdConnString"> 

So just in case you are getting similar issues, it is worth adding the port number to the connection string... Hoping that wil save a few hours of debugging...

14 September 2014

Retrieve Datasource from a Controller Rendering

If you are using Sitecore MVC then I am sure you have been using Controller Rendering. When using personlisation you are most likely either switch the Rendering or simply change the Datasource to point at different items. In your controller code, you may have tried the following:

SitecoreContext.GetCurrentItem< Item>()

With the SitecreContext being the Glass.Mapper.Sc.ISitecoreContext...

The GetCurrentItem in the controller will always return the Context Item, not the Datasource. So you need to actually retrieve the Datasource with Code. What you can use is something similar to:

        /// 
        /// Get either the data source or the context item
        /// 
        private Item Datasource
        {
            get
            {
                var dataSource = SitecoreContext.GetCurrentItem< Item>();
                string datasourceId = RenderingContext.Current.Rendering.DataSource;
                if (Sitecore.Data.ID.IsID(datasourceId))
                {
                    dataSource = SitecoreContext.GetItem< Item>(new Guid(datasourceId));
                }

                return dataSource;
            }
        }

From the above code you can see that this will either return the Context Item if the Datasource is not set, OR the datasource item if set.

Now, I am sure you will have to create multiple Controller Renderings in your solution. So it could be a great idea to create an abstract class Controller and all your controller will be based on this:

namespace MySite.Controllers
{
    public abstract class BaseController: SitecoreController
    {
        protected readonly ISitecoreContext BaseSitecoreContext;

        public BaseController(ISitecoreContext sitecoreContext)
        {
            this.BaseSitecoreContext = sitecoreContext;
        }

        /// 
        /// Get either the data source or the context item
        /// 
        public Item Datasource
        {
            get
            {
                var dataSource = BaseSitecoreContext.GetCurrentItem< Item>();
                string datasourceId = RenderingContext.Current.Rendering.DataSource;
                if (Sitecore.Data.ID.IsID(datasourceId))
                {
                    dataSource = BaseSitecoreContext.GetItem< Item>(new Guid(datasourceId));
                }

                return dataSource;
            }
        }
    }
}


You can now use the base Controller to derive your custom controller:
    public class CalculatorController : BaseController
    {
        private readonly ISitecoreContext sitecoreContext;

        public CalculatorController(ISitecoreContext sitecore)
            : base(sitecore)
        {
             // Do whatever
        }
    }

2 September 2014

Email function in Sitecore

Just a quick reminder for those who wants to send an email from Sitecore. There are times where you have to write your own method and this is completely understandable. However, dont forget to check if there is already a method that does it for you... I have seen a SendEmail Method where the SMTP, username, password and port were defined on the item fields. Well for this specific example, you have a method that already send email in sitecore:

Sitecore.MainUtil.SendMail(System.Net.Mail.MailMessage message)

This method is using the System.Net.Mail.SmtpClient to send the email which what most of us will actually implement on custom code. So why not using it... Here is the Method:

  /// 
  /// Sends the mail.
  /// 
  /// The message.
  public static void SendMail(System.Net.Mail.MailMessage message)
  {
   string mailServer = Settings.MailServer;
   System.Net.Mail.SmtpClient smtpClient;
   if (string.IsNullOrEmpty(mailServer))
   {
    smtpClient = new System.Net.Mail.SmtpClient();
   }
   else
   {
    int mailServerPort = Settings.MailServerPort;
    if (mailServerPort > 0)
    {
     smtpClient = new System.Net.Mail.SmtpClient(mailServer, mailServerPort);
    }
    else
    {
     smtpClient = new System.Net.Mail.SmtpClient(mailServer);
    }
   }
   string mailServerUserName = Settings.MailServerUserName;
   if (mailServerUserName.Length > 0)
   {
    string mailServerPassword = Settings.MailServerPassword;
    System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(mailServerUserName, mailServerPassword);
    smtpClient.Credentials = credentials;
   }
   smtpClient.Send(message);
  }



So you should be able to use it straight away as per the following:

var myMessage = new MailMessage(from, to, subject, body);
  Sitecore.MainUtil.SendMail(myMessage);


RE-EDITED the post: obviously you need to setup your SMTP in the web.config for this to work:
      < !--  MAIL SERVER
            SMTP server used for sending mails by the Sitecore server
            Is used by MainUtil.SendMail()
            Default value: ""
      -->
      < setting name="MailServer" value="" />
      < !--  MAIL SERVER USER
            If the SMTP server requires login, enter the user name in this setting
      -->
      < setting name="MailServerUserName" value="" />
      < !--  MAIL SERVER PASSWORD
            If the SMTP server requires login, enter the password in this setting
      -->
      < setting name="MailServerPassword" value="" />
      < !--  MAIL SERVER PORT
            If the SMTP server requires a custom port number, enter the value in this setting.
            The default value is: 25
      -->
      < setting name="MailServerPort" value="25" />


I hope that will help...