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;
  }
 

Get User Profile properties in SharePoint

User Profile Service application maintains User Profiles for all the Users in SharePoint and synchronizes with the Active Directory or with your Custom DB based on the configuration. If you want to access the User Profile properties from Web Application make sure your Web Application is configured with any of the User Profile Service application.

Check here to see Creation of User Profile Service application.
Follow below steps to check the Service connections.
1.       Navigate to Central Administration à Application Management à Manage Web applications
2.       Select your Web Application and Click on the Service Connections from Ribbon.

 
3.       Make sure User Profile Service application is selected from the list and click OK. 

To access a specific user profile, we need call the UserProfileManager class to create an object  for the UserProfile and to get the Properties of the User from the User Profile Database.

   
SPSecurity.RunWithElevatedPrivileges(delegate()
 {
    using (SPSite site = new SPSite(web.Url))
    {
      using (SPWeb objWeb = site.OpenWeb())
      {
         string strDisplayName = string.Empty;
         string strMySiteURL = string.Empty;
         string strEmail = string.Empty;
         SPServiceContext sc = SPServiceContext.GetContext(web.Site);
 
         //Get the User Profile Service configured to the current site
         UserProfileManager objUserProfileManager = new UserProfileManager(sc);
         UserProfile profile = null;
                           
         //Check whether the specified User exists in the UserProfile
         if (objUserProfileManager.UserExists(accountName))
         {
             //Get the User Profile using the Profile Manager
             profile = objUserProfileManager.GetUserProfile(accountName);
           
             //Now you can get all the Properties of the User from this object
             strDisplayName = profile.DisplayName;
             strMySiteURL = profile.PublicUrl.ToString();
             strEmail = profile[“WorkEmail”].Value();
         }
      }
    }                           
 });
            
 

If you need full access for all the User Profiles, you need to have “Manage User Profile” rights. By default, everyone will have read access to all the User Profiles.

Create User Profile Service application in SharePoint 2010

The User Profile service application stores information about users in a central location. It maintains User Profiles for each User with detailed information maintained as User Properties. These User Profiles will be and synchronized with the Active Directory or with your Custom DB based on the configuration.  These Information will be useful for provisioning My Sites, enable social computing features such as social tagging and newsfeeds, and create and distribute profiles across multiple sites and farms, you must enable the User Profile service application.

Follow below steps to Create User Profile Service application.
1.       Navigate to Central Administration à Application Management à Manage Service Applications.
2.       Select New from the Ribbon and click on User Profile Service Application from the dropdown.

Note: Make Sure that “SharePoint Web Services root” application pool is running in IIS.


Fill-in the required information like Service application Name, application pool details and the Application pool account details.

(Note: It’s better to have separate account for this configuration, to track down the issues).

The Application Pool account which configure here must have the following privileges.

·         Farm Administrator
·         Local Administrator in the server where SharePoint is running as application server.
·         Log on locally policy in the server where SharePoint is running as application server.


Choose domain and username in site naming format if your application have more than one domain to avoid the Naming conflicts.

3.       SharePoint creates 3 different databases for storing the User Profile Information.
·         Profile database – Stores all the User Profile Properties.
·         Synchronization database – Stores all the configuration information for synchronizing profile data from external sources such as the Active Directory or BDC.
·         Social tagging database - Stores social tags and notes created by users. Each social tag and note is mapped with a tag owner.
4.       Once the User Profile Service application is created. We need to make sure the below Services are running in the server.
·         User Profile Service
·         User Profile Synchronization service 

5.       To check the above, again Navigate to Central Administration à Application Management à Manage Services on Server.


6.       Once the Services are the started in the Server, now we need to Create the Service Connections for Synchronizing the User Profiles from our Source like Active Directory.

7.       To Create a new Connection. Navigate to  Central Administration à Application Management à Manage Service applications and click on the newly created the Service application.


8.       Click on Configure Synchronization Connections link under Synchronization section. 
9.       Now Click on the Create New Connection link to create the connections.
 Fill-in all the required details
·         Connection Name: ADConnection
·         Forest Name: ad.local
·         Account Name: domainname\accname 

Specify the Provider name if you want to synchronize from any other source.

10.   Once done with creating the Synchronize Connections, now we are good to go to Start Full Synchronization. Select Start Full Synchronization link under Synchronization Section.

 

You can check the Profile Synchronization status in the Right section, where you get the more details about the User Profiles.

11.   Now configure the Incremental Synchronization which will make sure your User Profiles are up-to-date with Active Directory. Click on Configure Synchronization timer job link under Synchronization Section to change the occurrence of the Timer Job.
Related Posts Plugin for WordPress, Blogger...