Configuring Facebook Authentication in SharePoint 2010

I got a task to configure Facebook Authentication couple of days back. I explored couple of blogs like PointBridge and Osnapz , they are good blog posts it give you an idea how to do that but overall i didn’t find anything like a step by step guide for those users who are doing it first time. Also when i started configuring Facebook Authentication i came across several issues which serves a lot of time and eventually my whole day was spent doing that. Therefore, i thought to make a blog entry which provides Step to Step guide for configuring Facebook Authentication in SharePoint 2010.

Following are the steps to configure Facebook Authentication for SharePoint sites.

Step 1: Download and Install Components

  1. Download and Install Windows Identity Framework SDK from http://www.microsoft.com/download/en/details.aspx?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3a+MicrosoftDownloadCenter+(Microsoft+Download+Center)&utm_content=Google+Reader&id=4451
  2. Download Json.Net from
    http://json.codeplex.com/

Step 2: Create a new ASP.Net website

  1. Open Visual Studio and click on File> New Website
  2. Specify Website Name and path to the folder where you want to store the website and click on OK
  3. It will create a new Website.
  4. Now associate a certificate with this Website and enable SSL.
  5. Open IIS Manager by typing inetmgr from the run option in windows OS.
  6. Open Server Certificates and click on Create Self-Signed Certificate.
  7.  

     

  8. Specify certificate friendly name, click OK.
  9.  

     

  10. Certificate will be created. Now associate this certificate to your Website
  11. Right click on the Server in IIS and click on Add Website. Specify Site Name and Physical Path, Select Port and click on Ok. Your website will be hosted on IIS.
  12. Select Website and click on Bindings from the left Panel.
  13. Click on Add and select the type ‘Https’ and specify any port by default it uses 443 but you can assign any other port as well. Select certificate you just created and click OK.
  14. Now the server certificate has been associated with your website.
  15. Export this certificate and save it somewhere in your system. We need this when running power shell scripts.
  16. Now Open Visual Studio and change the Sever settings in the Property Pages of the website.
  17. Right click on your website and click on Property Pages
  18. Go to the Startup Options and select Use custom server option and specify the Website URL that is hosted on IIS (Use SSL one).
  19. Now navigate to your website and test it should be in working state and there should not be any issue.
  20.  

 

Step 3: Create an STS Site from ASP.Net website

 

  1. Go to the Visual Studio and right click on the Website project and click on Add STS Reference
  2. It will pop up a Wizard window just click Next.
  3. In the next window select “Create a New STS Project in the current Solution”.
  4. Click on Finish.
  5. You will notice a new Website will be added in the solution.
  6. Now Open the IIS Manager and change the physical path to the newly STS website.
  7. Just click on Website in the IIS Manager
  8. Click on Basic Settings from the Right Panel in IIS Manager
  9. Specify new path and click OK.
  10. Now Test your STS website it should run without any issue.

Step 4: Create Application in Facebook

  1. Navigate to http://facebook.com/developers
  2. Sign in with your account
  3. Create new Application using Create New Application option
  4. Provide name
  5. Click ok It will create a new application
  6. Now Click on Edit Setting and Specify your ASP.Net site URL. We need to specify this so it will redirect it to the default.aspx after successful authentication.
  7. Note Application Id and Secret Key that we will reference in the ASP.Net code.
  8. Now we are ready to move next on Step 5.
  9.  

Step 5: Execute Scripts on Power Shell

Open SharePoint 2010 Management Shell and execute following scripts in order.

  1. $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(“c:\yourexported_cert.cer”)
  2. $map1 = New-SPClaimTypeMapping “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication” -IncomingClaimTypeDisplayName “FacebookID” –SameAsIncoming
  3. $map2 = New-SPClaimTypeMapping -IncomingClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name” -IncomingClaimTypeDisplayName “Display Name” -LocalClaimType http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
  4. $realm = “urn:researchfacebook.com:facebook” (Specify any urn but note it)
  5. $signinurl = https://localhost:4431/Website_STS/ (Your ASP.Net website address)
  6. New-SPTrustedIdentityTokenIssuer -Name “Facebook” -Description “Facebook custom STS” -Realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map1,$map2 -SignInUrl $signinurl -IdentifierClaim $map1.InputClaimType
  7. New-SPTrustedRootAuthority -Name “Facebook custom STS token signing certificate” -Certificate $cert

 

Step 6: Modify Code and Edit Configuration file

1. Create a new oAuthFacebook.cs class and add it in the App_Code folder in the Website project.
Following is a code of oAuthFacebook.cs. Change the Yellow highlighted part according to your application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Collections.Specialized;
using System.IO;

