Sunday 23 June 2013

SharePoint 2010 & .NET 4

Our backup admin needs to install Avamar SQL Agent on the SharePoint 2010 server and Avamar needs .NET 4 to be installed, so is it going to cause any problem?

We already know that SharePoint 2010 works only with .NET 3.5 and it doesn't support .NET for in application developments. but what about having both .NET 3.5 and .NET 4 installed on the SP server, I've been searching and here is what I found:

Here is a link to Technet where someone asked the same question, people argue both cases where it is OK to have both .NET versions and also some say, it may cause problems.

as an example, if you want to install the June 2011 patch, here is a key known issue on the description:

 Known issue 1
If you install an earlier build of this hotfix package on a SharePoint server that has the .NET Framework 4 installed, you cannot synchronize user profiles from Active Directory and LDAP into the SharePoint User Profile Service application database. The user profile synchronization export process fails. Additionally, the System.PlatformNotSupportedException exception shows in Event Viewer.
Note This issue is fixed in build 14.0.6106.5002 of this hotfix package.

From my experience, If you don't need to add any hotfix or major change on the server, then installing .NET 4.0 is fine, so if you are building a new server then leave it for last.

Site Collection Backup & Restore by Powershell

Backup-SPSite

Backup-SPSite -Identity SiteCollectionURLHere -Path BackupFilePathHere [-Force] [-NoSiteLock] [-UseSqlSnapshot] [-Verbose]
  • Identity - Specifies the URL or GUID of the site collection to be backed up.
  • For example, a valid URL, such as http://server_name/sites/site_name or a GUID such as, "01234567-89ab-cdef-0123-456789abcdef"
  • Path - Specifies the full path to the backup file (that is, C:\Backup\site_name.bak)
  • Force - Specify to overwrite an existing backup file if it already exists.
  • NoSiteLock - Specifies the site collection to remain read and write during the backup.
  • If the NoSiteLock parameter is not specified, then a site collection that has a site collection lock setting of "none" or "no additions" will be temporarily set to "read only" while the site collection backup is performed. Once the backup has completed, the site collection lock will return to its original state. The backup package will record the original site collection lock state so that it is restored to that state.
    If users are writing to the site collection while the site collection is being backed up, then the NoSiteLockparameter is not recommended for potential impact to backup integrity, it means if someone changes content on the site while the backup is being created and according to Microsoft “might lead to possible data corruption”
  • UseSqlSnapshot - Specifies a SQL Database Snapshot will be created when the backup begins, and all site collection data will be retrieved directly from the database snapshot, this snapshot will be deleted automatically when the backup completes.
  • The UseSqlSnapshot parameter is recommended if the database server hosting your content database supports database snapshots such as SQL Server Enterprise Edition and SQL Server Developer Edition. This is because it will ensure a valid backup while allowing users to continue reading and writing to the site collection during the backup. It is not necessary to specify the NoSiteLock parameter when specifying the UseSqlSnapshot parameter.
  • NoSiteLock - Specifies the URL or GUID of the site collection to be backed up.

Example

Backup-SPSite http://server_name/sites/site_name -Path C:\Backup\site_name.bak
Get-SPSiteAdministration http://server_name/sites/site_name Backup-SPSite -Path C:\Backup\site_name.bak
Backup-SPSite http://server_name/sites/site_name -Path C:\Backup\site_name.bak -UseSqlSnapshot

Restore-SPSite

Restore-SPSite -Identity SiteCollectionURLHere -Path BackupFilePathHere [-ContentDatabase ContentDatabaseNameHere] [-Force] [-GradualDelete] [-HostHeaderWebApplication HostHeaderHere]
  • ContentDatabase - Specifies the SQL Server content database where the site collection data will be stored. If no content database is specified, the content database with the greatest unused site collection capacity and whose database status is ready will be used.
  • Force - Specifies that the existing site collection at the URL location is to be overwritten by this restoration.
  • GradualDelete - Specifies that the site collection being overwritten with the Force parameter should be gradually deleted over time by a timer job instead of all at once, which reduces its impact on SharePoint 2010 Products and SQL Server performance. This option is recommended for large site collections.
  • HostHeaderWebApplication - A valid URL assigned to the Web application by using alternate access mapping, such as http://server_name.
  • Restores a site collection as a host-named site collection instead of a path-based site collection. When the HostHeaderWebApplication parameter is present, the value of the Identity parameter is the URL of the host-named site collection and the value of the HostHeaderWebApplication parameter is the URL of the Web application that will hold the host-named site collection
Restore-SPSite -Identity SiteCollectionURLHere -Path BackupFilePathHere [-DatabaseServer DatabaseServerNameHere] [-DatabaseName ContentDatabaseNameHere] [-HostHeaderWebApplication HostHeaderHere] [-Force] [-GradualDelete] [-Verbose]
  • DatabaseServer - Specifies the name of the SQL Server containing the content database specified by the DatabaseName parameter.
  • The type must be a valid database server name, in the form SQLBE1 and needs to be used in conjunction with the DatabaseName parameter.
  • DatabaseName - Specifies the SQL Server content database where the site collection data will be stored.
  • If no content database is specified, the content database with the greatest unused site collection capacity and whose database status is ready will be used. The type must be a valid database name, in the form SQLDB1.
  • Force - Specifies that the existing site collection at the URL location is to be overwritten by this restoration.
  • GradualDelete - Specifies that the site collection being overwritten with the Force parameter should be gradually deleted over time by a timer job instead of all at once, which reduces its impact on SharePoint 2010 Products and SQL Server performance. This option is recommended for large site collections.
  • HostHeaderWebApplication - A valid URL assigned to the Web application by using alternate access mapping, such as http://server_name.
  • Restores a site collection as a host-named site collection instead of a path-based site collection. When the HostHeaderWebApplication parameter is present, the value of the Identity parameter is the URL of the host-named site collection and the value of the HostHeaderWebApplication parameter is the URL of the Web application that will hold the host-named site collection

