Pages

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