///

/// Summary description for oAuthFacebook
///

public class oAuthFacebook
{
public enum Method { GET, POST };
public const string AUTHORIZE = “https://graph.facebook.com/oauth/authorize”;
public const string ACCESS_TOKEN = “https://graph.facebook.com/oauth/access_token”;
public const string CALLBACK_URL = “https://localhost:4431/Login.aspx”;

private string _consumerKey = “”;
private string _consumerSecret = “”;
private string _token = “”;

#region Properties

public string ConsumerKey
{
get
{
if (_consumerKey.Length == 0)
{
//Your application ID
_consumerKey = “000000000000000”;
}
return _consumerKey;
}
set { _consumerKey = value; }
}

public string ConsumerSecret
{
get
{
if (_consumerSecret.Length == 0)
{
//Your application secret key
_consumerSecret = “00000000000000000000000000000000”;
}
return _consumerSecret;
}
set { _consumerSecret = value; }
}

public string Token { get { return _token; } set { _token = value; } }

#endregion

///

/// Get the link to Facebook’s authorization page for this application.
///

/// The url with a valid request token, or a null string.
public string AuthorizationLinkGet()
{
return string.Format(“{0}?client_id={1}&redirect_uri={2}”, AUTHORIZE, this.ConsumerKey, CALLBACK_URL);
}

///

/// Exchange the Facebook “code” for an access token.
///

/// The oauth_token or “code” is supplied by Facebook’s authorization page following the callback.
public void AccessTokenGet(string authToken)
{
this.Token = authToken;
string accessTokenUrl = string.Format(“{0}?client_id={1}&redirect_uri={2}&client_secret={3}&code={4}”,
ACCESS_TOKEN, this.ConsumerKey, CALLBACK_URL, this.ConsumerSecret, authToken);

string response = WebRequest(Method.GET, accessTokenUrl, String.Empty);

if (response.Length > 0)
{
//Store the returned access_token
NameValueCollection qs = HttpUtility.ParseQueryString(response);

if (qs[“access_token”] != null)
{
this.Token = qs[“access_token”];
}
}
}

///

/// Web Request Wrapper
///

/// Http Method
/// Full url to the web resource
/// Data to post in querystring format
/// The web server response.
public string WebRequest(Method method, string url, string postData)
{

HttpWebRequest webRequest = null;
StreamWriter requestWriter = null;
string responseData = “”;

webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
webRequest.Method = method.ToString();
webRequest.ServicePoint.Expect100Continue = false;
webRequest.UserAgent = “[You user agent]”;
webRequest.Timeout = 20000;

if (method == Method.POST)
{
webRequest.ContentType = “application/x-www-form-urlencoded”;

//POST the data.
requestWriter = new StreamWriter(webRequest.GetRequestStream());

try
{
requestWriter.Write(postData);
}
catch
{
throw;
}

finally
{
requestWriter.Close();
requestWriter = null;
}
}

responseData = WebResponseGet(webRequest);
webRequest = null;
return responseData;
}

///

/// Process the web response.
///

/// The request object.
/// The response data.
public string WebResponseGet(HttpWebRequest webRequest)
{
StreamReader responseReader = null;
string responseData = “”;

try
{
responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
responseData = responseReader.ReadToEnd();
}
catch
{
throw;
}
finally
{
webRequest.GetResponse().GetResponseStream().Close();
responseReader.Close();
responseReader = null;
}

return responseData;
}
}

2. In this step we will replace the existing logic in the Login.aspx for Facebook Authentication
3. Open Login.aspx and replace with following code.

using System;
using System.Web.Security;
using System.Web;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public partial class Login : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e )
{
string url = string.Empty;
oAuthFacebook fbAuth = new oAuthFacebook();

if (Request[“code”] == null)
{
// Response.Redirect(“http://www.google.com”);
if (Request.QueryString[“ReturnUrl”] != null)
HttpContext.Current.Session.Add(“OriginalQueryString”, Request.QueryString.ToString());

//Redirect the user back to Facebook for authorization.
Response.Redirect(fbAuth.AuthorizationLinkGet());
}
else
{
//Get the access token and secret.

fbAuth.AccessTokenGet(Request[“code”]);

if (fbAuth.Token.Length > 0)
{
url = “https://graph.facebook.com/me?fields=id,name,verified,picture&access_token=” + fbAuth.Token;
string json = fbAuth.WebRequest(oAuthFacebook.Method.GET, url, String.Empty);

Dictionary claims = GetClaims(json);
HttpContext.Current.Session.Add(“AuthClaims”, claims);

FormsAuthentication.SetAuthCookie(“Facebook Test”, false);
Response.Redirect(“default.aspx?” + HttpContext.Current.Session[“OriginalQueryString”]);
}
}
}