Example

Restore-SPSite http://server_name/sites/site_name -Path C:\Backup\site_name.bak
Restore-SPSite http://server_name/sites/site_name -Path C:\Backup\site_name.bak
Restore-SPSite http://www.example.com -Path \\file_server\share\site_name.bak -HostHeaderWebApplication http://server_name

Tuesday 11 June 2013

New Twitter API Version 1.1 (Part 1: Authentication)

As you know, the old twitter API V1 has been retired few hours ago [@twitterapi]. What does it mean for SharePoint developers? Well if you use any twitter webpart which using the API V1, then it is dead by now, because twitter depricate the API V1 and you need to upgrade your apps to use the new twitter API V1.1.
 Figure 1 - Twitter TimeLine Web part using API V1 (Before 11/06/2013)

Figure 2 - Twitter TimeLine Web part using API V1 (After 11/06/2013)

I have been trying to upgrade my company’s twitter web part to version 1.1, and find out there is very hard to find the relevant information from many resources out there. Finally after spending two days searching and trialing different solutions, I could do it, so here is the summary of what I found usefull, and a quick steps guide of what exactly needs to be done to build a reader webpart for twitter  timelines.
To use the Twitter API V 1.1, you must first authenticate (source), even if you only want to read timelines like in my case. After authenticate is done, you simply call the API and get the results in Json, and now you can display those data in whatever format you like to do it.
There aren't quick and easy instructions on how to move from that model because there aren't quick and easy ways to migrate. One has to completely rethink their approach to the API in this model, leveraging a server-to-server approach instead of a client-to-server model. Instead of using jQuery to make requests to the API, you'll need to make requests using OAuth from your back end. (Source from @episod)

Authentication (OAuth FAQ):

Before start coding, you need to create an application. https://dev.twitter.com/apps.
Once you've done that, you need to get your consumer key, consumer secret, access token and access token secret.




Here is a link to the twitter document for Moving from Basic Auth to OAuth. After many searching and reading, here is the best approach for my case to do the oAuth in SharePoint.
Thanks to @countscar and @bobbykc13 who post their codes here. this is what I did to build this code for SharePoint 2010.

To use/test this code, create a new web application in C# and copy this code to the Page Load function. Replace the "consumerKey, consumerSecret, accessToken, accessTokenSecret" with your own key details and run the application.

            // oauth application keys
            var consumerKey = "Your Key";
            var consumerSecret = "Your Key";
            var accessToken = "Your Key";//oauth_token
            var accessTokenSecret = "Your Key";//oauth_token_secret
            var Count = "3";

            // oauth implementation details
            var oauthSignatureMethod = "HMAC-SHA1";
            var oauthVersion = "1.0";
            // message api details
            //var status = "Updating status via REST API if this works";
            var resource_url = "https://api.twitter.com/1.1/statuses/user_timeline.json";
            var screen_name = "TransPerth";

            // unique request details
            var oauth_nonce = Convert.ToBase64String(
               new ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
            var timeSpan = DateTime.UtcNow
                - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();

            // create oauth signature
            var baseFormat = "count={7}&oauth_consumer_key={0}&oauth_nonce={1}&oauth_signature_method={2}" +
                            "&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}&screen_name={6}";
            var baseString = string.Format(baseFormat,
                                        consumerKey,
                                        oauth_nonce,
                                        oauthSignatureMethod,
                                        oauth_timestamp,
                                        accessToken,
                                        oauthVersion,
                                         Uri.EscapeDataString(screen_name),
                                         Uri.EscapeDataString(Count)
                                        );

            baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));

            var compositeKey = string.Concat(Uri.EscapeDataString(consumerSecret),
                                    "&", Uri.EscapeDataString(accessTokenSecret));

            string oauth_signature;
            using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey)))
            {
                oauth_signature = Convert.ToBase64String(
                    hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString)));
            }

            // create the request header
            var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
                               "oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
                               "oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
                               "oauth_version=\"{6}\"";

            var authHeader = string.Format(headerFormat,
                                    Uri.EscapeDataString(oauth_nonce),
                                    Uri.EscapeDataString(oauthSignatureMethod),
                                    Uri.EscapeDataString(oauth_timestamp),
                                    Uri.EscapeDataString(consumerKey),
                                    Uri.EscapeDataString(accessToken),
                                    Uri.EscapeDataString(oauth_signature),
                                    Uri.EscapeDataString(oauthVersion)
                            );

            // make the request
            ServicePointManager.Expect100Continue = false;

            var postBody = string.Format("screen_name={0}&count={1}", Uri.EscapeDataString(screen_name), Uri.EscapeDataString(Count));
            resource_url += "?" + postBody;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(resource_url);
            request.Headers.Add("Authorization", authHeader);
            request.Method = "GET";
            request.ContentType = "application/x-www-form-urlencoded";

            WebResponse response = request.GetResponse();
            string responseData = new StreamReader(response.GetResponseStream()).ReadToEnd();
            //Label1.Text = responseData;
  
I will write another post soon, to explain the display method, and how convert the JSON results to a repeater and make the SharePoint web part.