Pages

Dec 30, 2010

10 reasons to use Sandboxed Solutions

  • Sandboxed solutions are secure.
  • Sandboxed solutions can be monitored.
  • Sandboxed solutions do not affect other sandboxed solutions, well atleast not in other site collections is what I mean.
  • Sandboxed solutions do not touch the file system for the most part
  • Sandboxed solutions skip application pool recycles, so debugging is not such a pain.
  • Sandboxed solutions allow the site collection administrator to perform deployment and upgrades
  • Sandboxed solutions make CAS policies look like the out of style hairstyles of 1980s
  • The Solution validation framework for sandboxed solutions is exntensible, simply inherit from the SPSolutionValidator base class.
  • Sandboxed solutions remove the need for line by line code reviews
  • Sandboxed solutions allow you to offer different level of SLAs to different site collections using Resource Quotas.

What is supported by sandboxed solutions?

Basically it is a narrowed down subset of the SharePoint OM. This is controlled with VS2010 by selecting your Visual Studio project as a sandboxed solution. It will hide any methods/classes that are not available automatically.

The following capabilities and elements are available in sandboxed solutions:

  • List definitions
  • List instances
  • Onet.xml
  • WebTemplate Feature element instead of Webtemp.xml
  • Content Types/Fields
  • Navigation
  • Module/files
  • Feature callouts
  • Web Parts derived from WebPart
  • Event receivers
    • SPItemEventReceiver
    • SPListEventReceiver
    • SPWebEventReceiver
  • Custom Actions
  • Workflows

What is not supported by sandboxed solutions?

The following capabilities and elements are not available in sandboxed solutions (from MSDN):

  • Custom Action groups
  • HideCustomAction element
  • Content Type Binding
  • Web Application-scoped Features
  • Farm-scoped Features
  • CustomPropertyToolPart Class
  • programmatic workflow
  • Event receivers
    • SPLimitedWebPartManager
  • timer jobs
  • visual WebParts
  • SharePoint mapped folders (e.g. "_layouts", and "images")

The following .NET namespaces are not supported by sandboxed solutions:

  • ADO.NET
  • System.IO
  • System.Security.Cryptography
  • System.Web.UI.ClientScriptManager

Dec 28, 2010

SharePoint 2010 versus SharePoint 2007 Object Model (Microsoft.SharePoint.dll)