private Dictionary GetClaims(string json)
{
Dictionary claims = new Dictionary();
JObject profile = JObject.Parse(json);

string userID = profile[“id”].ToString().Replace(@””””, “”);
string name = profile[“name”].ToString().Replace(@””””, “”);
string verified = profile[“verified”].ToString().Replace(@””””, “”);
string picture = profile[“picture”].ToString().Replace(@””””, “”);

if (!String.IsNullOrEmpty(userID))
claims.Add(System.IdentityModel.Claims.ClaimTypes.Authentication, userID);
if (!String.IsNullOrEmpty(name))
claims.Add(System.IdentityModel.Claims.ClaimTypes.Name, name);
if (!String.IsNullOrEmpty(picture))
claims.Add(System.IdentityModel.Claims.ClaimTypes.Webpage, picture);

return claims;
}

}

4. In the CertificateUtil.cs I have changed the logic from comparing Subject Name with Friendly Name of the certificate. This is done because I have multiple self- signed certificates installed on my server and all having a same subject name i.e. machine name. So the only unique name I found was Friendly Name, that’s why I have changed it to Friendly Name.
public static X509Certificate2 GetCertificate( StoreName name, StoreLocation location, string subjectName )
{
X509Store store = new X509Store( name, location );
X509Certificate2Collection certificates = null;
store.Open( OpenFlags.ReadOnly );

try
{
X509Certificate2 result = null;

//
// Every time we call store.Certificates property, a new collection will be returned.
//
certificates = store.Certificates;

for ( int i = 0; i < certificates.Count; i++ )
{
X509Certificate2 cert = certificates[i];

if ( cert.FriendlyName.ToLower() == subjectName.ToLower() )
{
if ( result != null )
{
throw new ApplicationException( string.Format( "There are multiple certificates for subject Name {0}", subjectName ) );
}

result = new X509Certificate2( cert );
}
}

if ( result == null )
{
throw new ApplicationException( string.Format( "No certificate was found for subject Name {0}", subjectName ) );
}

return result;
}
finally
{
if ( certificates != null )
{
for ( int i = 0; i < certificates.Count; i++ )
{
X509Certificate2 cert = certificates[i];
cert.Reset();
}
}

store.Close();
}
}
}

5. GetScope Method of CustomTokenSecurityService.cs looks like following

protected override Scope GetScope( IClaimsPrincipal principal, RequestSecurityToken request )
{
// ValidateAppliesTo( request.AppliesTo );

//
// Note: The signing certificate used by default has a Distinguished name of "CN=STSTestCert",
// and is located in the Personal certificate store of the Local Computer. Before going into production,
// ensure that you change this certificate to a valid CA-issued certificate as appropriate.
//
Scope scope = new Scope( request.AppliesTo.Uri.OriginalString, SecurityTokenServiceConfiguration.SigningCredentials );
scope.TokenEncryptionRequired = false;
//Specify the Realm name as defined in the script in PowerShell.
if (scope.AppliesToAddress == "urn:fbauth.com:facebook")
{
//Specify the Web Application URL which has claim based authentication as Facebook as a Trusted provider.
scope.ReplyToAddress = "http://win-6rnn5tdp5c6:47213/_trust/&quot;;

}
else
{
scope.ReplyToAddress = scope.AppliesToAddress;
}
return scope;

}

6. In the Web.config file update the SigningCertificateName

 

 

Step 7: Create a New Web Application in SharePoint 2010

  1. Open Central Administration
  2. Click on Manage Web Applications
  3. Select New Web Application option from the Ribbon bar.
  4. In the New Web Application window select Claim Based as Authentication mode.

  5. Select Facebook as Trusted Identity Provider

  6. Click OK
  7. Now Once the Web Application is created we need to create a Site collection.
  8. Click on Create Site Collections under Site Collections
  9. Make sure your newly created Web Application is selected for which you are creating a site collection.
  10. Specify Title and select any template, In the Primary Site Collection Administrator select Browse people/group button.

 

  1. Select People window opens and there you will see Facebook in the left pane

     

     

  2. Now select Facebook and click on the search icon button to search. You will see one Facebook user will populate in the main pane.

     

     

  3. Select and click ok
  4. We are done now we will navigate to our Web Application and login with Facebook account.

[Hint]

 

 

 

