Showing posts with label SharePoint. Show all posts
Showing posts with label SharePoint. Show all posts

Friday, 13 July 2012

Using the AJAX Control Toolkit in SharePoint

The ASP.NET AJAX Control Toolkit provides a set of sample controls and extenders that makes it a snap to spice up your web site with rich functionality. Think about the Control Toolkit as a bunch of sexy controls which use the ASP.NET AJAX extensions, plus a framework to create a new even sexier control on your own. In this post I'll describe how you can make use of the Control Toolkit in your SharePoint 2007 sites, for example by using the SmartPart.

Actually SharePoint doesn't differ from any other ASP.NET web site to use the Control Toolit, there are only three things that you need to do:

  1. Make sure SharePoint has access to AjaxControlToolkit.dll
    You can do this in two ways: either you deploy the assembly to the Global Assembly Cache (GAC) or you put in the \BIN folder of the SharePoint site's folder.

  2. Add an assembly reference in the web.config (note: for the future versions of the Control Tookit, the version number can change!):
    <assemblies>
    ...
    <add assembly="AjaxControlToolkit, Version=1.0.10201.0, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"/>
    ....
    </assemblies>

  3. Add the tagprefix for the Control Toolkit in the web.config:
    <controls>
    ...
    <add namespace="AjaxControlToolkit" assembly="AjaxControlToolkit" tagPrefix="ajaxToolkit"/>
    ....
    </controls>


That's it! Now you can make use of the Control Toolkit coolness in your SharePoint 2007 sites! If you want to test if the Control Toolkit is working on your installation: I've upload a very small example to CodePlex.

Adding the left navigation menu to web part pages in SharePoint 2010

I taught a SharePoint 2010 super-user class last week, and the students experienced like so many before them that the web part page layouts which come with SharePoint 2010 removes the left hand navigation menu (the quick launch).
image
This is nothing new and it has been blogged about since 2007. But on my 15 minute Google spree this morning I could not find a recipe which worked 100% with SharePoint 2010,  so I will give it a try myself, and hopefully this can help some others in the future. I’m sure someone else has a complete post on this which I missed, but at least I have leveled up myself in the use of SharePoint Designer and modifying existing layouts instead of creating custom ones :)

Step 1 – Create a new web part page


Create a new web part page either via SharePoint or SharePoint Designer

Step 2 – Edit the page in SharePoint Designer


Edit your web part page in “Advanced Mode” in SharePoint Designer

image

Step 3 – Remove custom css


Around line 34 you will find a code block like the one below











1

2

3

4

5

6

7

8

9

10

11

12


<SharePoint:UIVersionedContent ID="WebPartPageHideQLStyles" UIVersion="4" runat="server">

<ContentTemplate>

<style type="text/css">

body #s4-leftpanel {

display:none;

}

.s4-ca {

margin-left:0px;

}

</style>

</ContentTemplate>

</SharePoint:UIVersionedContent>




Delete this code block.


Step 4 – Remove the overrides for the left column

Further down you will find three lines which prevents the left column for rendering.











1

2

3


<asp:Content ContentPlaceHolderId="PlaceHolderPageImage" runat="server"></asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderNavSpacer" runat="server"></asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderLeftNavBar" runat="server"></asp:Content>




Remove all three lines.


Step 5 –Save the page

Save and publish your page.


Step 6 – Preview your changes


image

Ajax Control Toolkit with SharePoint 2010

I had to use Ajax control toolkit with sharepoint and I had download the latest version from codeplex. We usually download latest versions of software because we believe that with latest version we can get more features and more bug-free. I had used Ajax Control Toolkit with SharePoint 2007 and it was much easier to configure and use Ajax Control Toolkit. With that belief in mind I had started using Ajax Control Toolkit in SharePoint 2010 downloading latest version for .net framework 3.5. But I failed  and after investigating I had found the following errors.


  • AjaxControlToolkit requires ASP.NET Ajax 4.0 scripts. Ensure the correct version of the scripts are referenced. If you are using an ASP.NET ScriptManager, switch to the ToolkitScriptManager in AjaxControlToolkit.dll.



  • Sys.registerComponent is not a function



The problem here is that latest versions of Ajax Control Toolkit is more optimized or targeted with .net framework 4.0. Even the Ajax control toolkit for .net framework 3.5 doesn’t work with SharePoint 2010. If you try to use Ajax Control Toolkit for 3.5 with SharePoint 2010, you may get the exceptions shown above.

How to make Ajax Control Toolkit working with SharePoint 2010?


