Saturday, August 17, 2013

Update User Profile picture programmatically in SharePoint

User Profile Service application maintains all the Information about the User available in SharePoint as User Profiles. These Information will be synchronized with the external source such as Active Directory or Custom DB by User Profile Synchronization Service running in the SharePoint server. User Profile Photo is one of the property in User Profile called “PictureUrl”. All the User Profile Photos are maintained in SharePoint library in My Site called “User Photos”, for each User Profile 3 files are maintained with various dimensions (Large,Medium and Small size) in the library.

When a User uploads a profile picture in SharePoint, these three files will be created from the chosen file and uploaded to the Profile Pictures folder in “User Photos” library under My site and the reference to the Image will be updated to the “PictureUrl” property in the User Profile.
If we are giving an option to change the Profile picture in out custom component, we also need to create these 3 different files and update the reference in User Profile property. Below code snippet will do the need.
#region Profile Image Updation
/// 
/// Updates the current User profile Image
/// 
/// 
/// 
protected void btnProfileUpload_Click(object sender, EventArgs e)
{
    try
    {
        //Uncomment if Change profile photo functionality is required
        if (Page.IsValid && ctrlUpload.HasFile)
        {
            UploadPhoto(SPContext.Current.Web.CurrentUser.LoginName, ctrlUpload.FileBytes);
        }
    }
    catch (Exception ex)
    {
        ErrorHandling.WriteLog("btnProfileUpload_Click " + ex.Message, ex, SPContext.Current.Web);
    }
}

public void UploadPhoto(string accountName, byte[] image) 
{
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(webURL))
        {
            using (SPWeb web = site.OpenWeb())
            {
                web.AllowUnsafeUpdates = true;
                ProfileImagePicker profileImagePicker = new ProfileImagePicker();
                InitializeProfileImagePicker(profileImagePicker, web);
                SPFolder subfolderForPictures = GetSubfolderForPictures(profileImagePicker);
                string fileNameWithoutExtension = GetFileNameFromAccountName(accountName);
                int largeThumbnailSize = 120; int mediumThumbnailSize = 90; int smallThumbnailSize = 30;
                using (MemoryStream stream = new MemoryStream(image))
                {
                    using (Bitmap bitmap = new Bitmap(stream, true))
                    {
                        CreateThumbnail(bitmap, largeThumbnailSize, largeThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_LThumb.jpg");
                        CreateThumbnail(bitmap, mediumThumbnailSize, mediumThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_MThumb.jpg");
                        CreateThumbnail(bitmap, smallThumbnailSize, smallThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_SThumb.jpg");
                    }
                }
                SetPictureUrl(accountName, subfolderForPictures, fileNameWithoutExtension);
                web.AllowUnsafeUpdates = false;
            }
        }               
    });
}

public void SetPictureUrl(string accountName, SPFolder subfolderForPictures, string fileNameWithoutExtension)
{

    SPSite site = subfolderForPictures.ParentWeb.Site;
    UserProfileManager userProfileManager = new UserProfileManager(SPServiceContext.GetContext(site));
    UserProfile userProfile = userProfileManager.GetUserProfile(accountName);
    string pictureUrl = String.Format("{0}/{1}/{2}_MThumb.jpg", site.Url, subfolderForPictures.Url, fileNameWithoutExtension);
    userProfile["PictureUrl"].Value = pictureUrl;
    userProfile.Commit();
} 


public string GetFileNameFromAccountName(string accountName) 
{ 
    string result = accountName; 
    string charsToReplace = @"\/:*?""<>|"; Array.ForEach(charsToReplace.ToCharArray(), charToReplace => result = result.Replace(charToReplace, '_')); 
    return result; 
}   

public void InitializeProfileImagePicker(ProfileImagePicker profileImagePicker, SPWeb web) 
{ 
    Type profileImagePickerType = typeof(ProfileImagePicker); 
    FieldInfo fieldInfo = profileImagePickerType.GetField("m_objWeb", BindingFlags.NonPublic | BindingFlags.Instance); 
    fieldInfo.SetValue(profileImagePicker, web); 
    MethodInfo miLoadPictureLibraryInternal = profileImagePickerType.GetMethod("LoadPictureLibraryInternal", BindingFlags.NonPublic | BindingFlags.Instance); 
    if (miLoadPictureLibraryInternal != null) 
    { 
        miLoadPictureLibraryInternal.Invoke(profileImagePicker, new object[] { }); 
    } 
}   