Step 8: Navigating to SharePoint 2010 Site

 

  1. Navigate to your SharePoint site. It will show you the option to select Authentication type as Facebook and Windows Authentication.
  2. Just Select Facebook.

  3. As the certificate I have used is self- signed that’s why It will show some warning as below. Just click on Continue to the website and proceed.

  1. It will show the Facebook login page. Enter your user name and password and click on Sign In.

     

  2. It will show the Main SharePoint site Home page.

     

Note: One thing you want to do here is when you will login to your account first time with your Facebook Id you will be prompted Access Denied in SharePoint site and it will give show you the numeric ID of your Facebook Account that this does not have an access to your site. Just copy that ID and place it in any of the SharePoint User Groups of your Site Collection or even specify it as a Primary or Secondary Administrator just to test. Then now when you re login, it will show the main SharePoint site page.

Configuring Live Authentication in SharePoint 2010

This post shows the steps which leads towards the configuration of Live Authentication in SharePoint 2010.

Before going in depth I want to tell some key points when configuring Live Authentication in SharePoint 2010. Actually WLID provides two zones “INT” and “PROD”. The “INT” zone is for testing purpose and the “PROD” zone is for production and you can use your actual hotmail or live accounts to authenticate users in SharePoint. One cannot directly submit their site to PROD until and unless they first submit their site in “INT”.

Creating a Test account

First of all create a test account in account services database.

1. Go to https://accountservices.msn-int.com
2. Sign up a new account
3. Choose “Yes, use my e-mail address” in the Signup window and press continue
4. Fill the form and specify an email address which contains @hotmail-int.com in the end. for e.g. ovaismehboob@hotmail-int.com

5. After creating account we need to see the unique id of the newly created account.
6. Click on credentials and note the UniqueId, save it somewhere we need to use it while specifying the site collection administrator for sharepoint site.

Registering a Site at Microsoft Services Manager

1. Navigate to http://msm.live.com
2. Enter your hotmail or live account id and sign in
3. Click on “Register your Site” link
4. Specify the name of your site for e.g. “Ovais Live Site”
5. Specify the DNS name of your site for e.g. “ovais.live”
6. Select the checkbox named “Windows Live Id”

7. Click on submit
8. Now after done submitting click on the “Manage your site” link
9. In the Manage your site page click on “Modify Editable Site properties”

10. Click on “Show Advanced Properties”
11. Configure the domain name in my case i have specified ovais.live.com
12. Specify DNS in my case i have specified urn:ovaislivesite:int
13. Specify the domain name in the default return url to https://ovais.live.com/_trust/default.aspx. Make sure it should match with the domain name.
14. Specify the domain name in the Expire cookie URL to https://ovais.live.com/wlid/expirecookie.aspx. Make sure it should match with the domain name.
15. Select “Override Authentication Policy” to MBI_FED_SSL
16. Click on Submit.

Creating and Importing a Certificate provided by Nexus Passport INT
1. Navigate to the https://nexus.passport-int.com/federationmetadata2/2007-06/federationmetadata.xml
2. Copy the inner text of X509Certificate node and paste it in a notepad.
3. Save the file with .cer as file extension
4. Run MMC.
5. Add Certificates Snap In
6. Import the newly created certificate in three places.
– SharePoint > Certificates
– Trusted People > Certificates
– Trusted Root Certification Authority > Certificates

Create STS Provider

Open Microsoft Shell Management and execute scripts as defined below. Note: the $realm should match with the DNS name you have specified while creating your site at msm.live.com. The $certfile should map to the path where the certificate is stored which was created in the previous section.

1. asnp microsoft.sharepoint.powershell
2. $realm = “urn:ovaislivesite:int”
3. $certfile = “C:\Live.cer”
4. $rootcert = Get-PfxCertificate $certfile
5. New-SPTrustedRootAuthority “Live ID INT Root Authority” -Certificate $rootcert
6. $emailclaim = New-SPClaimTypeMapping
-IncomingClaimType “http://schemas.xmlsoap.org/claims/EmailAddress&#8221;
-IncomingClaimTypeDisplayName “http://schemas.xmlsoap.org/claims/EmailAddress&#8221;
-SameAsIncoming
7. $upnclaim = New-SPClaimTypeMapping
-IncomingClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&#8221;
-IncomingClaimTypeDisplayName “UPN”
-LocalClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn&#8221;
8. $authp = New-SPTrustedIdentityTokenIssuer -Name “LiveID INT”
-Description “LiveID INT” -Realm $realm -ImportTrustCertificate $certfile
-ClaimsMappings $emailclaim,$upnclaim -SignInUrl “https://login.live-int.com/login.srf&#8221;
-IdentifierClaim “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&#8221;

Create Web Application in SharePoint