There are the differences between the new object model (Microsoft.SharePoint.dll) and the old.  Some classes/interfaces/enums were removed, but nothing that looks to hurt anyone.  The really cool part though...no properties or methods were removed between the two versions (doesn't mean that they are not depreciated however)!  NOTE:This is based on a beta version of SharePoint 2010.
  • Classes/Interfaces/Enums in 2007:   3225
  • Classes/Interfaces/Enums in 2010:   6658
  • New namespaces in 2010:    46
    • Microsoft.BusinessData
      Microsoft.SharePoint.Administration.AccessControl
      Microsoft.SharePoint.Administration.Claims
      Microsoft.SharePoint.ApplicationPages.Calendar
      Microsoft.SharePoint.ApplicationPages.PickerQuery
      Microsoft.SharePoint.Applications.GroupBoard
      Microsoft.SharePoint.Applications.GroupBoard.MobileControls
      Microsoft.SharePoint.Applications.GroupBoard.Utilities
      Microsoft.SharePoint.Applications.GroupBoard.WebControls
      Microsoft.SharePoint.Applications.GroupBoard.WebPartPages
      Microsoft.SharePoint.BusinessData
      Microsoft.SharePoint.BusinessData.Administration
      Microsoft.SharePoint.BusinessData.Infrastructure
      Microsoft.SharePoint.BusinessData.Infrastructure.Collections
      Microsoft.SharePoint.BusinessData.MetadataModel
      Microsoft.SharePoint.BusinessData.MetadataModel.Collections
      Microsoft.SharePoint.BusinessData.MetadataModel.Constants
      Microsoft.SharePoint.BusinessData.MetadataModel.Dynamic
      Microsoft.SharePoint.BusinessData.MetadataModel.Static
      Microsoft.SharePoint.BusinessData.MetadataModel.Static.DataAccess
      Microsoft.SharePoint.BusinessData.Offlining
      Microsoft.SharePoint.BusinessData.Parser
      Microsoft.SharePoint.BusinessData.Runtime
      Microsoft.SharePoint.BusinessData.SharedService
      Microsoft.SharePoint.BusinessData.SharedService.Structs.ExtensionMethods
      Microsoft.SharePoint.BusinessData.SystemSpecific
      Microsoft.SharePoint.BusinessData.SystemSpecific.Db
      Microsoft.SharePoint.BusinessData.SystemSpecific.DotNetAssembly
      Microsoft.SharePoint.BusinessData.SystemSpecific.Wcf
      Microsoft.SharePoint.BusinessData.SystemSpecific.WebService
      Microsoft.SharePoint.BusinessData.Upgrade
      Microsoft.SharePoint.Calculation
      Microsoft.SharePoint.Client
      Microsoft.SharePoint.CoordinatedStreamBuffer
      Microsoft.SharePoint.Diagnostics.ULSEventTemplates
      Microsoft.SharePoint.JSGrid
      Microsoft.SharePoint.JsonUtilities
      Microsoft.SharePoint.MobileMessage
      Microsoft.SharePoint.RBSWrapper
      Microsoft.SharePoint.TenantAdministration
      Microsoft.SharePoint.UserCode
      Microsoft.SharePoint.Utilities.Cab
      Microsoft.SharePoint.Utilities.SimpleParsers
      Microsoft.SharePoint.Utilities.SqlTrace
      Microsoft.SharePoint.Utilities.Win32
      Microsoft.Xslt
  • I have attached lists of
    • All new classes/interfaces
    • All removed classes/interfaces
    • All Property Changes (adds and deletions) to old classes
    • All Methods Changes (adds and deletions) to old classes
Links:
Enjoy!
Pravyn.

HOW TO: Write an SQL Webpart


Start up Visual Studio and create a new webpart. It'll be called webpart1 by default, lets leave it at that for now. First off, right click the project in the solution explorer, and click add reference. Scroll down and select System.Data. Once you've added this we're ready to begin.
Now, make your code look like this:
using System;
using System.Runtime.InteropServices;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Serialization;
using System.Data;
using System.Data.SqlClient;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace WebPart1
{
    [Guid("493c926d-f885-4965-b72d-ee18e0292630")]
    public class WebPart1 : Microsoft.SharePoint.WebPartPages.WebPart
    {
        private string _sqlStatement = "SELECT * from tblTest";
        [WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),
        WebDisplayName("SQL Statement"),
        WebDescription("Query to return a set of data")]
        public string SQLstatement
        {
            get { return _sqlStatement; }
            set { _sqlStatement = value; }
        }
        protected override void CreateChildControls()
        {
            if (string.IsNullOrEmpty(SQLstatement)
|| !SQLstatement.ToUpper().TrimStart().StartsWith("SELECT")
|| SQLstatement.Contains(";"))
            {
                Literal lit = new Literal();
                lit.Text = "Only single SELECT statement allowed"; Controls.Add(lit); return;
            }
            DataGrid grid = new DataGrid();
            
            //Attempt connection
            try
            {
                
                using (SqlConnection conn = new SqlConnection("server=SP-TEST\\databasearea; Initial Catalog=spTest; User ID=sharepoint; Password=password; Trusted_connection=yes;"))
                {
                    SqlCommand cmd = new SqlCommand(SQLstatement, conn); 
                    conn.Open(); 
                    SqlDataReader reader = cmd.ExecuteReader(); 
                    grid.DataSource = reader; 
                    grid.AutoGenerateColumns = true; 
                    grid.DataBind(); 
                    reader.Close(); 
                    conn.Close();
                } Controls.Add(grid);
            }
            catch (Exception exp)
            {
                Literal errMessage = new Literal();
                errMessage.Text = exp.ToString();
                Controls.Add(errMessage);
            }
        }
    }
}
Now just build the control and your webpart should be working well. Lets take a look at some of the key parts.
private string _sqlStatement = "SELECT * from tblTest";
        [WebBrowsable(true),
        Personalizable(PersonalizationScope.Shared),
        WebDisplayName("SQL Statement"),
        WebDescription("Query to return a set of data")]
        public string SQLstatement
        {
            get { return _sqlStatement; }
            set { _sqlStatement = value; }
        }
This part sets the SQL query you're about to run.
using (SqlConnection conn = new SqlConnection("server=SP-TEST\\databasearea; Initial Catalog=spTest; User ID=sharepoint; Password=password; Trusted_connection=yes;"))
                {
                    SqlCommand cmd = new SqlCommand(SQLstatement, conn); 
                    conn.Open(); 
                    SqlDataReader reader = cmd.ExecuteReader(); 
                    grid.DataSource = reader; 
                    grid.AutoGenerateColumns = true; 
                    grid.DataBind(); 
                    reader.Close(); 
                    conn.Close();
                } Controls.Add(grid);
This part connects to the database and displays the results in a data grid. Note the server name SP-TEST\\databasearea has two backslashes, this is to counter the escape effect of a backslash.
So that's it really, tiny bit of code with big implications. Hope it opens some doors for you.

Dec 22, 2010

SharePoint Implementations: the 80/20 rule

“if you can earn 80 percent of your requirement with current SharePoint features and need to development for other features , SharePoint is your solution.”

