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

Thursday, December 10, 2015

SharePoint Custom ULS Logging

Here is a working code snippet (C# class) to write custom errors or logs to ULS log.

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Collections.Generic;

namespace CustomLogging
{
    class LoggingService : SPDiagnosticsServiceBase
    {
        public static string diagnostcAreaName = "CustomLogging";
        public static string errorPrefix = "CustomLogging: ";

        private LoggingService()
            : base("CustomLogging Logging Service", SPFarm.Local)
        {
        }

        protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
        {
            List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>
            {
                new SPDiagnosticsArea(diagnostcAreaName, new List<SPDiagnosticsCategory>
                {
                    new SPDiagnosticsCategory("CustomLogging", TraceSeverity.Unexpected, EventSeverity.Error)
                })
            };

            return areas;
        }

        public static void LogError(string message, EventSeverity eventSeverity)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate ()
            {
                SPDiagnosticsService diagnosticService = SPDiagnosticsService.Local;
                diagnosticService.WriteTrace(0, new SPDiagnosticsCategory(diagnostcAreaName, TraceSeverity.Monitorable, eventSeverity),
                   TraceSeverity.Monitorable, errorPrefix + "{0}", new object[] { message });
            });

        }
    }
}

An entry to ULS logs can be written using the below snippet with make use of the above class.
try
{
    //Business logic
}
catch (Exception ex)
{
    LoggingService.LogError(ex.Message + " " + ex.StackTrace + "\r" + ex.Source, (EventSeverity)EventSeverity.Information);
}

Monday, August 3, 2015

SharePoint Cross Site Lookup Field

Can we create a cross site lookup field?
Yes of course, it can be. Thought it is not possible OTB, a simple trick will do this.

Scenario: Creating a cross site lookup field between the two peer web sites or sub web sites under a same site collection.
Example: Create a lookup field between two sites http:/sitecollection/webA & http://sitecollection/webB

The trick is just to set the lookup field webId with the target list webId.
Code snippet to create cross site lookup field programatically:
private bool CreateCrossSiteLookupField(SPWeb sourceWeb, SPWeb targetWeb, string sourceListTitle, string targetListtitle, string lookUpFieldName, string lookupValueColumn, bool isRequiredField)
{
    ////Get the source and target lists 
    SPList sourceList = sourceWeb.Lists.TryGetList(sourceListTitle);
    SPList targetList = targetWeb.Lists.TryGetList(targetListtitle);

    if (null != sourceList && null != targetList)
    {
        ////Add a lookup field to source list with target list as lookup list
        sourceList.Fields.AddLookup(lookUpFieldName, targetList.ID, isRequiredField);

        ////Get the created lookup field from source list 
        SPFieldLookup lookupField = (SPFieldLookup)sourceList.Fields[lookUpFieldName];

        ////Set the lookup field's webID with target list webId
        lookupField.LookupWebId = targetList.ParentWeb.ID;

        ////Set the lookup field's display field 
        lookupField.LookupField = targetList.Fields[lookupValueColumn].InternalName;

        ////Finally update the lookup field
        lookupField.Update();
    }
    return true;
}
Code snippet to create cross site lookup field with PowerShell:
Add-PSSnapIn "Microsoft.SharePoint.Powershell"

#Get the webs and lists
$webA = Get-SPWeb http://siteurl/webA/
$webB = Get-SPWeb http://siteurl/webB/
$sourceList = $webA.Lists.item("SourceList")
$targetList = $webB.Lists.item("TargetList")

#Add a lookup field to source list with target list as lookup list
$sourceList.fields.AddLookup("LookupFieldName", $targetList.id, "true")

#Get the created lookup field from source list
$lookupField = $sourceList.Fields["LookupFieldName"]

#Set the lookup field's webID with target list webId
$lookupField.LookupWebId = $targetList.ParentWeb.ID

#Set the lookup field's display field
$lookupField.LookupField = $targetList.Fields["Title"].InternalName
$lookupField.Update();

Thursday, July 16, 2015

How to Get Outgoing E-Mail Settings Programatically