Here are the steps to make Ajax Control Toolkit working with SharePoint 2010.

  1. Download Correct (compatible) version of Ajax Control Toolkit.Since current release of Ajax Control Toolkit doesn’t work with SharePoint 2010, you need to download previous release. Maybe Ajax Control Toolkit team will address this issue and we’ll be able to use current Toolkit version with SharePoint in future. Until the current release is made compatible, please download the SharePoint 2010 compatible Ajax Control Toolkit from here.

  2. Add AjaxControlToolkit.dll reference to your projectTo use the Ajax Control Toolkit in your SharePoint project, add reference to the AjaxControlToolkit.dll in your project. To use the Ajax Control Toolkit in any web part control add the following lines to register the Ajax Control Toolkit namespace at web.config
    <%@ Register Assembly="AjaxControlToolkit, Version=3.0.30930.28736,
    Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"
    Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>


  3. Remember, here version 3.x version of Ajax Control Toolkit is used instead 3.5.

  4. Add Ajax Control Toolkit ScriptManager in master page.Open the Master page in SharePoint Designer. By default the v4.Master file is the default master page can be found “_catalogs/masterpage” folder. Before modifying the master page, keep a backup copy.

    • First register the Ajax Control Toolkit namespace in the masterpage file by putting the following line at the top of the file:
      <%@ Register Assembly="AjaxControlToolkit, Version=3.0.30930.28736,
      Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"
      Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>


    • Then remove the ScriptManager registration from the master page by removing the following line:
      <asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="false"  
      EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true"/>


    • Finally Add the following line in place of the above line to register Ajax Control Toolkit
      <ajaxToolkit:ToolkitScriptManager id="ScriptManager" runat="server" EnablePageMethods="false" 
      EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true"/>




  5. Register Ajax Control Toolkit namespaces in SharePoint package DesignerFinally, you need to register the Ajax Control Toolkit namespace with SharePoint Package designer. Registering Ajax Control Toolkit namespaces will add Ajax Control Toolkit namespaces in web.config’s safecontrol list. First open the Package designer in Visual Studio (Package usually exists under Package folder in Visual Studio). And then click the “Advanced” button in package designer window as shown in the image below. In that advanced tab you can add/edit assemblies to be registered safe as part of the deployment of the solution package. Click Add ==> “Add Existing Assembly”. The following image shows wizard to follow.

    image

    Figure 1: Package Designer’s Advance tab

     

    In the “Add existing Assembly” window, add the following namespaces for Ajax Control Toolkit.






































    NamespaceType NameAssembly Name
    AjaxControlToolkit*AjaxControlToolkit
    AjaxControlToolkit.Design*AjaxControlToolkit
    AjaxControlToolkit.HTMLEditor*AjaxControlToolkit
    AjaxControlToolkit.HTMLEditor.Popups*AjaxControlToolkit
    AjaxControlToolkit.HTMLEditor.ToolbarButton*AjaxControlToolkit
    AjaxControlToolkit.MaskedEditValidatorCompatibility*AjaxControlToolkit

    The following image shows the “Add Existing Assembly” window for AjaxControlToolkit dll.

    image

    Figure 2: Add/Edit Existing Assembly window

     

    Now you can build and deploy the package and as a result of deployment, Ajax Control Toolkit namespaces will be registered as safe controls in web.config.


Conclusion


Its really hard to believe that Ajax Control Toolkit’s  latest version doesn’t work with SharePoint. We expect to have the latest version of Ajax Control Toolkit to be compatible with SharePoint 2010. Until then we might have to use an old version of Ajax Control Toolkit.

Wednesday, 16 May 2012

Sharepoint adding an item into a Picture Library



private byte [] StreamFile(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Open,FileAccess.Read);
// Create a byte array of file stream length
byte[] ImageData = new byte[fs.Length];
//Read  block of bytes from stream into the byte array
fs.Read(ImageData,0,System.Convert.ToInt32(fs.Length));
//Close the File Stream
fs.Close();
return ImageData;
}


// then use the following to add the file to the list
list.RootFolder.Files.Add(fileName, StreamFile(fileName));

Thursday, 3 May 2012

SharePoint: Don’t Forget to Uninstall the Feature

A question came up today that I thought was interesting and I hadn’t fully examined before.

If you retract and delete a solution in SharePoint 2007 without first uninstalling its features, are turds left behind?

The short answer: If you retract and delete a solution without deactivating and uninstalling the feature for each deployed scope, then turds are left behind both in the file system and in the config database.

To demonstrate this, I created a simple ItemEventReceiver, which uses a feature that is scoped to the web level.  I deploy the solution to a web application, and then it is available to the individual web sites to activate.  The code for this is unimportant, it’s just a solution that contains a feature scoped to the web level.  Here are the commands that I run to add my solution to the solution store, deploy it to a web application, and activate the feature for a web site within the web application.
stsadm -o addsolution -filename featuretester.wsp
stsadm -o deploysolution -name featuretester.wsp -allowGacDeployment -immediate -url http://moss-1
stsadm -o execadmsvcjobs
stsadm -o activatefeature -id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1

This is pretty standard stuff.  You probably already know that this creates a folder in the SharePoint root for our feature in the 12/Template/Features folder.

image

This also deploys our assembly to the Global Assembly Cache.

image

I wonder, though, does the feature exist only in the file system, or is it now part of the configuration database?  We check the configuration database, and yep… there’s an entry in the dbo.Features table for our feature.

image

Let’s see what happens if we activate our feature for a new web.
stsadm -o activatefeature -id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1/sitedirectory/team

As we expected, there are now two entries in the dbo.Features table.

image

Cleaning It Up The Right Way


Cleaning this up the right way is simple, we reverse all of our steps until now.  We need to deactivate the feature for each scope that we activated it for.
stsadm –o deactivatefeature –id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1
stsadm –o deactivatefeature –id fb9375d5-07ae-4835-b64c-83441c806691 -url http://moss-1/sitedirectory/team
stsadm –o uninstallfeature –id fb9375d5-07ae-4835-b64c-83441c806691

This will remove the entries from the configuration database and remove the entries from the file system in a supported manner.

What Happens if I Don’t Clean It Up The Right Way?