1. Open Central Management and click on Application Management
2. Click on New in the top panel
3. Select Claim Based in the Authentication

4. Select Allow Anonymous to No and SSL to Yes as shown below.

5. Click OK to finish creating a web application.
6. Now create a site collection. Click on the Create Site Collection under Application Management tab in Central Administration
7. Specify any title and select any template
8. In the Site collection administrator specify the live account address, the format should be uniqueid@live.com.

Add Certificate to Web Application

1. Open IIS
2. Open Server Certificates

3. Click on “Create Self Signed Certificate”

4. Specify certificate name in my case i had specified “ovais.live.com”
5. Add this certificate in the newly created web application and also add https binding to 443.

Configure Host Address
1. Open file C:\Windows\System32\drivers\etc\Hosts in Notepad and specify the host address

2. Click on the “Configure Alternate Access Mappings” under System Settings in Central Administration

3. Specify the Site URL, in my case it was ovais.live.com

4. Check by accessing https://ovais.live.com

5. It will show you to select the Authentication Provider

6. Select Live ID
7. Enter Live id login credentials

8. Press Sign In

9. It will show the SharePoint site as shown below.

Configuring Form Based Authentication in WSS

Last week i was just configuring the Form Based Authentication in WSS for one of our client. Although its been a very basic thing in sharepoint but i thought to blog it for any one who is new to it.

Below are the steps to configure FBA (Form Based Authentication) in Sharepoint/WSS 3.0.

Scenario: We will create a webapplication and site collection and then we will change the authentication to Form based rather windows which is default.

Form based authentication provider supports authentication against credentials stored in one of the following.

1. The Active Directory

2. a Database

3. An LDAP store

In this example i will show you the way one can authenticate the users from the database store.

1. First of all execute aspnet_sqlreg.exe to configure the Asp.Net membership provider database in SQL Server.

Note: aspnet_regsql is placed inside %WindowsDir%\Microsoft.Net\Framework\v2.0.50727

Above screen shows the way to execute aspnet_regsql.exe

2. Press Next, and complete the wizard.

3. You will notice that the tables will be created in the database selected.

4. Now create a dummy website in Asp.Net

5. Add web cofiguration file

6. Specify the connection string to the database just created above.

7. Now we have to add users, click on the Asp.Net Configuration under website section from Visual Studio

8. Now click on the Security link from the Asp.Net configuration website

9. In the Security page click on the Authentication Type and select “From Internet”

10. Press done to save the settings.

11. Now click on the Create users link to add users from the Security Page.

11. Now create a new Web Application in SharePoint from Central Administration.

12. Go to the Application Management in Central Administration website and click on “Create or Extend Web Application”.

13. In the Create or Extend Web Application page click on Create New Web Application

14. Specify appropriate values in the Create new web application screen and press Ok to create.

15. Now create a site collection for the newly created webapplication.

16. Now open the sharepoint webapplication web.config file and place connection string, people picker, membership provider and role providers.

Add People Picker Wild Cards for your Membership Provider

    <PeoplePickerWildcards>
      <clear />
      <add key="SqlProvider" value="%" />
    </PeoplePickerWildcards>

Add Connection string tag after </sharepoint>

  <connectionStrings>
    <add name="MySqlConnection" connectionString="server=ovais-2504dc252; database=SPFormBased; User Id=FBAService; Password=123;"/>
  </connectionStrings>

Add Membership provider and Role Manager under <system.web>

    <membership defaultProvider="SqlProvider">
      <providers>
        <clear />
        <add connectionStringName="MySqlConnection" enablePasswordRetrieval="false"
          enablePasswordReset="true" requiresQuestionAndAnswer="false"
          applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed"
          maxInvalidPasswordAttempts="5" minRequiredPasswordLength="1"
          minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
          passwordStrengthRegularExpression="" name="SqlProvider" type="System.Web.Security.SqlMembershipProvider" />
      </providers>
    </membership>
    <roleManager enabled="true" defaultProvider="SqlRoleProvider">
      <providers>
        <add connectionStringName="MySqlConnection" applicationName="/"
          name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider" />
      </providers>
    </roleManager>