Sometimes it might be needed to get the Web Application outgoing emails settings programatically.
The below code snippet gives all the settings including Outbound SMTP server, From address, Reply-to address and Character set information.
using (SPSite site = new SPSite("http://siteurl"))
{
    SPWebApplication webApp = site.WebApplication;
    string outboundSMTPServer = webApp.OutboundMailServiceInstance.Parent.Name;
    string fromAddress = webApp.OutboundMailSenderAddress;
    string replyToAddress = webApp.OutboundMailReplyToAddress;
    int characterSet = webApp.OutboundMailCodePage;
}
Web application outgoing email settings can also be updated programatically as below.
using (SPSite site = new SPSite("http://siteurl"))
{
    string outboundSMTPServer = "Outbound SMTP server";
    string fromAddress = "From address";
    string replyToAddress = "Reply-to address";
    int characterSet = 65001; //Character set code

    SPWebApplication webApp = site.WebApplication;
    webApp.UpdateMailSettings(outboundSMTPServer,fromAddress,replyToAddress,characterSet);
}
Similarly we can get & set the Global outgoing email settings as below.
GET:
var globalAdmin = SPAdministrationWebApplication.Local;
var outboundSMTPServer = globalAdmin.OutboundMailServiceInstance.Parent.Name;
var fromAddress = globalAdmin.OutboundMailSenderAddress;
var replyToAddress = globalAdmin.OutboundMailReplyToAddress;
var characterSet = globalAdmin.OutboundMailCodePage;
SET:
string outboundSMTPServer = "Outbound SMTP server";
string fromAddress = "From address";
string replyToAddress = "Reply-to address";
int characterSet = 65001; //Character set code
var globalAdmin = SPAdministrationWebApplication.Local;
globalAdmin.UpdateMailSettings(outboundSMTPServer, fromAddress, replyToAddress, characterSet); 

Monday, July 13, 2015

SharePoint ListItem Update vs SystemUpdate vs UpdateOverwriteVersion

Here is a simple table format to explain the differences among Update vs SystemUpdate vs UpdateOverwriteVersion vs SystemUpdate(true). 

This information is pretty much useful to look at the differences between the following SPListItem methods when working with event receivers or workflows.


Update()
SystemUpdate()
SystemUpdate(true)
UpdateOverwriteVersion()
Updates the item in the database
ü  
ü  
ü  
ü  
Creates a new version
ü  
û   
ü  
û   
Updates the Modified and Modified By values
ü  
û   
û   
ü  

How to update Modified By field in a SharePoint list item programatically

While adding/updating a list item using SPSecurity.RunWithElevatedPrivileges with administrator privileges, Created By / Modified By fields are set to System Account as the piece of code is executed with Application Pool account context.

But in an ideal case Created By / Modified By fields should have the original user who actually did the modification. In order to achieve this Created By / Modified By fields needs to be updated at the time of inserting / updating list item.

The catchy point here is to get the Current User out of the SPSecurity.RunWithElevatedPrivileges scope because within the scope it is always System Account as mentioned.

The below code snippet works as as explained above:
////Get the current user out of the SPSecurity.RunWithElevatedPrivileges scope
SPUser currentUser = SPContext.Current.Web.CurrentUser;

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite newSite = new SPSite("http://siteurl"))
    {
        using (SPWeb newWeb = newSite.OpenWeb())
        {
            SPList list = newWeb.Lists.TryGetList("List Title");
            if (null != list)
            {
                bool isNewItem = true; //Adding or Updating item
                SPListItem item = list.GetItemById(1);
                if (isNewItem)
                {
                    item["Author"] = currentUser;
                }
                item["Editor"] = currentUser;

                item.Update();
            }
        }
    }
});

Reference:
How to update Modified By field programatically
How to update Created By field programatically
SharePoint List Item update Modified By field programatically
SharePoint List Item update Created By field programatically

Tuesday, January 6, 2015

How to Check Group Exists in SharePoint Programatically

I was trying to check if specific group exists in SharePoint web. I couldn't find any OTB API method to achieve this.
Hence I am using the below LINQ statement to check whether group exists in a web.
string groupName = "MyGroupName";
SPWeb web = SPContext.Current.Web;
 //Check if group exists in the web
 if (web.Groups.OfType<SPGroup>().Count(g=>g.Name.Equals(groupName, StringComparison.InvariantCultureIgnoreCase))>0)
 {
     //Get the SPGroup by group name if exists
     SPGroup group = web.Groups[groupName];
 }