OK, now our real question.  Imagine we are still at the point where everything is deployed and activated.   We now have artifacts in the configuration database, and we have artifacts in the file system for every server in our farm.  What happens if we retract the solution and delete it?  Are turds left behind in the database and file system, or does SharePoint get rid of them for us?
stsadm -o retractsolution -name featuretester.wsp -immediate -url http://moss-1
stsadm -o exeadmsvcjobs
stsadm -o deletesolution -name featuretester.wsp

Here, we are retracting the solution from the web application and then deleting the solution from the solution store.  Let’s go check our artifacts on the server again to see what remains.

First, we look in the file system.  Hmm… the files are still there.

image

I know what you’re thinking, “so what?  they’re just files and folders.”  Fair enough, simply adding folders and files to the SharePoint root doesn’t do anything unless we tell SharePoint about it using an stsadm command.  Let’s go look at the Global Assembly Cache.

image

As you can see, the entry for our assembly is no longer in the GAC.  When we deleted the solution, the assembly was removed as part of the process (just as it is added when you call addsolution).

OK, so far it left behind files and folders, removed an entry from the GAC… is it clean?  Well, no.  SharePoint still has pointer records to the features in the configuration database.

image

At this point you may be thinking, “so what?  it left behind turds, but my farm is still running ok.”  Effectively, all we did was remove the DLL from the GAC and the WSP from the solution store.  The individual web sites still think there’s an ItemEventReceiver deployed.  That’s why we find the following types of errors when we go to a list where an ItemEventReceiver was bound
02/02/2011 22:40:54.78    w3wp.exe (0x193C)    0x1EDC    Windows SharePoint Services    General    75fe    High    Failed to determine definition for Feature with ID 'fb9375d5-07ae-4835-b64c-83441c806691'.  Skipping this feature for element querying consideration.

What’s happening is that there is a feature that is orphaned because its implementation is missing.  It shows up in the ULS log to let us know that it thought there was a feature deployed here, but something’s gone wrong.

Let’s look at one more thing… upgrading.  After SP2 for SharePoint 2007, a new command was added to stsadm to check for potential upgrade issues.  We run the command:
stsadm -o preupgradecheck

This is a benign operation, meaning it makes no changes to your farm at all.  It simply runs through a list of known issues that occur when upgrading from SharePoint 2007 to SharePoint 2010 and validates your farm.  You can see in the command window output that we have one error, colored red.

image

After the tool is run, it generates a .HTM file that describes the errors it encountered and provides more information on each potential issue.

image

Right there at the top, we see that our missing feature has caused a potential blocking issue for upgrade.

What About SharePoint 2010?


Oh, astute reader!  You are thinking about the upgrade process and wondering if this has been “fixed” in SharePoint 2010.  The first thing to address is that there’s really nothing to fix, as this isn’t a bug, it’s working just as it was intended to.  The proper sequence is to deactivate and uninstall the feature, as shown in the section above “Cleaning It Up the Right Way”.  This behavior did not change for stsadm commands in SharePoint 2010, they remain unchanged so that administrators can continue managing their farms without completely changing all of their scripts.

But wait, SharePoint 2010 has all these great PowerShell cmdlets!  Yes, that’s true, there are a ton of new PowerShell cmdlets that give you even greater flexibility for managing SharePoint.  But the simple design fact remains that you still have to explicitly deactivate the feature at the specified scope using the cmdlet Disable-SPFeature. Once the feature has been deactivated at the given scope, you can use the new PowerShell cmdlet “Remove-SPSolution” that collapses the minimum of 3 separate stsadm commands into 1 single PowerShell cmdlet that removes the solution from the solution store.

How to calculate Age using Calculated Value of a Column