public SPFile CreateThumbnail(Bitmap original, int idealWidth, int idealHeight, SPFolder folder, string fileName) 
{ 
    SPFile file = null; Assembly userProfilesAssembly = Assembly.Load("Microsoft.Office.Server.UserProfiles, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"); 
    Type userProfilePhotosType = userProfilesAssembly.GetType("Microsoft.Office.Server.UserProfiles.UserProfilePhotos"); 
    MethodInfo miCreateThumbnail = userProfilePhotosType.GetMethod("CreateThumbnail", BindingFlags.NonPublic | BindingFlags.Static);             
    if (miCreateThumbnail != null) 
    { 
        file = (SPFile)miCreateThumbnail.Invoke(null, new object[] { original, idealWidth, idealHeight, folder, fileName }); 
    } 
    return file; 
}   

public SPFolder GetSubfolderForPictures(ProfileImagePicker profileImagePicker) 
{ 
    SPFolder folder = null; 
    Type profileImagePickerType = typeof(ProfileImagePicker); 
    MethodInfo miGetSubfolderForPictures = profileImagePickerType.GetMethod("GetSubfolderForPictures", BindingFlags.NonPublic | BindingFlags.Instance); 
    if (miGetSubfolderForPictures != null) 
    {
        folder = (SPFolder)miGetSubfolderForPictures.Invoke(profileImagePicker, new object[] {true }); 
    } 
    return folder; 
}
#endregion


 

Send Calendar Meeting request in C#

To send Calendar meeting request through code first we need to format string in the form of iCalendar Outlook event. Then we have create a AlternateView object of Calendar MIME type with the formatted string. Now if we add this object to the Mail message, user will receive email in the format of Outlook Event.

Framing the String in iCalendar format and Sending Email
StringBuilder sw = new StringBuilder();        
sw.AppendLine("BEGIN:VCALENDAR");
sw.AppendLine("VERSION:2.0");
sw.AppendLine("METHOD:PUBLISH");
sw.AppendLine("BEGIN:VEVENT");
sw.AppendLine("CLASS:PUBLIC");
sw.AppendLine(string.Format("CREATED:{0:yyyyMMddTHHmmss}", DateTime.UtcNow));
sw.AppendLine("DESCRIPTION: " + desc);
sw.AppendLine(string.Format("DTEND:{0:yyyyMMddTHHmmss}", eventendDT));
sw.AppendLine(string.Format("DTSTART:{0:yyyyMMddTHHmmss}", eventstartDT));
sw.AppendLine(string.Format("ORGANIZER:MAILTO:{0}", SPContext.Current.Web.CurrentUser.Email));
sw.AppendLine("SEQUENCE:0");
sw.AppendLine("UID:" + Guid.NewGuid().ToString());
if (lblIntLocation != null && lblIntLocation.Text != "")
    sw.AppendLine("LOCATION:" + lblIntLocation.Text);
if (lblCandidateName != null && lblCandidateName.Text != "")
    sw.AppendLine("SUMMARY;LANGUAGE=en-us: Scheduled for " + lblCandidateName.Text);
else
    sw.AppendLine("SUMMARY;LANGUAGE=en-us: Scheduled");

sw.AppendLine("BEGIN:VALARM");
sw.AppendLine("TRIGGER:-PT15M");
sw.AppendLine("ACTION:DISPLAY");
sw.AppendLine("DESCRIPTION:Reminder");
sw.AppendLine("END:VALARM");
sw.AppendLine("END:VEVENT");
sw.AppendLine("END:VCALENDAR");   

string from = SPContext.Current.Web.Site.WebApplication.OutboundMailSenderAddress;

string smtpAddress = SPContext.Current.Web.Site.WebApplication.OutboundMailServiceInstance.Server.Address;

// Assign SMTP address 
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = smtpAddress;

MailMessage mailMessage = new MailMessage(from, toRecipients);
mailMessage.Subject = subject;

// Create the Alternate view object with Calendar MIME type
System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType("text/calendar");
ct.Parameters.Add("method", "REQUEST");

//Provide the framed string here
AlternateView avCal = AlternateView.CreateAlternateViewFromString(sw.ToString(), ct);
mailMessage.AlternateViews.Add(avCal);

smtpClient.Send(mailMessage);
Check this article to create downloadable iCalendar files in C#

Send Email with Embedded Images in C#