Monday, December 1, 2014

Access Denied within SPSecurity.RunWithElevatedPrivileges

I never thought that SPSecurity.RunWithElevatedPrivileges gives an error "Access Denied". But yes, i see it in my below scenario.

I was doing an operation within an item event receiver which required higher level of access to update the web level information. Since this was to be executed irrespective of the access of the user logged in, i had the code to be executed within the SPSecurity.RunWithElevatedPrivileges. Unexpectedly the code was failing and throwing an error "Access Denied".

The below code executes well and fine for the users who has Full Control on a web but gives a "Access Denied' error for contributors or readers though the code is wrapped in SPSecurity.RunWithElevatedPrivileges.
public override void ItemCheckedIn(SPItemEventProperties properties)
{
            base.ItemCheckedIn(properties);
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                         SPWeb web = properties.Web;
                         var listItem = properties.ListItem;
                          if (!listItem.Title.Equals(web.Title))
                          {
                                    web.AllowUnsafeUpdates = true;
                                    web.Title = listItem.Title;
                                    web.Update();
                                    web.AllowUnsafeUpdates = false;
                           }
             }
}
In the above code web.Update() throws an exception "Access Denied" Though the code is executing under RunWithElevatedPrivileges. Because the code doesn't really execute under elevated privileges as the respective object SPWeb was not created within the SPSecurity.RunWithElevatedPrivileges but it is retrieved through the receiver context properties.Web, which is created before elevated privileges. Hence the elevated privileges cannot be applied to that object.