Created a calculated column called "Today Date", but this column will not be displayed in any of the views..
the formula is as follow:
=DATE(YEAR(Modified), MONTH(Modified),DAY(Modified)
initially i thought that this formula would auto-update today's date and store it inside this column, but i was wrong *ah wells*

next, i have a calculated column called "Their Age" and "Their Birthday"
the formula is as follow:
=DATEDIF([Their Birthday],Today Date,"y")
although it does return a age, it uses the date difference of "The date when u entered the value" and "Their date of birth"



try this formula:
   =FLOOR(DATEDIF(DOB,Modified,"d")/365,1)

hopefully it works :x

How to upload a user profile photo programmatically

Updated No. 1: Changes required by SP 2010 RTM.

Updated No. 2: Method added to set the picture URL property for the user profile.

On the MSDN forum I’ve met a question that ask about how can one upload and set user profile pictures programmatically. I did a little research on the area and found another thread with the same question but I think the accepted answer of Chakkaradeep Chandran really does not answer the question, as it simply sets the image in the profile through the PictureUrl profile property, but does nothing related to upload and image resizing.

I admit the later tasks are not trivial although definitely not impossible through some hacking with Reflection. It is required since the methods we need (LoadPictureLibraryInternal, CreateThumbnail, GetSubfolderForPictures) are internal and private members of the ProfileImagePicker and UserProfilePhotos classes (later class is internal itself as well). So if you don’t mind this kind of dirty code, here is the solution for the question.

You should create a console application and add references to System.Drawing, System.Web, Microsoft.SharePoint, Microsoft.SharePoint.Portal, Microsoft.Office.Server and Microsoft.Office.Server.UserProfiles assemblies.

Next, use the code below:


  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Drawing;

  6. using System.Reflection;

  7. using Microsoft.SharePoint;

  8. using Microsoft.SharePoint.Portal.WebControls;

  9. using System.IO;

  10. using Microsoft.Office.Server.UserProfiles;

  11. namespace UploadProfileImage

  12. {

  13.     class Program

  14.     {

  15.         static void Main(string[] args)

  16.         {

  17.             Program prog = new Program();

  18.             prog.UploadProfileImages();

  19.         }

  20.         private void UploadProfileImages()

  21.         {

  22.             // my site host url

  23.             String url = "http://sp2010/profiles/host";

  24.             using (SPSite site = new SPSite(url))

  25.             {

  26.                 using (SPWeb web = site.OpenWeb())

  27.                 {

  28.                     ProfileImagePicker profileImagePicker = new ProfileImagePicker();

  29.                     InitializeProfileImagePicker(profileImagePicker, web);

  30.                     SPFolder subfolderForPictures = GetSubfolderForPictures(profileImagePicker);

  31.                     // repeat this block if you have more images and users

  32.                     // your account name

  33.                     String accountName = @"domain\administrator";

  34.                     // path to image file

  35.                     String imageFilePath = @"C:\Temp\AdminAvatar.jpg";

  36.                     UploadPhoto(accountName, imageFilePath, subfolderForPictures, profileImagePicker);

  37.                     SetPictureUrl(accountName, subfolderForPictures);

  38.                     // repeat block finished

  39.                 }

  40.             }

  41.         }

  42.         private void SetPictureUrl(string accountName, SPFolder subfolderForPictures)

  43.         {

  44.             Console.WriteLine("Setting profile image for user '{0}'", accountName);

  45.             SPSite site = subfolderForPictures.ParentWeb.Site;

  46.             UserProfileManager userProfileManager = new UserProfileManager(SPServiceContext.GetContext(site));

  47.             UserProfile userProfile = userProfileManager.GetUserProfile(accountName);

  48.             string fileNameWithoutExtension = GetFileNameFromAccountName(accountName);

  49.             string pictureUrl = String.Format("{0}/{1}/{2}_MThumb.jpg", site.Url, subfolderForPictures.Url, fileNameWithoutExtension);

  50.             userProfile["PictureUrl"].Value = pictureUrl;

  51.             userProfile.Commit();

  52.         }

  53.         private void UploadPhoto(string accountName, string imageFilePath, SPFolder subfolderForPictures, ProfileImagePicker profileImagePicker)

  54.         {

  55.             Console.WriteLine("Uploading image '{0}' for user '{1}'", imageFilePath, accountName);

  56.             if (!File.Exists(imageFilePath) || Path.GetExtension(imageFilePath).Equals(".gif"))

  57.             {

  58.                 Console.WriteLine("File '{0}' does not exist or has invalid extension", imageFilePath);

  59.             }

  60.             else

  61.             {

  62.                 string fileNameWithoutExtension = GetFileNameFromAccountName(accountName);

  63.                 FileStream file = File.Open(imageFilePath, FileMode.Open);

  64.                 BinaryReader reader = new BinaryReader(file);

  65.                 if (subfolderForPictures != null)

  66.                 {

  67.                     // try casting length (long) to int

  68.                     byte[] buffer = reader.ReadBytes((int)file.Length);

  69.                     int largeThumbnailSize = 0×90;

  70.                     int mediumThumbnailSize = 0×60;

  71.                     int smallThumbnailSize = 0×20;

  72.                     using (MemoryStream stream = new MemoryStream(buffer))

  73.                     {

  74.                         using (Bitmap bitmap = new Bitmap(stream, true))

  75.                         {

  76.                             CreateThumbnail(bitmap, largeThumbnailSize, largeThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_LThumb.jpg");

  77.                             CreateThumbnail(bitmap, mediumThumbnailSize, mediumThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_MThumb.jpg");

  78.                             CreateThumbnail(bitmap, smallThumbnailSize, smallThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_SThumb.jpg");

  79.                         }

  80.                     }

  81.                 }

  82.             }

  83.         }

  84.         private void InitializeProfileImagePicker(ProfileImagePicker profileImagePicker, SPWeb web)

  85.         {

  86.             Type profileImagePickerType = typeof(ProfileImagePicker);

  87.             FieldInfo fi_m_objWeb = profileImagePickerType.GetField("m_objWeb", BindingFlags.NonPublic | BindingFlags.Instance);

  88.             fi_m_objWeb.SetValue(profileImagePicker, web);

  89.             MethodInfo mi_LoadPictureLibraryInternal = profileImagePickerType.GetMethod("LoadPictureLibraryInternal", BindingFlags.NonPublic | BindingFlags.Instance);

  90.             if (mi_LoadPictureLibraryInternal != null)

  91.             {

  92.                 mi_LoadPictureLibraryInternal.Invoke(profileImagePicker, new object[] { });

  93.             }

  94.         }

  95.         public SPFile CreateThumbnail(Bitmap original, int idealWidth, int idealHeight, SPFolder folder, string fileName)

  96.         {

  97.             SPFile file = null;

  98.             // hack to get the Microsoft.Office.Server.UserProfiles assembly

  99.             Assembly userProfilesAssembly = typeof(UserProfile).Assembly;

  100.             // or assuming you know all the details of the assembly

  101.             // Assembly userProfilesAssembly = Assembly.Load(“Microsoft.Office.Server.UserProfiles, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c”);

  102.             // UserProfilePhotos is internal class,

  103.             // so you cannot get it directly from Visual Studio

  104.             Type userProfilePhotosType = userProfilesAssembly.GetType("Microsoft.Office.Server.UserProfiles.UserProfilePhotos");

  105.             MethodInfo mi_CreateThumbnail = userProfilePhotosType.GetMethod("CreateThumbnail", BindingFlags.NonPublic | BindingFlags.Static);

  106.             if (mi_CreateThumbnail != null)

  107.             {

  108.                 file = (SPFile)mi_CreateThumbnail.Invoke(null, new object[] { original, idealWidth, idealHeight, folder, fileName });

  109.             }

  110.             return file;

  111.         }

  112.         private SPFolder GetSubfolderForPictures(ProfileImagePicker profileImagePicker)

  113.         {

  114.             SPFolder folder = null;

  115.             Type profileImagePickerType = typeof(ProfileImagePicker);

  116.             MethodInfo mi_GetSubfolderForPictures = profileImagePickerType.GetMethod("GetSubfolderForPictures", BindingFlags.NonPublic | BindingFlags.Instance);

  117.             if (mi_GetSubfolderForPictures != null)

  118.             {

  119.                 folder = (SPFolder)mi_GetSubfolderForPictures.Invoke(profileImagePicker, new object[] { });

  120.             }

  121.             return folder;

  122.         }

  123.         private string GetFileNameFromAccountName(string accountName)

  124.         {

  125.             string result = accountName;

  126.             string charsToReplace = @"\/:*?""<>|";

  127.             Array.ForEach(charsToReplace.ToCharArray(), charToReplace => result = result.Replace(charToReplace, '_'));

  128.             return result;

  129.         }

  130.     }

  131. }


 

 

Happy profile image uploading!

You should know that user profile photos are stored in three different resolutions in a folder called Profile Pictures in the User Photos image library on the My Site Host site.

Note, that I found a bit strange dependency of behavior on the size of the photo you set in the PictureUrl profile property when it is about removing the profile image. It seems to be a minor issue, but might have significant impact on your solution.

When you upload the profile photo via the Edit User Profile user interface and then removes that also via the UI, then all of the image versions (I mean the three different resolution) are deleted. and using code. I consider this to be the standard behavior as it is not desired to leave orphaned files in the User Photos image library.

First I’ve tried to set the large image (_LThumb.jpg) from code in the PictureUrl profile property, but when I was to remove the image from the UI then only the large image was deleted, medium and small images remained in the image library. After checking the effect of setting the image from the UI I found, that it sets the PictureUrl property  to the medium image (_MThumb.jpg), so I modified the code accordingly. Now all of the images were removed as expected.

Get Current User Email, Login, Display Name Details

working on a requirement on getting the current user's Email id in efficient way.
The normal code which microsoft given fails:
SPWeb site = SPContext.Current.Web;
SPUser user = site.CurrentUser;
string DisplayName = user.Name;
string Login = user.LoginName;
string EMail = user.Email;
string User Notes = user.Notes;

Because most of the users who don't have access to All sites won't give details of their email by the code given. If you are wondering what is all about the difference between All users see below:
SPWeb site = SPContext.Current.Web;
SPUserCollection c1 = site.Users;
SPUserCollection c2 = site.AllUsers;
SPUserCollection c3 = site.SiteUsers;


The code gives 3 types of different user collection so i guess the user who logged in and didn't find his email by the code above belongs to one of this group.
The difference between these SPUserCollection is copied from MSDN.:
The Users collection has the smallest membership of these three collections. This collection includes all the external principals that have been explicitly assigned permissions within the current site.

The AllUsers collection includes all members of the Users collection, plus external users that have accessed objects within the site using implicit permissions through group or role membership. For example, imagine a user named Brian with the login of LITWAREINC\BrianC that has never been given explicit permissions to access a site and view a particular list. However, he might still be able to view the list because of his membership within an Active Directory group that has been configured with list view permissions. When Brian first accesses the site or one of its objects (say, a list using implicit permissions), he is added as a member of the AllUsers collection, but he is not added as a member of the Users collection.

The SiteUsers collection is an aggregation that combines membership for each AllUsers collection within the current site collection. The membership of this collection includes all external principals that have been assigned permissions to any object within the site collection as well as all external users that have been granted access to any of the site collection's objects using implicit permissions.

I used a basic way to get the current user using (context of control HTTPCONTEXT) Context.User.Identity.Name or Page.User.Identity.Name which does the same httpcontext.

After we get the current user login i can pass it to the magic of another Class in sharepoint object Model which brings the user details.

using Microsoft.SharePoint.Utilities;

SPWeb osite = SPContext.Current.Web;

SPPrincipalInfo prin = SPUtility.ResolvePrincipal(osite,Context.User.Identity.Name , SPPrincipalType.All, SPPrincipalSource.All, osite.AllUsers, false);
writer.Write(prin.Email);

using this method u can also search the user by their Email ID, or their Display name. its a cool method who does the search on multiple fields.

Wednesday, 18 April 2012

Ribbon customization : Adding functionality to Ribbon Button

SharePoint 2010 Ribbon customization : Add functionality to the button


pre-requisite
Ribbon Basics

Writing the script in scriptblock
In the basics you saw the command action of the button firing a javascript that was inline. Supposingly if you wanted to call a block of JS code .. you cannot write it inline. For that you will have to use a ScriptBlock attribute of the CustomAction node like the following..

Writing the script in an external js file
The same javascript function can be written in an external *.js file. To achieve this, right-click on the project and Add the layouts mapped folder. In the subfolder under the layouts folder, add a js file.

Next, modify the elements.xml as below

done.


Enabling EcmaScript(JavaScript) IntelliSense in VS2010
To add intellisense to SP COM, add the following lines at the top of the js file..



/// <reference name="MicrosoftAjax.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />



After adding the above lines, you will notice that the intellisense for the sharepoint client object model is active.

Using Client Object Model to dispplay SharePoint Status bar
Lets modify the HelloWorld function to show the message in the status bar of SharePoint. Below is the modified javascript..

/// <reference name="MicrosoftAjax.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />

/// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />


function HelloWorld() {

    this.statusID = SP.UI.Status.addStatus("Hello World",

"A message from Mano <a href='#' onclick='javascript:closeStatus();return false;'>Close</a>.", true);

    SP.UI.Status.setStatusPriColor(this.statusID, "green");

}


function closeStatus() {

    SP.UI.Status.removeStatus(this.statusID);

}


Using Client Object Model to display current selected listItems and the list id
Now that we are able to access the SP namespace, we should be able to access the SharePoint entities like the site and the web for our use. In the code snippet we will be looking at how to get the selected items and the list Id from where these items are displayed.



function ShowListInformation() {

    // get all selected items

    var items = SP.ListOperation.Selection.getSelectedItems();

    var itemCount = CountDictionary(items);

    

    // get the current list

    var listID = SP.ListOperation.Selection.getSelectedList();


    // Remove all previous status

    SP.UI.Status.removeAllStatus(false);


    this.statusID = SP.UI.Status.addStatus("Selection Information", "Item Count : "

+ itemCount.toString() + " List ID : " + listID.toString(), true);

    SP.UI.Status.setStatusPriColor(this.statusID, "blue");

}





Note: Make sure that you change the CommandAction attribute in the elements.xml with the new function
Why is the above code important ?
This code opens a whole new arena for us to play with , including to enable the button based on a condition, which we will see as we dwell deeper.

Tip: Make sure that the latest code is used to render the button
1. Make sure the app pool is recycled
2. Make sure that the browser cache is cleared

Code to Hide the Ribbon and Site Actions Menu for Anonymous Users

In SharePoint 2010 sites that use the publishing infrastructure have an option on the Navigation Settings page to hide the ribbon by default.



Other sites lack this functionality as does SharePoint Foundation. However, the code to do the hiding is simple:
public void HideRibbonForAnon() { SPRibbon current = SPRibbon.GetCurrent(this.Page); if (current != null && !this.Page.Request.IsAuthenticated) { current.CommandUIVisible = false; SiteActions actions = SiteActions.GetCurrent(this.Page); if (actions != null) { actions.Visible = false; } HideStatusBar(); } } 

internal void HideStatusBar() { string script = "document.onreadystatechange=fnRemoveAllStatus; function fnRemoveAllStatus(){removeAllStatus(true)};"; this.Page.ClientScript.RegisterClientScriptBlock(typeof(HideTheRibbon), "statusBarRemover", script, true); } 

InfoPath Forms Server, Data Sources and Authentication



OK, So I put together a nice little InfoPath form, nothing too flash – it collects some data about a site and sub sites and then goes ahead and calls a web service to create the site, sub sites and sets permissions.

Problem is that while the form works fine in the InfoPath client if I try to use it as a browser enabled form in SharePoint (which I need to do) it fails to make the data connection calls.

It’s a permission thing, basically SharePoint doesn’t pass the user credentials to the web service so the web service denies the connection.

Trying to work around it, I first thought it was to do with form trust so I fully trusted the form which meant that when I deployed it it forced me to deploy it as an administrator approved form. In simple terms it saves the form on the file system, the administrator uploads it to the central form template library (Central Administration > Application Management > Manage Form Templates) and deploys it to a site collection. This puts a feature wrapper around the form and deploys it as a content type. Apply the content type to a library and hey presto…

So I did that and it still didn’t work, that’s when I figured it was authentication and not trust that was causing the issue.

Basically to use data connections in InfoPath Forms Server (IFS from now on) you will need to create a Universal Data Connection (UDC) and store it in a Data Connection Library (DCL)… ’nuff acronyms ;-)

  • UDC = a file that stores (in plain text!) authentication details and the details of the web service (or whatever) you need to connect with.

  • DCL = just like it sounds this is where you put the UDC


So how do you write a UDC?


There’s a decent overview here: http://blogs.msdn.com/infopath/archive/2006/10/02/Data-Connections-in-Browser-Forms.aspx and if you’re anything like me you’ll want to see an example so here we go:
<?xml version="1.0" encoding="UTF-8"?>
<?MicrosoftWindowsSharePointServices ContentTypeID="0×010100B4CBD48E029A4ad8B62CB0E41868F2B0"?>
<udc:DataSource MajorVersion="2" MinorVersion="0" xmlns:udc="
http://schemas.microsoft.com/office/infopath/2006/udc">
<udc:Name>CreateSite</udc:Name>
<udc:Description>CreateSite</udc:Description>
<udc:Type MajorVersion="2" MinorVersion="0" Type="WebService">
<udc:SubType MajorVersion="0" MinorVersion="0" Type=""/>
</udc:Type>
<udc:ConnectionInfo Purpose="ReadWrite">
<udc:WsdlUrl>
http://hp-vs-moss2007:555/HP.WebServices.CreateWorkspace.asmx?wsdl</udc:WsdlUrl>
<udc:SelectCommand>
<udc:ServiceUrl>
http://hp-vs-moss2007:555/HP.WebServices.CreateWorkspace.asmx</udc:ServiceUrl>
<udc:SoapAction>HP.WebServices.CreateWorkspace/Create</udc:SoapAction>
</udc:SelectCommand>
</udc:ConnectionInfo>
</udc:DataSource>

You’ll notice that in my example above there are no authentication details. Well…that’s because I forgot to put them in! And what I actually found was that simply by using the UDC method authentication started working, I haven’t had time to look into this but I assume this is because by the very virtue of using a UDC connection held in a SharePoint library PassThrough authentication is being used. I then started adding some cod ethat runs under elevated privileges and ran into some problems, so put the authentication details back in again ala:

How do you ‘do’ one of these DCL things?


That’s easy ;-) It’s just like a document library in SharePoint. Go the the root of your site collection (that usually a site like http://server/sites/xxxx) and click Site Actions then Data Connection Library, give it a name and hey presto.

Now upload your UDC to your DCL and remember to approve the UDC.

Getting it to work with Infopath


This bit is the simple bit

  1. You create a new data connection (Tools -> Data Connections -> New -> Search for Connections on MOSS -> Add your site -> Select the UDC)

  2. And then use it as you would any other data connection


So what have you achieved?


Well you’ve kind of abstracted web service and InfoPath form so you now need to go through the UDC to get to the web service calls, of course you can go direct to the web service for normal InfoPath forms but not for web based forms. Is it good thing? Not sure, I’ve read posts saying that it makes things better because your connections are in a central library and can be shared between forms and I guess that’s something but then I can secure my form library, web service, web application etc anyway so do I really need another layer of security?

Anyway, it’s the only way it works so you’re stuck with it for now.

 

Ribbon customization : Hide Ribbon Programatically

Ribbon customization : how to hide Ribbon programatically


programatically hide a Ribbon



public void HideRibbon()

{

SPRibbon current = SPRibbon.GetCurrent(this.Page);


if (current != null && !this.Page.Request.IsAuthenticated)

{

current.CommandUIVisible = false;

}

}


programatically hide a single ribbon button



public void HideRibbonItem()

{

//if this is a System.Web.UI.Page

SPRibbon ribbon = SPRibbon.GetCurrent(this);

ribbon.TrimById("Ribbon.ListItem.New.NewFolder");

}


programatically hide the status bar




public void HideStatusBar()

{

string script = "document.onreadystatechange=fnRemoveAllStatus; function fnRemoveAllStatus(){removeAllStatus(true)};";

this.Page.ClientScript.RegisterClientScriptBlock(typeof(HideTheRibbon), "statusBarRemover", script, true);

}





programatically hide the SiteActions Menu





public void HideSiteActionsMenu()

{

SiteActions actions = SiteActions.GetCurrent(this.Page);


if (actions != null && !this.Page.Request.IsAuthenticated)

{

actions.Visible = false;

}

}



Tuesday, 17 April 2012

Display SharePoint User Profile Picture - C#

SPWeb oWeb = currSite.OpenWeb();
SPList oList = oWeb.SiteUserInfoList;
SPListItem userInfo = oList.Items.GetItemById(SPContext.Current.Web.CurrentUser.ID);
imgPic.ImageUrl = userInfo["Picture"].ToString();

 

 

or

SPServiceContext context = SPServiceContext.GetContext(SPContext.Current.Site);
UserProfileManager profileManager = new UserProfileManager(context);
UserProfile theProfile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
//theProfile["PictureUrl"].Value = "<img url>";
litPic.Text = Convert.ToString(theProfile["Picture"]);
theProfile.Commit();
litPic.Text = "<img src=" + userLI["Picture"].ToString() + " />".ToString();

//userInfo.Update();

Get User Profile Details Programmatically - SharePoint

In WSS, there is a basic list called the ‘User Information List’ which holds some profile details about the users themselves. These details can be viewed/edited from the ‘My Settings’ screen.

ms

WSS holds the following user details:

  • Account (Login Name)

  • Name (Display Name)

  • E-Mail

  • About Me

  • Picture

  • Department

  • Job Title

  • SIP Address


You can get a reference to any of these properties in code simply by querying the list with the ID of the required SPUser:

e.g.

using (SPSite Site = new SPSite(“Site URL”))

{
using (SPWeb Web = Site.OpenWeb())
{


SPList UserInfoList = Web.Lists[“User Information List”];


SPUser User = Web.Users.GetByID(1); – Put the User ID Here


SPListItem UserItem = UserInfoList.GetItemById(User.ID);


UserItem[“Department”] = “Department Name”;


}


}

Using this list you can set any of the values as required or simply retrieve the stored values. I used the above to get a reference to the ‘Picture’ which is stored as a URL.

Monday, 16 April 2012

upload a file to a Web server in ASP.NET by using Visual C# .NET

Complete code listing


WebForm1.aspx




<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="CSharpUpload.WebForm1" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" enctype="multipart/form-data" runat="server">
<INPUT type=file id=File1 name=File1 runat="server" >
<br>
<input type="submit" id="Submit1" value="Upload" runat="server" NAME="Submit1">
</form>

</body>
</HTML>



 

WebForm1.aspx.cs




using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace CSharpUpload
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.HtmlControls.HtmlInputFile File1;
protected System.Web.UI.HtmlControls.HtmlInputButton Submit1;

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}

#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Submit1.ServerClick += new System.EventHandler(this.Submit1_ServerClick);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void Submit1_ServerClick(object sender, System.EventArgs e)
{
if( ( File1.PostedFile != null ) && ( File1.PostedFile.ContentLength > 0 ) )
{
string fn = System.IO.Path.GetFileName(File1.PostedFile.FileName);
string SaveLocation = Server.MapPath("Data") + "\\" + fn;
try
{
File1.PostedFile.SaveAs(SaveLocation);
Response.Write("The file has been uploaded.");
}
catch ( Exception ex )
{
Response.Write("Error: " + ex.Message);
//Note: Exception.Message returns a detailed message that describes the current exception.
//For security reasons, we do not recommend that you return Exception.Message to end users in
//production environments. It would be better to return a generic error message.
}
}
else
{
Response.Write("Please select a file to upload.");
}
}
}
}