You might came across a scenario where we need to add Images as part of Email sent through code in HTML format. We can directly give the absolute url of the image and add the image reference in the email. But the when the server in which the Image is hosted goes Offline, we can’t get the image in our Email. To avoid this issue we can embed the Image in Email itself and then it will be available to the User even if the server is offline.

To Embed the Image in our Email we need to create an object for LinkedResource with our image path. Later this LinkedResource will be added to AlternateView of HTML type.
Each Image references should have one unique ID associated with the Image. So first while framing the HTML we will create the Unique ID and mention in “img src” as below,
<img src=”cid:YOUR UNIQUE ID”/>
Then you need use the same unique ID (which is mentioned in Image reference) for creating the Linked Resource object.
LinkedResource obj = new LinkedResource(“Physical path of the image”, "image/png");
Obj.ContentId = “YOUR UNIQUE ID; 
 
If your Image is hosted in any site and doesn’t exists in physical folder, you can get Stream from the Image and pass the Stream as Input while creating object for LinkedResource.

 
byte[] imgByte = null;
using (var webClient = new WebClient())
{
   webClient.UseDefaultCredentials = true;
   Uri uri = new Uri(url);
   imgByte = webClient.DownloadData(uri);
}
Stream memStream = new MemoryStream(img.ImgStream);
LinkedResource pic6 = new LinkedResource(memStream, "image/png");
pic6.ContentId = img.ImgGuid.ToString();
 

Once the LinkedResource object is created we need to add to an object of AlternateView of HTL type. Below is the full sample code snippet for embedding images (Check inline comments for more details).
 
// Creating Unique ID for adding image referrence
string GUId1 = Guid.NewGuid().ToString();               
 
// frame the HTML with the img tag and above unique id
string htmlBody = "<html><body><div><img src=\"cid:" + GUId1 + "\"></div></body></html>";
 
// Create alternateview object with Mime type HTML
AlternateView avHtml = AlternateView.CreateAlternateViewFromString
                    (htmlBody, null, MediaTypeNames.Text.Html);
 
//Create object for Linked Resource with the Image physical path or Image Stream
LinkedResource pic1 = new LinkedResource(HttpContext.Current.Server.MapPath("/_layouts/Images/header.jpg"), "image/png");
 
// Provide the previously created Unique ID to associate the Image with the respective img src.
pic1.ContentId = GUId1;
 
//Add the Linked Resource to the AlternateView
avHtml.LinkedResources.Add(pic1);
 
string from = SPContext.Current.Web.Site.WebApplication.OutboundMailSenderAddress;
 
string smtpAddress = SPContext.Current.Web.Site.WebApplication.OutboundMailServiceInstance.Server.Address;
 
// Assign SMTP address
SmtpClient smtpClient = new SmtpClient();
smtpClient.Host = smtpAddress;
 
MailMessage mailMessage = new MailMessage(from, toRecipients);
mailMessage.Subject = subject;
 
// Add the Alternate view with the Mail message
mailMessage.AlternateViews.Add(avHtml);
mailMessage.IsBodyHtml = true;
 
smtpClient.Send(mailMessage);
 
 

Happy Coding!

Start User Profile Synchronization Service using PowerShell

Using Get-SPServiceInstance powershell commandlet you can get GUID details of all the Service instances running in your server. From that pick the GUID of your User Profile Synchronization service and use Start-SPServiceInstance commandlet to start the service in the server. 
 

Start-SPServiceInstance –Identity  GUID of the Service application
Sometimes your User Profile Synchronization service might stuck in “Starting” due to some issues in Synchronization. To Stop that service, use the below command
Stop-SPServiceInstance –Identity  GUID of the Service application

Calling a method in Parent page from User Control

User Controls in ASP.net is a reusable server control independent of Containing parent aspx page. When a User control embedded into a Aspx Page or other control, parent control will have access to the public properties, methods and objects of the child user control. There might be a scenario where, we need to call one of the method from Parent page or Parent control from the Child User control.

So to call the method in the Parent page or control we can create one Event Handler to our User control and add the Event Handler definition in parent control. Now from the User control we can trigger that Event which will then execute the Event Handler definition in Parent control,  then from there we can call the respective method in Parent Control.
1.       Add an Event to your User Control.

public event EventHandler CreateClick;

2.       Trigger the event from the User Control whenever required on particular action.

CreateClick(sender, e); 