SharePoint is a Development Platform with lots of functionality available out of the box. SharePoint MVP, Sahil Malik, also recently did a podcast show where he also quoted the 80/20 rule. So what is it?

When you’re gathering requirements, gather requirements!

One of the tips that Sahil raised was that before saying “yes, no problem” about implementing a Solution in SharePoint, do a quick Proof of Concept (PoC) to guarantee it will actually work. The best approach when gathering requirements from Business Users is to gather the requirements…and not drag the conversation down to how it will be implemented in SharePoint. This can be hard sometimes as you wish to explain how you can leverage SharePoint functionality that may improve the End User experience for the End User and extend the requirements with little effort.

Watch out for the traps

Dragging it down to the implementation will cause you to promise functionality that may not be possible with excessive customisation or development. Sahil used a great example of the limitation around SharePoint 2007 not being able to have a BDC Site column in a Content Type, this kind of thing would not be obvious without actually running a PoC.

There are plenty of these trip wires in the SharePoint platform where you think it would be easy and then realise it isn’t! The 80/20 rule is the guidance around where 80% of the requirements can easily be implemented using out of the box components with the Web UI or SharePoint Designer. There are often requirements (the last 20%) that require customisations or development work to occur.

One step forward, one step back

The other thing to bare in mind is that there are often multiple ways to implement the solution to meet the requirements. Often the last 20% of the requirements to be implemented can mean taking a few steps back from the implementation approach and moving down another approach. With all implementations it is worth putting a PoC together across all the requirements where there are unknowns. This would reduce the amount of back steps taken during the process.

Do you really need this?

Often with a lot of discussions with Business Users, they will mention requirements that they have come up with that may never be used. Don’t be a afraid to push back on these, especially if it is something in the last 20%. A delicate way to do this is to take the Agile methodology approach to requirements and rate the priorities and then schedule implementation based on this. Often Business Users see the functionality roll out gradually as more requirements are reached and realise that some of their requirements are not necessary.

Dec 21, 2010

Common File Locations Accessible from SharePoint WSPs

Folder in 12 hiveContains
\ISAPI\HELP\[LCID]SharePoint help files. Deploy your own .chm files to this folder (or a localized subfolder)
\CONFIGWeb.config customizations
\ISAPISharePoint web services (deploy your custom web services here as well); maps to /_vti_bin
\ResourcesGlobal .resx files accessed from custom features and site definitions
\TEMPLATE\CONTROLTEMPLATES.Ascx user controls; maps to /_controltemplates
\TEMPLATE\FEATURESFeatures, of course!
\TEMPLATE\LAYOUTSCommon site pages; maps to /_layouts
\TEMPLATE\IMAGESCommon site image files; maps to /_layouts/images
\TEMPLATE\SiteTemplatesAll SharePoint site definitions; create a \xml to deploy your onet.xml custom site definition
\TEMPLATE\THEMESAll UI elements used in themes; clone an existing theme folder to create your own
\TEMPLATE\[LCID]\XMLWebtemp.xml files to define available site definitions; add an xml file here for your custom site definition
\TEMPLATE\ADMINPages used by Central Admin; maps to /_admin
\ADMISAPIAdministration web services; maps to /_vti_adm

Oct 12, 2010

Exchange (Outlook) distribution list (mailing group) not showing up in SharePoint

Scenario: There is a distribution list you can see and use in outlook, but when you search for the same list in SharePoint it doesn’t show up in the people picker. What gives?

Chances are that the distribution list is not security enabled. This would need to be done by your domain administrator. He would need to change the ‘Group Type’ of the list from ‘distribution’ to ‘security’. Once this is done your SharePoint administrator would need to run a profile import so SharePoint can pick up the change immediately (alternatively you can let SharePoint automatically pick it up during its scheduled AD crawl).

Oct 11, 2010

Adding Spell Checker to custom SharePoint Pages

If you have been doing SharePoint development for some time it is more than likely that you have developed your fair share of custom pages and custom controls/webparts for MOSS 2007. Where possible I try and leverage the existing SharePoint controls (such as the People Picker) to use on my pages as Microsoft has already done all the work developing these controls. One aspect I had never been able to get going until recently though was adding a spell checker control to my pages. I have just discovered that this is alot easier than I thought.

To add the out of the box spell checker all you need to do is:
1. Make sure you have the right page directive on the page you are adding the control to

<%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

2. To the head of your page, add the following controls, which will give you the javascript required for the spell checker to run:

<SharePoint:ScriptLink ID="ScriptLink1" Language="javascript" Name="core.js" runat="server" />
<SharePoint:ScriptLink ID="ScriptLink2" Language="javascript" Name="bform.js" runat="server"
/>
<SharePoint:ScriptLink ID="ScriptLink3" Language="javascript" Name="SpellCheckEntirePage.js" runat="server" />