Uploading images into picture library in sharepoint using c#

spSite objSite = new SPSite(SPContext.Current.Web.Url);


try
{
byte[] imageData = null;
if (flUpload != null)
{
// This condition checks whether the user has uploaded a file or not
if ((flUpload.PostedFile != null) && (flUpload.PostedFile.ContentLength > 0))
{
Stream MyStream = flUpload.PostedFile.InputStream;
long iLength = MyStream.Length;
imageData = new byte[(int)MyStream.Length];
MyStream.Read(imageData, 0, (int)MyStream.Length);
MyStream.Close();
string filename = System.IO.Path.GetFileName(flUpload.PostedFile.FileName);
using (SPWeb myWeb = objSite.OpenWeb())
{
SPPictureLibrary pic = (SPPictureLibrary)myWeb.Lists["Images"];//Images is the picture library name
SPFileCollection filecol = ((SPPictureLibrary)myWeb.Lists["Images"]).RootFolder.Files;//getting all the files which is in pictire library
filecol.Add(filename , imageData);//uploading the files to picturte library
}
}
}
lblMessage.Text = "Uploaded successfully";
}
catch (Exception ex)
{
Response.Write(ex.Message);
}

Friday, 13 April 2012

Update email address at SQL server Database in FBA (SharePoint C#)

try
{
MembershipUser usr = System.Web.Security.Membership.Providers["FBAUser"].GetUser(SPContext.Current.Web.CurrentUser.LoginName, true);
usr.Email = "emailaddress@email.com";
System.Web.Security.Membership.UpdateUser(usr);
Msg.Text += "Email is Changed at FBA <br/>";
}
catch (Exception ex)
{
Msg.Text += " *Email is not updated at FBA <br/>" + ex.Message;
}

Get the current username from windows authentication or form base authentication

string userName = " ";
SPContext currentContext;
try
{
currentContext = SPContext.Current;
}
catch (InvalidOperationException)
{
currentContext = null;
}
if (currentContext != null && currentContext.Web.CurrentUser != null)
{
//userName = SPContext.Current.Web.CurrentUser.LoginName;
userName = HttpContext.Current.User.Identity.Name;
}
else
{
WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();
if (windowsIdentity != null)
{
userName = windowsIdentity.Name;
}
}
return userName;

Update the user information list in SharePoint at User Profile C#

SPSite spsite = SPContext.Current.Site;
SPWeb spweb = spsite.OpenWeb();
SPList splist = spweb.SiteUserInfoList;
SPListItem userInfo = splist.Items.GetItemById(SPContext.Current.Web.CurrentUser.ID);
try{
Msg.Text = " ";
if ((txtFirstName.Text != "") || (txtLastName.Text != ""))
{
userInfo["Title"] = txtFirstName.Text + " " + txtLastName.Text;
}
if (txtEmail.Text != "")
{
userInfo["Work e-mail"] = txtEmail.Text;
}
if (txtFirstName.Text != "")
{
userInfo["First name"] = txtFirstName.Text;
}
if (txtLastName.Text != "")
{
userInfo["Last name"] = txtLastName.Text;
}
if (txtMobilePhone.Text != "")
{
userInfo["Mobile phone"] = txtMobilePhone.Text;
}
if (txtWorkPhone.Text != "")
{
userInfo["Work phone"] = txtWorkPhone.Text;
}
if (txtUsername.Text != "")
{
userInfo["User name"] = txtUsername.Text;
}
Msg.Text += "Profile Details are updated";
userInfo.Update();
}
catch{
Msg.Text = "Profile Details are not updated";
}

Update the user profile picture in SharePoint

SPServiceContext context = SPServiceContext.GetContext(SPContext.Current.Site);
UserProfileManager profileManager = new UserProfileManager(context);
UserProfile theProfile = profileManager.GetUserProfile(SPContext.Current.Web.CurrentUser.LoginName);
theProfile["PictureUrl"].Value = "<img url>";
theProfile.Commit();