17. Do the same for Central Administration web application but instead of setting Default provider to SqlProvider (in our case) set AspNetWindowsTokenRoleProvider in Role Manager tag.

   <membership defaultProvider="SqlProvider">
      <providers>
        <clear/>
        <add name="SqlProvider" type="System.Web.Security.SqlMembershipProvider"
             connectionStringName="MySqlConnection"
             enablePasswordRetrieval="false"
             enablePasswordReset="true"
             requiresQuestionAndAnswer="false"
              applicationName="/"
              requiresUniqueEmail="false"
              passwordFormat="Hashed"
              maxInvalidPasswordAttempts="5"
              minRequiredPasswordLength="1"
              minRequiredNonalphanumericCharacters="0"
              passwordAttemptWindow="10"
              passwordStrengthRegularExpression=""
             />
      </providers>
    </membership>
    <roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
      <providers>
        <add name ="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider"
        connectionStringName="MySqlConnection"
        applicationName="/" />
      </providers>
    </roleManager>

18. Now, open the properties windows from IIS for newly created website and go to the Directory Security tab.

19. Click on edit and set the Administrator account in Authentication methods screen. Note the administrator should have access rights to the ASPNet database.  Make sure that the user should have db_owner, membership_fullaccess rights.

20. Now go to the Central Administration > Application Management > Policy for Web Application. Make sure the correct web application is selected.

21. Type the user name that exist in the Aspnet database. Sharpoint will resolve the name give appropriate rights.

22. Now navigate to the Web Application

23. Enter user name and password that exist in AspNet database.

24. System will login and display the home page.

Dynamic Binding of SharePoint Lists with .Net Business Objects

Dynamic Binding of SharePoint Lists with .Net Business Objects

This document highly detailing the binding of .Net business objects with SharePoint list and also provides a framework which provides dynamic support of CRUD operations, In which the developer only needs to define a business object and mapping with list and its fields, rest will be done by the framework itself.
First of all, develop two class Attributes namely ListAttribute and FieldAttribute

a. ListAttribute maps the SharePoint List Name.
b. FieldAttribute maps the column of SharePoint list.

Code Snippet for ListAttribute

[AttributeUsage(AttributeTargets.Class)]
public class ListAttribute
{
string listName;

public ListAttribute(String _listName)
{
this.listName = _listName;
}

public string ListName
{
get { return this.listName; }
}
}

Code snippet for FieldAttribute

[AttributeUsage(AttributeTargets.Property)]
public class FieldAttribute : Attribute
{

public FieldAttribute(String listItemName)
{
this.listItemName = listItemName;
}
string listItemName;

public string ListItemName
{
set { this.listItemName = value; }
get { return this.listItemName; }
}
}

Now let’s develop the custom list named Demo in SharePoint and specify Title, Description, Date columns.

Develop the business object for Demo list. Below code snippet shows the class details. Business Object class is derived from the parent class BaseEntity. Reason of binding is that the framework supports generic methods for all types of CRUD operations, this benefits the business objects that are derived from the BaseEntity to be passed as a parameter.

[ListAttribute("Demo")]
public class TripLogList: BaseEntity
{
string title;
[FieldAttribute("Title")]
public string Title {
set { this.title = value; }
get { return this.title; }
}

string description;
[FieldAttribute("Description")]
public string Description
{
set { this.description = value; }
get { return this.description; }
}

DateTime dateTime;
[FieldAttribute("Date")]
public DateTime DateTime
{
set { this.dateTime = value; }
get { return this.dateTime; }
}

Int32 id;
[FieldAttribute("ID")]
public Int32 Id
{
set { this.id = value; }
get { return this.id; }
}
}

Develop windows form through which we can manipulate SharePoint list items and can perform Insert, update, delete and load operations.

Below screen shows all the items stored in the Demo list

Framework provides the PersistanceManager object through which the developer can directly call Insert, Update, Delete and LoadAll methods and these operations will be performed by the PersistanceManager itself. Developer does not need to manually bind the SharePoint list items with business objects and depending on the fieldname specified, automatic binding will be done on loading, insertion, updation and deletion of list.

To Insert,

Demo demoObj = new Demo();
demoObj.Title = txtitle.Text;
demoObj.Description = txtDescription.Text;
demoObj.DateTime = dtPicker.Value;
PersistanceManager.GetInstance().Insert(demoObj);

To update,

Demo demoObj = new Demo();
demoObj.Id = Convert.ToInt32(row.Cells["id"].Value.ToString());
demoObj.Title= row.Cells["Title"].Value.ToString();
demoObj.Description=row.Cells["Description"].Value.ToString();
demoObj.DateTime = Convert.ToDateTime(row.Cells["DateTime"].Value);
PersistanceManager.GetInstance().Update(demoObj);

To delete,

Demo demoObj = new Demo();
demoObj.Id = Convert.ToInt32(row.Cells["id"].Value.ToString());
PersistanceManager.GetInstance().Delete(demoObj);

To LoadAll,

ArrayList lst=PersistanceManager.GetInstance().LoadAll(typeof(Demo));