Below is the Code behind of the User Control
 
  //Event Handler Declaration
 public event EventHandler CreateClick;
 
  //Triggering the Event in User control
 public void CallParentEvent(object sender, EventArgs e)
 {
    if (CreateClick != null)
    {
        CreateClick(sender, e);
    }
 }
 
  //Calling the Event trigger after action completed in User control
 protected void btnCreateCtrl_Click(object sender, EventArgs e)
 {
    //your code here then trigger the event
    CallParentEvent(sender, e);
 }
  

3.       Now register the User Control in your Parent page or control, while registering provide the Event Handler method for our custom event.
Below is the Parent Control page. You can also behind the Event handler in Page load in code behind.
 
<SP:CreateCtrl id="createCtrl" runat="server" OnCreateClick="CreateCtrl_Click"/>
 
 

4.       Now in the Parent control code behind, call the respective method inside the above mentioned Event Handler (CreateCtrl_Click)
 
protected void CreateCtrl_Click(object sender, EventArgs e)
{
    try
    {
        //Call the respective in Parent control
    }
    catch (Exception ex)
    {
    }
}
 

 

Friday, August 16, 2013

Get Social tags in SharePoint 2010

Social Tagging in SharePoint really helps in categorizing the information upon User’s interest with meaningful tag and also improves the quality of search and sharing the data with others.

SocailTagManager is a sealed class which contains the methods and properties used to handle social Tag data.
We are going to use GetTags method from SocialTagManager class which returns all the Tags based on the Item URL or User Profile. To know all the methods and preoperties of SocialTagManager class click here.
(Check inline comments for more details).
   
var type = typeof(SocialTagManager);
var methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance);
 
// Get the method from SocialTagManager sealed class which returns all the Tags
var method = methods.FirstOrDefault(m => m.ToString() == "Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.Uri, Int32, Microsoft.Office.Server.SocialData.SocialItemPrivacy)");
if (method != null)
{
SPServiceContext serviceContext = SPServiceContext.GetContext(ospWeb.Site);
SocialTagManager stm = new SocialTagManager(serviceContext);
 
// Get page URL
Uri uri = new Uri(listItemURL);
 
// Retrieve only the public tags
var itemTags = (SocialTag[])method.Invoke(stm, new object[] { uri, 1000, SocialItemPrivacy.PublicOnly });
 
// Get the count of the selected tag.
likeCount = itemTags.Count(t => t.Term.Name.ToLower() == "i like it");
 
// Filter the tags with the selected tag
var socialTags = itemTags.Where(t => t.Term.Name.ToLower() == "i like it");
 
string username ="";
foreach (var socialTag in socialTags)
{
    // Each tag will be mapped with the Profile ID
    var user = socialTag.Owner;
    string personalSite = user.PublicUrl.AbsoluteUri;   
    username = username + ";" + user.DisplayName;
}
 

 

Get Document Icon Image in SharePoint

While we Query the Documents from the Library and list out the items with the Custom branding in the Webpart, Users expects to see the related icon for the document to easily segregate and recognize the document. SharePoint makes it easier with a method in SPUtility class called SPUtility.MapToIcon() which gets the document icon file name, which is being used in SharePoint. These icons are stored in 14 hive images folder.

string docicon = SPUtility.ConcatUrls("/_layouts/images",
SPUtility.MapToIcon(item.Web, SPUtility.ConcatUrls(item.Web.
Url, item.Url), "", IconSize.Size16));
SPUtility.MapToIcon() method retrieves the document from a XML file called “Docicon.xml” which maintains the mapping for the document icons with the extension files under 14 hive XML folder. We can also use the same XML file to get the respective icon for the Document based on the document extension. In case if you are listing the documents from some other source other than document library.
   
  private string ReturnExtension(string fileExtension)
  {
     XmlDocument document = new XmlDocument();
 
     document.Load(SPUtility.GetGenericSetupPath(string.Empty) + @"\TEMPLATE\XML\DOCICON.XML");
 
     XmlNodeList xnList = document.SelectNodes("//DocIcons/ByExtension/Mapping[@Key='" + fileExtension.ToLower() + "']");
 
            string returnURL = "";
            if (xnList.Count > 0)
            {
                foreach (XmlNode xn in xnList)
                {
                    returnURL = xn.Attributes["Value"].Value;
                    break;
                }
            }
            else
            {
                returnURL = "icgen.gif";
            }
            return returnURL;
  }
 
Related Posts Plugin for WordPress, Blogger...