The solution for this problem is very simple. Create the objects which are being used to perform some operations with in the SPSecurity.RunWithElevatedPrivileges.
public override void ItemCheckedIn(SPItemEventProperties properties)
{
          base.ItemCheckedIn(properties);
          SPSecurity.RunWithElevatedPrivileges(delegate()
          {                 
                 var listItem = properties.ListItem;
                 using (SPSite site = new SPSite(properties.Site.ID))
                 {
                        using (SPWeb web = site.OpenWeb(properties.Web.ID))
                        {     
                               if (!listItem.Title.Equals(web.Title))
                              {
                                    web.AllowUnsafeUpdates = true;
                                    web.Title = listItem.Title;
                                    web.Update();
                                    web.AllowUnsafeUpdates = false;
                              }
                        }
                 }
           }
}
In this case created a SPWeb object with in elevated previliges though it is available as properties.Web.

Friday, December 13, 2013

How to Add User to Default SharePoint Groups Programatically

As every SharePoint developer or user know that when a new Site is created, Obviously 3 commonly used site specific groups will be created automatically along with some general groups.
<Site Name> Owners
<Site Name> Members
<Site Name> Visitors

To add an user to any of the above three groups of a site, we have a API method to get the groups associated with that site, programatically.
using (SPSite site = new SPSite("http://siteurl"))
{
    using (SPWeb web = site.RootWeb)
    {
        ////Get the site default groups
        SPGroup owernsGroup = web.AssociatedOwnerGroup;
        SPGroup membersGroup = web.AssociatedMemberGroup;
        SPGroup visitorsGroup = web.AssociatedVisitorGroup;

        ////Add user to groups
        SPUser user = web.EnsureUser("login");
        if (null != user)
        {
            owernsGroup.AddUser(user);
            membersGroup.AddUser(user);
            visitorsGroup.AddUser(user);
        }
    }
}

Also we can add user to other default groups like Approvers, Designers and Viewers etc., But there is no API property for web to get these groups. So we can get the group by Name.
if (web.GroupExists("Approvers"))
{
    ////Get approvers group
    SPGroup approversGroup = web.Groups["Approvers"];            
    if (null != approversGroup)
    {
        ////Add user to group
        SPUser user = web.EnsureUser("login");
        approversGroup.AddUser(user);
    }
}

Check User exists in SharePoint Group

I was looking for direct API method to check whether specified user exists in SharePoint group. Unfortunately there is no direct API check.

I found below single statement is efficient for this check. I made it a generic for re-usability.

SPGroup spGroup = web.Groups["Group Name"];
if (null != spGroup)
{
  SPUser spUser = web.EnsureUser("Login Account");
  if (null != spUser)
  {
    bool userExsists = spUser.Groups.Cast<SPGroup>().Any(g => g.Name.ToLower() == spGroup.Name.ToLower());
     if (!userExsists)
     {
        spGroup.AddUser(spUser);
     }
  }
}

Wednesday, May 30, 2012

Migration SharePoint 2007 to SharePoint 2010


As we know SharePoint 2010 has significant user experience, performance, and other improvements, most of the organizations with existing SharePoint 2007 applications are planning to upgrade to SharePoint 2010. New hardware and software requirements, architectural changes, and UI changes in the product will require solid migration and testing plans to ensure these upgrades proceed smoothly.

My goal of this migration article is to illustrate step by step migration from SharePoint 2007 to SharePoint 2010.
Here I am going to describe the migration process steps for the below scenario which exists in SharePoint 2007 environment.

Scenario: Migrating Team Site with below content/functionalities/custom solutions
  • Ø  Regular Team Site
  • Ø  Team Site with sub-sites
  • Ø  Team Site with list template
  • Ø  Team Site with sub sites using Site Template
  • Ø  Team Site with sub sites using Site Template + Custom WP solution
  • Ø  Team Site with sub sites using Site Template + Custom WP solution + Custom Content Types
Before you run any process to upgrade from Microsoft Office SharePoint Server 2007 to Microsoft SharePoint Server 2010, you have to determine which upgrade approach to take from the below two major approaches. The Article Upgrade process overview (SharePoint Server 2010) gives the more information possible approaches for migration.
The article Determine upgrade approach (SharePoint Server 2010) helps in comparing the pros and cons for each approach and to review information about special cases that might influence your approach. In addition to this information, be sure to read Review supported and unsupported upgrade paths (SharePoint Server 2010) to understand exactly which upgrade situations are valid and lead to successful upgrades.

Here in my case I am using the Database Attach Approach. The Source and Destination servers are different. The below describes the Step-by-Step Migration Process.

1.      Check Pre-Requisites for upgrading from SharePoint 2007 to 2010

2.       SharePoint 2007 with SP2 environment
3.       A web application with above scenario in SharePoint 2007 environment
5.       A web application with no site collection in SharePoint 2010 environment

2.      Run the pre-upgrade check

Note: To perform an upgrade, you must have installed Office SharePoint Server 2007 with Service Pack 2 (SP2).

The pre-upgrade checker is a STSADM operation that you run in a Microsoft Office SharePoint Server 2007 environment to find any potential issues for upgrade and to review recommendations and best practices.
STSADM -o preupgradecheck

In my environment, I got the following issues after running the preupgradecheck.

Issue 1: This server machine in the farm does not have a 64 bit version of Windows Server 2008 SP2 or higher installed.
Description: This issue is related to hardware, software, pre-requisites of SharePoint 2010 server.

Issue 2: Orphaned site collections
An orphaned site collection is a site collection exists in the content database, but it is not available in the configuration site map(CA/UI). Such site collections are not accessible and will not be upgraded properly. The following orphaned site collections were found.

/sites/MyTest (Data Source=WS2003\OfficeServers; Initial Catalog=WSS_Content_80; Integrated Security=True; Enlist=False; Connect Timeout=15)

Description: This issue is related to MyTest Site is corrupted in SharePoint 2007 server.

Issue 3: Missing server file or server configuration issues
Description: This issue is related to custom web parts, event handlers, and features etc.

Note: The generated report is available in LOG files.  

3.      Clean up the Environment:

Resolution of Issue 1:
Resolve all the environment issues mentioned in Issue 1.

Resolution of Issue 2:
·         Verify whether the reported orphan site collection exists in the specified web application through CA (UI).

Then verify whether the same orphaned site collection exists in content database using the below STSADM command
STSADM -o enumallwebs -databasename  <<name of the content database>>

It gives the count of the site collections in content database and lists all the site collections and webs inside with IDs. The orphaned site collection should be found here.

·         The orphaned site collection Sites/MyTest is deleted in content database using below STSADM command
STSADM -o deletesite -force -siteid <<site guid>> -databaseserver <<database server>> -databasename <<name of the content database>>

·         RECOMMENDATION: After deleting the orphaned site collection, it is recommended to repair the content database for any schema related issues using below STSADM command.
STSADM -o databaserepair -url <<site collection url>> -databasename  <<name of the content database>>

Note: The siteid is copied from the STSADM command prompt after running enumallwebs command.

Resolution of Issue 3:
This issue is related to custom solution. Lists all the missing web parts, features, content types etc., in content database; Make sure all the custom solutions are deployed to the farm.

Note: Run the preupgradecheck command again after resolving all the listed issues to see if there are any issues still.

4.      Backup Content Database -SharePoint 2007 Environment 

In any type of database attach upgrade, you can set the database to read-only temporarily to ensure that you capture all the data in the backup so that you are restoring and upgrading the current state of the environment. If the database are set to read-only, users can continue to view content, but they will be unable to add or change content.

5.      Restore Content Database - SharePoint 2010 Environment 

After you configure the new server farm (SharePoint 2010), you can restore the backup copies of the database new environment.

You must also set the database back to read-write before you attach and upgrade them.

6.      Verify Custom Components 

Before you attach the content database to the Web application, use the 
Test –SPContentDatabase Windows PowerShell cmdlet to verify that you have all the custom components that you need for that database against the web application.
Test-SPContentDatabase -Name <<restored content database name>> -WebApplication <URL>

7.      Attach a Content Database to a Web application 

You can use either the Mount -SPContentDatabase cmdlet in Windows PowerShell or the addcontentdb Stsadm command to attach a content database to a Web application.

Note: Using the SharePoint Central Administration pages to attach a content database is not supported for upgrading.

PowerShell Cmdlet
Mount-SPContentDatabase -Name <<restored content database name>> -DatabaseServer <<database server>> -WebApplication <<URL>> [-Updateuserexperience]

 STSADM command
STSADM -o addcontentdb -url <<web application url>> -databasename <<content database name>> [-preserveolduserexperience]

Note: Updateuserexperience & preserveolduserexperience are optional and used for visual upgrade respectively, which applies the 2010 look and feel for 2007 pages.
After you have attached a database, you can use the Upgrade Status page in Central Administration to check the status of upgrade on your site collections. After the upgrade process is complete, you can review the upgrade log file to see whether there were any issues during upgrade. Also, you can review each upgraded site to find and address any issues with how the content is displayed. For more information, see Verify upgrade and review upgraded sites (SharePoint Server 2010).

To view the Upgrade Status page:
In Central Administration, click Upgrade and Migration, and then click Check upgrade status.

8.      Visual Upgrade 

Once the content database is restored, attached to a web application and the site is accessed through browser, the site holds the 2007 look and feel if user experience operation is not used in PowerShell/STSADM while attaching content database.
To apply the 2010 look and feel to the restored sites follow the below simple approach.
Logon to SharePoint 2010 team site; click on Site Settings->Visual Upgrade, select the update the user interface radio button, which will update the SharePoint 2010 interface.

9.      Verify Successful Upgrade 

Run the below PowerShell command to check whether the upgrade/migration is successful
Test-SPContentDatabase –Name <name of the content database > -WebApplication <web application url>

It generates a report of missing custom features, web parts and event receivers….etc.

10. Deploy Custom Solution 

1.      Add & deploy the custom solution to SharePoint 2010 restored site using PowerShell or STSADM.
2.      Activate the content type and webpart features in SharePoint 2010 restored site.

11. Again Verify Successful Upgrade 


Run the PowerShell command as follows to check for successful upgrade
Test-SPContentDatabase –Name <database name> -WebApplication <URL>

      This time it should be successful, no warning/errors.

I hope this post is useful in manual migration.

Tuesday, March 15, 2011

Microsoft SharePoint 2010 Contest

Microsoft SharePoint 2010 makes it easier for people to work together. Here‘s an opportunity to test your knowledge on Microsoft SharePoint 2010. Participate in the Quiz Contest and you stand a chance to win a Windows Mobile and USB Pen Drives.

Click here for more details.