grdView.DataSource=lst; // Binding datasoure with datagridview object.

Framework Classes/Interfaces

IDataManager

An interface which contains generic methods. When defining new Persistance Manager for any data source this interface should be derived with it.

interface IDataManager
{
void Insert(BaseEntity baseEntity);
void Update(BaseEntity baseEntity);
void Delete(BaseEntity baseEntity);
ArrayList LoadAll(Type type);
}

SPPersistanceManager

Persistance Manager class for SharePoint. This class implements the Insert, Update, Delete and LoadAll operations. For e.g if you have SQL Server datasource you need to develop a new class named SQLPersistanceManager and defines implements IDataManager methods.

public class SPPersistanceManager : IDataManager
{

String siteURL = System.Configuration.ConfigurationSettings.AppSettings.Get("SharePointSite");

//Load All Items

public ArrayList LoadAll(Type type)
{

ArrayList objlist = new ArrayList();

using (SPSite site = new SPSite(siteURL))
{
using (SPWeb web = site.OpenWeb())
{
String listName=FrameworkFacade.GetInstance().GetListName(type);
ArrayList fieldList = (ArrayList)FrameworkFacade.GetInstance().GetFields(type);
SPList list=web.Lists[listName];
foreach (SPListItem item in list.Items)
{
Demo tripLogObject = new Demo();

foreach (String fieldName in fieldList)
{

FrameworkFacade.GetInstance().SetFieldValue(tripLogObject, fieldName, item[fieldName]);

}
objlist.Add(tripLogObject);
}
}
}
return objlist;
}

//Insert Implementation

public void Insert(BaseEntity obj)
{
ArrayList fieldList = (ArrayList)FrameworkFacade.GetInstance().GetFields(obj.GetType());
using (SPSite site = new SPSite(siteURL))
{
using (SPWeb web = site.OpenWeb())
{
SPList myList = web.Lists[FrameworkFacade.GetInstance().GetListName(obj.GetType())];
SPListItem myListItem = myList.Items.Add();

foreach (String fieldName in fieldList)
{
if (!fieldName.Equals("ID"))
{
myListItem[fieldName] = FrameworkFacade.GetInstance().GetFieldValue(obj, fieldName);
}

}
web.AllowUnsafeUpdates = true;
myListItem.Update();
web.AllowUnsafeUpdates = false;
}
}
}

//Update Implementation

public void Update(BaseEntity obj)
{

using (SPSite site = new SPSite(siteURL))
{
using (SPWeb web = site.OpenWeb())
{
SPList myList = web.Lists[FrameworkFacade.GetInstance().GetListName(obj.GetType())];
SPListItem item = myList.GetItemById(Convert.ToInt32(FrameworkFacade.GetInstance().GetFieldValue(obj, "ID")));
ArrayList arrFields = FrameworkFacade.GetInstance().GetFields(obj.GetType());
foreach (String fieldName in arrFields)
{
if(fieldName!="ID")
item[fieldName] = FrameworkFacade.GetInstance().GetFieldValue(obj, fieldName);

}

item.Update();
}
}

}

//Delete Implementation

public void Delete(BaseEntity obj)
{

using (SPSite site = new SPSite(siteURL))
{
using (SPWeb web = site.OpenWeb())
{
SPList myList = web.Lists[FrameworkFacade.GetInstance().GetListName(obj.GetType())];
Int32 value = Convert.ToInt32(FrameworkFacade.GetInstance().GetFieldValue(obj, "ID").ToString());
myList.Items.DeleteItemById(value);
}
}

}

}

FrameworkFacade

FrameworkFacade is a core class which traverses object metadata through reflection and helps to retrieve properties, custom attributes and setting or getting property values, invoking methods etc.