3. Add the following block of javascript code to your page:

<script language="javascript" type="text/javascript">
function doSpellCheck() {
SpellCheckEntirePage('/_vti_bin/SpellCheck.asmx', '/_layouts/SpellChecker.aspx');
}script>

4. Now all you need to do is create a link or a button which starts the spell checker. to this you just need to add the onclick javascript method 'doSpellCheck()'

class="ms-toolbar" href="javascript:doSpellCheck()">Spelling...a>

As a result of using this on click event, SharePoint will invoke a popup control which will enable your users to run a spell check against any input control that is on your page. Of course there might be certain controls on your page that you do not want to spell check against (such as People Pickers!) so all you need to do is add the attribute excludeFromSpellCheck="true" to any control that should not be spell checked:

<asp:TextBox ID="txtDontSpellCheck" runat="server" CssClass="ms-long" excludeFromSpellCheck="true">asp:TextBox>

All in all, for a few lines of code, this really adds a heck of a lot of power and useability to your custom SharePoint pages!

Sep 9, 2010

How to: Converting List Item to SPUser object..?

Hi All,

Many times we need to cast a list item to a SPUser object. It can easily done using these steps:

Step1: Get the current item
SPListItem currentItem = properties.ListItem;

Step2: Get the value display name of the current logged in user and Created by Field of the current item
currentUser = currentItem["Author"].ToString();

Step3: Get the user id as integer
int userid = Convert.ToInt32(currentUser.Substring(0, currentUser.IndexOf(";#")));

Step4: Convert SharePoint user which matches the ID
SPUser user = currentTeamSite.AllUsers.GetByID(userid);

There is one more case where we have number of users. In this scenario,
we can loop the users:

--------------------------------------------------------------------------------
// get a reference to the "Alerts" list as an instance
SPList alerts = spWebRoot.Lists["Checklists Alerts"];
// get the query object for user alert
SPQuery queryUserAlert = new SPQuery();
queryUserAlert.Query = "" +
"" +
"" +
"" + teamName + "" +
"
" +
"
";

SPListItemCollection noOfUsers = alerts.GetItems(queryUserAlert);

//Get all the users in that team (such as Desktop Support - Daily)
foreach (SPListItem item in noOfUsers)
{
//Use "GetUser" function for List "item" into a SPUser ojbect
SPUser user = GetUser(item, item.Fields["User"]);

// REMAINING LOGIC
}


private SPUser GetUser(SPListItem item, SPField userField)
{
string currentValue = item[userField.Title].ToString();
SPFieldUser field = (SPFieldUser)userField;
SPFieldUserValue fieldValue = (SPFieldUserValue)field.GetFieldValue(currentValue);
return fieldValue.User;

}

Happy Coding,

Cheers
--Pravyn

Aug 30, 2010

How to rename SharePoint site and subweb

To rename a sub site is basically very easy to execute. In this article, I use WSS 2.0 environment (pretty old :) ) to rename SharePoint sites. Let’s say we have the url likehttp://sharapoint.company.com/Internationl%20site/EmeaFS and it needs to be renamed ashttp://sharapoint.company.com/Internationl%20site/GlobalFS.

In SharePoint we have command line utility tool STSADM. The format to rename web is stsadm -o renameweb -url http://server/site/web1 -newname web2

Here we need to user the WFS instead of url sharepoint.company.com. So, if the web server name iscobldwsswd1, then the actual command would be Stsadm –o renameweb –url http://cobldwsswd1/International IT/EmeaFS/ -newname “GlobalFS”.

How to rename SharePoint site

How to rename SharePoint site

Please note how we need to take care the query parameter like %20 with SPACE in the command line parameter.

To rename top level SharePoint site, there is no specific STSADM command. You can just take a backup of this site and restore the same on new site. Below the example how you can take a backup of the Sharepoint site HR.
stsadm -0 backup -url http://cobldwsswd1/site/HR -filename “D:\SPSiteBackup\HR.dat”

Next action item is to create one site with the new name say HRManager and restore the HR site over there.
stsadm -0 restore -url http://cobldwsswd1/site/HRManager -filename “D:\SPSiteBackup\HR.dat” .

Last action item should be delete the existing HR site http://cobldwsswd1/site/HR.

Remarks:

  • You cannot use the Rename method to convert a host-header-named site collection to a path-based site collection or vice versa.
  • The new URL must be reachable in the Web application and must not already be used as an alternate access mapping URL.
  • If you have .Net 1.1 installed on your server, then first you need to create the new site i.e. HRManager in this example, and then you can restore the site. Otherwise you will get error message in the command tool that the site is not exist. However if you have .NET 2.0 installed on your machine, you can just do the same task in one shot as described in this article.