public class FrameworkFacade
{
static Object _lock = new Object();
static FrameworkFacade instance = null;
private FrameworkFacade() { }
public static FrameworkFacade GetInstance() {
lock (_lock)
{
return (instance == null) ? new FrameworkFacade() : instance;
}

}

//Get Field value
public Object GetFieldValue(Object obj, String propertyAttributeName)
{
object fieldValue = null;
Type type = obj.GetType();
var props = type.GetProperties();
foreach (System.Reflection.PropertyInfo propInfo in props)
{
Object[] propertyAttribute = propInfo.GetCustomAttributes(typeof(FieldAttribute), true);
if (((FieldAttribute)propertyAttribute[0]).ListItemName == propertyAttributeName)
{
System.Reflection.MethodInfo methodInfo =
propInfo.GetGetMethod();
fieldValue = methodInfo.Invoke(obj, null);
break;
}

}

return fieldValue.ToString();
}

//Set Field Value

public void SetFieldValue(Object obj, String propertyAttributeName, Object value)
{

Type type = obj.GetType();
var props = type.GetProperties();
foreach (System.Reflection.PropertyInfo propInfo in props)
{
Object[] propertyAttribute = propInfo.GetCustomAttributes(typeof(FieldAttribute), true);
if (((FieldAttribute)propertyAttribute[0]).ListItemName == propertyAttributeName)
{

if (propInfo.CanWrite)
{
propInfo.SetValue(obj, value, null);
}

break;
}
}
}

//Get ListAttribute value from type

public String GetListName(Type type)
{
String name = type.Assembly.FullName;
object[] obj = type.GetCustomAttributes(typeof(ListAttribute), true);
ListAttribute listAttribute = (ListAttribute)obj[0];
return listAttribute.ListName;

}

//Get All Fields from Type.

public System.Collections.ArrayList GetFields(Type type)
{
System.Collections.ArrayList fieldProperties = new System.Collections.ArrayList();
string name = type.Assembly.FullName;
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(type.Assembly.Location);
System.Reflection.PropertyInfo[] propInfo = type.GetProperties();
foreach (System.Reflection.PropertyInfo property in propInfo)
{
object[] propAttributes = property.GetCustomAttributes(typeof(FieldAttribute), true);
foreach (object obj in propAttributes)
{
String fieldValue = ((FieldAttribute)obj).ListItemName;
fieldProperties.Add(fieldValue);
}
}
return fieldProperties;
}
#endregion
}

Offline Document Uploader in SharePoint 2010

A week ago i was just exploring Sharepoint 2010 Client Object model and have developed a utility which transfers all the documents from the windows folder to the Sharepoint document library. 

Following are the steps to develop Offline Document uploader in SharePoint 2010 using Client Object Model.

1. Create a menu item which opens files uploader utility from windows folder’s context menu.

                                        

In order to create custom menu item in windows, we have to place an entry into registry. 

I have first defined the two constant string variables as shown below that contains path to create a menu in the registry. You might have noticed that i have mentioned “Folder” at starting in both the values. This means that i want to create a context menu item at folder level. Otherwise if i place ” * ” it will be created at files, folder etc.

private const string MenuName = "Folder\\shell\\CMenuOption";
private const string Command= "Folder\\shell\\CMenuOption\Command";

Following is a code snippet that creates menu item at folder level. You can place it on any event. I have created two textboxes on a windows form i.e. txtMenuName and txtExecutablePath. In the txtMenuName textbox, i’ve  specified menu item name and in the txtExecutablePath i’ve specified the .exe path of an application which transfers file to sharepoint library.

Here is the complete code which creates a menu item into the registry.
           
RegistryKey regmenu = null;
            RegistryKey regcmd = null;
            try
            {
                regmenu = Registry.ClassesRoot.CreateSubKey(MenuName);
                if (regmenu != null)
                    regmenu.SetValue("", this.txtMenuName.Text);
                regcmd = Registry.ClassesRoot.CreateSubKey(Command);
                if (regcmd != null)
                    regcmd.SetValue("", this.txtExecutablePath.Text+ " \"%1\"");
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.ToString());
            }
            finally
            {
                if (regmenu != null)
                    regmenu.Close();
                if (regcmd != null)
                    regcmd.Close();
            }

Now there is a separate console application which sends the files from the folder path to the SharePoint document library. Following is the code snippet.

 
static void Main(string[] args)
        {

            String filepath =  args[0].ToString();
            Console.WriteLine(filepath);
            Console.WriteLine("Processing Documents");
            String[] files = Directory.GetFiles(filepath);

            String docLibrary= System.Configuration.ConfigurationSettings.AppSettings.Get("DocLibrary").ToString();
            String SPSiteURL= System.Configuration.ConfigurationSettings.AppSettings.Get("SPSiteURL").ToString();

            ClientContext context = new ClientContext(SPSiteURL);
            foreach (String fileName in files)
            {
                using(FileStream fileStream= new FileStream(fileName,FileMode.Open))
                {
                    Console.WriteLine("Uploading file = " + fileName);
                    Microsoft.SharePoint.Client.File.SaveBinaryDirect(context, "/"+ docLibrary + "/" + Path.GetFileName(fileName), fileStream, true);
                    Console.WriteLine("Uploaded");
                }
            }
 }

Finally, When the user clicks on “Upload files to SP” a console application runs and uploads all the documents in the Sharepoint document library.

                                                 

Figure shows the Console Application uploading documents into SP doc library.

                                                 

                                                           Figure shows the documents uploaded in the SP doc library.