PostRank Topblogs 2009 - #20 in Sharepoint

Windows Live Alerts web tracker
Chat with me if I'm online!
search blog
most popular
MCP MCTS MCT MVP

SP 2010: Uploading files using the Client OM in SharePoint 2010

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

In this article I will guide your through the process of uploading a document to any chosen document library in SharePoint 2010 through the Client Object Model.

This application has a very simple usage scenario:

  1. Type in the URL to your site where you want to upload your file
  2. Choose one of the available Document Libraries
  3. Click Upload a Document and you'll get a browse-dialog to choose the file

Example:

1) Enter a servername and click Fetch Libraries
2) Select the Document library you want to upload your file to
image

3) Browse for a local file on your filesystem
image

4) Click the magic button (Upload) and you'll see your document shoot straight into SharePoint from your client machine(s)
image

How to utilize the Client Object Model in SharePoint 2010 to upload files

The most important thing to learn about when it comes to uploading files with the Client OM is to master the FileCreationInformation class that comes with the Client OM.

Take a look at this complete snippet to see how you can upload a file:

private void btnUploadDocument_Click(object sender, EventArgs e)
{
    string library = listBox1.SelectedItem.ToString();
 
    OpenFileDialog openDialog = new OpenFileDialog();
    openDialog.Multiselect = false;
 
    if(openDialog.ShowDialog() == DialogResult.OK)
    {
        SP.ClientContext ctx = new SP.ClientContext(tbSite.Text);
 
        var web = ctx.Web;
 
        var fciNewFileFromComputer = new SP.FileCreationInformation();
        fciNewFileFromComputer.Content = File.ReadAllBytes(openDialog.FileName);
        fciNewFileFromComputer.Url = Path.GetFileName(openDialog.FileName);
 
        SP.List docs = web.Lists.GetByTitle(library);
        SP.File uploadedFile = docs.RootFolder.Files.Add(fciNewFileFromComputer);
 
        ctx.Load(uploadedFile);
        ctx.ExecuteQuery();
 
        // Tell your user that the file is uploaded. Awesomeness has been done!
        MessageBox.Show(openDialog.FileName + " uploaded to " + library);
    }
}

Things to note here is that I'm currently not changing the authentication for this application. That means it'll be using your Windows/Domain Credentials.

Learn more about the authentication options here:
http://www.zimmergren.net/archive/2009/11/30/sp-2010-getting-started-with-the-client-object-model-in-sharepoint-2010.aspx

Summary, References & Download

With this sample application you can easily upload any file to any of your SharePoint 2010 document libraries by first entering the URL to the site, then selecting your library and finally browsing for a file and click OK.

Easily enough, you can change or extend this project the way you want it to work if you've got specific requirements to upload files using the Client OM.

References

  1. Getting Started with the Client Object Model
  2. FileCreationInformation

Download project

You can download this sample project here.

Enjoy this piece of awesomeness :-)

 


Published: Jun-10-10 | 21 Comments | 0 Links to this post

SP 2010: How to create a PowerShell Snapin Cmdlet - Part 2

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

In my previous article (How to create a PowerShell Snapin - Part 1) I talked about the general approach to create a custom PowerShell Cmdlet. However, in Part 1 I did not talk about how you create SharePoint 2010 specific Cmdlets. That's what this article is all about.

So without further ado, I will quickly brief you on how you can create a custom PowerShell Cmdlet for SharePoint 2010 using the SPCmdlet base class.

In my example I will create a very simple Cmdlet you can use to automatically create demo-sites for use in demo-purposes or development scenarios so you don't have to go about creating all the different sites by hand, and without a need to create scripts to do the same.

Creating a custom PowerShell Cmdlet that talks with SharePoint 2010

I will add some functionality to my previous project (found in my previous article) and extend that project with some custom SharePoint 2010 specific Cmdlets to get your started with writing PowerShell cmdlets for SP 2010.

In order to do this, we should derive from a subclass of the type SPCmdletBase. The following base classes deriving from SPCmdletBase are available:

1. Create a new Cmdlet (SPNewCmdletBase)

  • Create a new Class and name it something of your own preference (I chose this silly name: SPAwesomeness.cs)
  • Add a reference to the following two namespaces:
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.PowerShell;

  • Add the following base code to your class:
    using System;
    using System.Management.Automation;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.PowerShell;
     
    namespace Zimmergren.SP2010.PowerShell
    {
        [Cmdlet(VerbsCommon.New, "SPCreateDemoSites")]
        public class SPAwesomeness : SPNewCmdletBase<SPWeb>
        {
            protected override SPWeb CreateDataObject()
            {
                throw new NotImplementedException();
            }
        }
    }
     

As you can see in the code above I've got a class called SPAwesomeness which derives from the SPNewCmdletBase class which in turn derives from the SPCmdletBase. SPNewCmdletBase should be derived from when you create a Cmdlet that should create and save data to SharePoint.

Also note that we're using the Attribute [Cmdlet] to set a name for our command, in this case SPCreateDemoSites.

When deriving from this class, you need to implement at least one method override, in this case CreateDataObject. This is where our magic will take place!

2. Add some logic to your custom SharePoint Cmdlet

Now that we've got the basic code up and out of the way, we need to add some logic to actually make something happen.

I've added some very simplistic code to create some Demo-sites based on the available templates in your installation. It looks like this:

using System;
using System.Management.Automation;
using Microsoft.SharePoint;
using Microsoft.SharePoint.PowerShell;
 
namespace Zimmergren.SP2010.PowerShell
{
    [Cmdlet(VerbsCommon.New, "SPCreateDemoSites")]
    public class SPAwesomeness : SPNewCmdletBase<SPWeb>
    {
        // Let's add a mandatory parameter that indicates that you need
        // to specify a value for this property through the PS console 
        [Parameter(Mandatory = true, 
            ValueFromPipeline = true, 
            Position = 0, 
            HelpMessage = "Specify an existing site to extend with demo sites")]
        public string SiteUrl { get; set; }
 
        protected override SPWeb CreateDataObject()
        {
            var site = new SPSite(SiteUrl);
 
            try
            {
                // SharePoint Server Publishing Infrastructure feature 
                site.Features.Add(new Guid("f6924d36-2fa8-4f0b-b16d-06b7250180fa"));
            }catch(Exception ex)
            { /* Empty catch block is not recommended :-) */}
 
            SPWeb demoWeb = CreateBaseDemoSite(site);
 
            // When we're done, you'll get this object returned to the PS console
            return demoWeb; 
        }
 
        private static SPWeb CreateBaseDemoSite(SPSite site)
        {
            // Creates a Blank Site which will host all the Demo-sites
            SPWeb web = site.AllWebs.Add(
                "DemoSite", 
                "Demo Sites", 
                "Demo Sites", 
                1033, 
                "STS#1", 
                false, 
                false);
 
            web.QuickLaunchEnabled = true;
            CreateDemoSites(web);
 
            return web;
        }
 
        private static void CreateSite(SPWeb parentWeb, string url, string template)
        {
            string desc = " created by Tobias Zimmergren's custom cmdlets";
            parentWeb.Webs.Add(url, 
                url + " demo", 
                url + desc, 
                1033, 
                template, 
                false, 
                false);
        }
 
        private static void CreateDemoSites(SPWeb web)
        {
            SPWebTemplateCollection webTemplates = 
                web.GetAvailableWebTemplates((uint)web.Locale.LCID, true);
            foreach (SPWebTemplate template in webTemplates)
            {
                try
                {
                    CreateSite(web, 
                        template.Title.Replace(" ", ""), 
                        template.Name);
                }
                catch (Exception ex) 
                { /* Empty catch block is not recommended :-) */ }
 
            }
        }
    }
}
 

3. Test your custom SharePoint 2010 cmdlet

In order to test it, follow along with the steps I mentioned in my previous article (here) to deploy it - then call the new command you've created called New-SPCreateDemoSites like this:

image

It will ask you to supply the mandatory property (SiteUrl), so type in an existing url to an existing site collection and execute like this:

image

Now you'll need to wait for a few minutes. What's happening now is that your Cmdlet is creating a site called "Demo Sites" and will add a whole bunch of sub-sites to that new site.

Navigate to your new site called "Demo Sites" and you should see something like the following sub-sites created:

image

Summary & Download

Quite easily you've created your first SharePoint 2010 Cmdlet extension to operate with the SPCmdletBase classes. In this case we've created a new site called Demo Sites and added a bunch of sites to that new site, as per the available templates on your server.

Download project

You can download my sample project here

Enjoy this awesomeness!


Published: Jun-08-10 | 8 Comments | 0 Links to this post

SP 2010: How to create a PowerShell Snapin - Part 1

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

In this article I will talk about how you can get started with creating custom PowerShell commands for SharePoint 2010 that you can use.

You will see how easy it actually is to build a custom class library that in turn is an extension to the PowerShell console and will add a couple of extra commands according to your preference.

The reasons for wanting to do this is an endless list, but as an example if you've got repeated tasks you'll need to perform that are not available out of the box, you can create them yourself and then use normal PowerShell scripts to execute your code. That way you can easily build your own custom commands (CmdLet) for PowerShell which basically extends the functionality to support whatever scenario you've got.

You might remember that in SharePoint 2007 you could extend the STSADM.EXE command with something called STSADM Extensions. The approach I'm talking about in this article is pretty much the same concept - extending the build-in commands of your PowerShell console by adding custom code.

How to create a PowerShell Snapin

Download the Windows SDK in order to get the
System.Management.Automation.dll file for PowerShell easily accessible.

1. Create a new Class Library project

Start out by creating a new Visual Studio 2010 Class Library project and give it a proper name.
I've named mine Zimmergren.SP2010.PowerShell.

Add assembly references

  1. Add a reference to System.Management.Automation
    1. This DLL is located  in:
      C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\
      (if you installed the Windows SDK as I told you earlier on in this article)
  2. Add a reference to System.Configuration.Installation

You should now have the following reference added: 
image

2. Create a PowerShell Installer class

In order for our PowerShell Cmdlet to work, we need to create an installer-class. This class is called when you install the SnapIn/Cmdlet and will provide the system with some information like where it comes from and what it's supposed to do.

Start out by creating a new class in your project, I named mine PowerShellInstallerClass.cs. Next, add the following code to that class:

using System.ComponentModel;
using System.Management.Automation;
 
namespace Zimmergren.SP2010.PowerShell
{
    [RunInstaller(true)]
    public class PowerShellInstallerClass : PSSnapIn
    {
        public override string Name
        {
            get
            {
                return "Zimmergren.SP2010.PowerShell";
            }
        }
 
        public override string Vendor
        {
            get
            {
                return "Tobias Zimmergren";
            }
        }
 
        public override string Description
        {
            get
            {
                return "Tobias Zimmergren's awesome PowerShell Cmdlets";
            }
        }
    }
}

This essentially provides some information to the system upon installation of your SnapIn.

3. Create a PowerShell Cmdlet class

Now you need to continue this venture by creating a new class in your project. I named mine TestCmdlet1.cs.

Use the [Cmdlet()] attribute on your class to tell the system that it's going to be a Cmdlet for PowerShell like this:

using System.Management.Automation;
 
namespace Zimmergren.SP2010.PowerShell
{
    [Cmdlet(VerbsCommon.Get, "TestCmdlet1")]
    public class TestCmdlet1 : PSCmdlet
    {
    }
}

Next, you should override the methods you want to execute your code and add some dummy-code. There's a couple of different methods to use here:

  • BeginProcessing()
  • EndProcessing()
  • ProcessRecord()
  • StopProcessing()

You should make sure your class looks like this so we can test the first part out:

using System.Management.Automation;
 
namespace Zimmergren.SP2010.PowerShell
{
    [Cmdlet(VerbsCommon.Get, "TestCmdlet1")]
    public class TestCmdlet1 : PSCmdlet
    {
        protected override void BeginProcessing()
        {
            WriteObject("BeginProcessing() method - Execution has begun");
        }
 
        protected override void ProcessRecord()
        {
            WriteObject("ProcessRecord() method - Executing the main code");
        }
 
        protected override void EndProcessing()
        {
            WriteObject("EndProcessing() method - Finalizing the execution");
        }
    }
}

4. Deploy the new PowerShell Snap-ins

Since this is a generic Class Library-project, we need to create some kind of deployment script to make sure that our Cmdlet gets deployed when we build our project.

There are two requirements for deploying and installing our PowerShell Cmdlet:

  1. Deployed to the server (Using GACUTIL)
  2. Installed on the server (using INSTALLUTIL)

In this sample project I'm simply adding two lined in the Post-Build actions like this::

"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\gacutil.exe" -if "$(TargetPath)" "C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe" "$(TargetPath)"

You'll find the post-build events if you click project properties and go to this box:

image

5. Project overview

Your project should look something like this:

image

6. Test your PowerShell Snapin

In order to test our project, we now just need to build the Visual Studio project and the post build scripts will automatically hook up our assembly in the GAC and use INSTALLUTIL to install the Cmdlet.

To try the commands out, you need to launch a powershell console and type in the following command:

Add-PSSnapin Zimmergren.SP2010.PowerShell

Now you should be able to just call your command (in my case, it's called TestCmdlet1) like this:

TestCmdlet1

This should bring your the following output in your PowerShell console window:

image

Great, our very first PowerShell cmdlet is created - and we have validated that it works!

Summary & Download

In this article we talked about how you create a general PowerShell Cmdlet in order to extend the capabilities in your PowerShell consoles. There's no business logic incorporated in this sample, that's up to you to implement in your projects. You've got the starting point to get sailing on the great PowerShell seas right here!

In my next article (Part 2) I will talk about the SharePoint 2010 specific details for creating a custom Cmdlet for your SharePoint installations. It will cover how you create custom Cmdlets to interact with the SharePoint 2010 object model in a nice way.

Download

Download this project here

Enjoy!


Published: Jun-07-10 | 5 Comments | 0 Links to this post

SP 2010: SharePoint Server 2010 - Creating a custom Document ID provider

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

In this article I will talk about how you can create your custom Document ID provider for your SharePoint Server 2010 installation. Sometimes I've been getting the question weather or not it's possible to change the behavior or change the way the Document ID's are generated, and some people have a tendency to say no to that question, just because there's no interface or out of the box functionality to do so.

I'll give you a quick walkthrough of how you can extend your Site Collection by adding a custom Document ID provider, that will automatically generate custom ID's based  on your own algorithms entirely!

Recommended reading about Document ID's before proceeding: 
http://msdn.microsoft.com/en-us/library/ee559302(office.14).aspx

Document ID overview

This section will give you a very brief conceptual overview of Document ID's in SharePoint Server 2010.

What is Document ID's?

Document ID's in SharePoint Server 2010 provide you with the ability to tag documents with a unique identification number. Something a lot of my clients have done manually or by implementing custom solutions to take care of in SharePoint 2007. With this new feature, you get all the required functionality to tag documents with unique identification numbers based on a specific pre-set formula with a custom prefix.

See this sample screenshot for an example:
image

Where do I enable Document ID's for my Site Collection?

In order to enable Document ID's in your Site Collection, you'll need to activate the Site Collection Feature called Document ID Service.

See this screenshot for an example:
image

How do I change the way my Document ID's are generated?

If you want to alter the way the Document ID's are generated for your documents in your Site Collection, you can do that by navigating to:

Site Actions - Site Settings - Document ID Settings, like so:
image

From this new settings page, you'll get the possibility to tell SharePoint how it should generate your unique ID's. You can specify a prefix for all the generated ID's:
image

I want to take it one step further!

If you're not quite satisfied with the way SharePoint 2010 generates your Document ID's for you, then you should most definitely follow along with the rest of this article as I will guide you through the steps to create your very own Document ID provider to generate exactly the kind of ID's you want - based on your very own code/algorithms!

Bring it on!

Learning about a SharePoint 2010 Custom Document ID provider

This section will give you an overview of what you will need in order to create a custom Document ID provider for SharePoint Server 2010!

Note: As of this writing MSDN isn't fully updated on these new SharePoint Server namespaces. Some details may or may not change when SharePoint Server 2010 is released into the wild (RTM)

Microsoft.Office.DocumentManagement

The namespace Microsoft.Office.DocumentManagement contains a class called DocumentIdProvider, which will be the base for our upcoming project!

Microsoft.Office.DocumentManagement.DocumentIdProvider

This is the class we will derive from when creating our custom provider. It contains three (3) abstract methods and one (1) abstract method that we need to implement:

A description of each of these methods and the property will be made inline in my code in the samples!

Creating a SharePoint Server 2010 Custom Document ID provider

Let's code this little piece of functionality, shall we. The final project (very basic) will look something like this:
image

So, let's get coding.

1. Create a class and derive from DocumentIdProvider

public class CustomDocumentIdProvider :
Microsoft.Office.DocumentManagement.DocumentIdProvider
    {
        // Method to generate the actual document ID. Awesomeness lives here!
        public override string GenerateDocumentId(SPListItem listItem)
        {
            // In this method we will tell SharePoint how it should generate
            // the unique ID we want.
            // In my case, I've just created a dummy-generator. 
            // Normally you would perhaps want to fetch this from another system or
            // generate it properly instead of like this.. 

            // Points to a method I've created that generates foo-ID's
            return FooSampleIDGenerator.GetFooUniqueID();
        } 

        public override bool DoCustomSearchBeforeDefaultSearch
        {
            // If set to true: It will call the GetDocumentUrlsById method before search
            // If set to false: It will use SharePoint Search before custom methods
            get { return false; }
        } 

        public override string[] GetDocumentUrlsById(SPSite site, string documentId)
        {
            // Returns an array of URLs pointing to 
            // documents with a specified DocumentId
            // An empty string array 

            // This is where you will implement your logic to find
            // documents based on a documentId if you don't want to use
            // the search-approach.
            return new string[] { };
        } 

        public override string GetSampleDocumentIdText(SPSite site)
        {
            // Returns the default Document ID value that will be initially
            // displayed in the Document ID search web part as a help when searching
            // for documents based on ID's.
            // This should correspond with the way you've designed your ID pattern
            return "AWESOME-12345-67890-SharePointRules";
        }
    }

2. Create a Feature Receiver to hook up your custom provider with your Site Collection

public class ProvisionCustomDocIdProviderEventReceiver : SPFeatureReceiver
{
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        DocumentId.SetProvider(properties.Feature.Parent as SPSite,
                                                                 new CustomDocumentIdProvider());
    }
    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        DocumentId.SetDefaultProvider(properties.Feature.Parent as SPSite);
    }
}

Actually, you're all done with the code for now.

3. Go to Document ID Settings page and see this message appear

image

This basically means that your custom provider has been successfully enabled (as per our Feature Receiver).

4. See that the Document ID's on your documents now is using your custom provider

(Please allow for some time to pass so the Timer Jobs can do their magic, or manually go into Central Admin and run the timer jobs instantaneously)

Behold, awesome custom Document ID provider in action:
image 

Summary and Download

What did we just do?

What we just did was to create a custom Document ID provider that generates our very own custom Document ID's based on whatever algorithm or pattern we want. There's no need to follow the built-in format for your generated IDs - which some people have presented in their seminars and blogs. So there you go, step by step!

This could be especially awesome if you've got an external system generating Document ID's already, and you want SharePoint to use those ID's alongside whatever other system is running. Use your own imagination as to what can be done. The code is in your hands, Obi Wan Coder!

Download project

You can download my sample project here

Enjoy, and please don't be afraid to leave comments!


Published: Apr-13-10 | 36 Comments | 0 Links to this post

SP 2010: Validate Sandboxed Solutions using SPSolutionValidator

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

If you've been playing around with SharePoint 2010 lately, you've most likely noticed a new concept introduced as "Sandbox Solutions".

With sandboxed solutions (read more about them here: http://msdn.microsoft.com/en-us/library/ee536577(office.14).aspx) comes the possibility to scope your solutions to Site Collection (into the new Solution gallery).

A question I often get is how you can validate those solutions automatically, and therefore I'll lay out the basic principles of creating a Sandbox Solution Validator which now is part of the SharePoint object model.

What will happen?

If you have a custom Solution Validator hooked up with your farm, a custom error page will be displayed, and the solution will not be activated.

If you try to activate the solution:
image

Our custom Solution Validator kicks in and in this case disallows the solution and displays the following custom error page:
image

So, let's get down to business!

Building a Solution Validator

What we need:

  1. A Solution Validator
  2. A feature to install/uninstall the validator in our Farm

1. Let's begin by creating our custom Solution Validator class

Essentially this is just a simple class, inheriting from SPSolutionValidator which gives us some methods we can override. Check this example out:

using System.Runtime.InteropServices;
using Microsoft.SharePoint.UserCode;
using Microsoft.SharePoint.Administration; namespace

Zimmergren._2010.SolutionValidation
{
    [Guid("29e3702d-5d8c-45ad-b1aa-a2087b9e8585")]
    public class ZimmergrenSolutionValidator : SPSolutionValidator
    {
        private const string myAwesomeValidator = "ZimmergrenSolutionValidator";
       
        // Not used, but needed for deployment and compilation
        public ZimmergrenSolutionValidator(){}  

        public ZimmergrenSolutionValidator(SPUserCodeService sandboxService) :
                   base(myAwesomeValidator, sandboxService)
        {
            // Use this to define a unique identification number
            // You may need this when updating/modifying the validator
            Signature = 666;
        } 

        public override void ValidateSolution(SPSolutionValidationProperties properties)
        {
            base.ValidateSolution(properties); 

            // Set to false if you want invalidate the solution
            // Set to true (default) if you want to validate
            properties.Valid = false; // Being evil and invalidates all solutions for test!

            // Then specify an errorpage to display
            // Tip: Create a nice application page for this..
            properties.ValidationErrorUrl =
                      "/_layouts/Zimmergren.2010.SolutionValidation/InvalidSolution.aspx";
        }
    }
}

In my sample I used an override of the ValidateSolution method and invalidated the solution to show you that it actually works.

The two most suitable methods for overriding are:

  1. ValidateSolution
  2. ValidateAssembly

2. We need to make easy installable (Read: Feature)

In order for our awesome solution validator (which in this case is very slim and don't really do any real validation, rather invalidates all solutions) - we need to let the SPUserCode service (Sandboxed Solution Service in layman terms) know that we want to hook it up.

This can easily be done using a Farm feature, using PowerShell or just plain'ol Object Model code in any application.

My approach is of course to make it as easy as possible for the end-user and administrator, so I'll create a Farm Feature with the following snippets of code:

[Guid("d0d086ec-2bef-45e8-be8b-a67895c1bd3b")]
public class ZimmergrenSolutionValidatorEventReceiver : SPFeatureReceiver
{
    public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {
        SPUserCodeService sandboxService = SPUserCodeService.Local;
        SPSolutionValidator zimmerValidator =
                new ZimmergrenSolutionValidator(sandboxService);
        sandboxService.SolutionValidators.Add(zimmerValidator);
    }

    public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
    {
        SPUserCodeService sandboxService = SPUserCodeService.Local;
        Guid zimmerValidatorId =
                sandboxService.SolutionValidators["ZimmergrenSolutionValidator"].Id;
        sandboxService.SolutionValidators.Remove(zimmerValidatorId);
    }
}

Summary and reflections

If you want to create some kind of check to automatically validate solution that are uploaded by end-users in their Solution Galleries, this is the way to do it.

Solution validators are very easy to write, and they can be installed using a few different approaches. My take is to create a farm feature, while you could still do it using powershell or in any way you want through the object model.

Good resources on Sandboxed Solutions:

  1. Deploying a Sandboxed Solution
  2. Sandboxed Solution Considerations
  3. Sandboxed Solution Architecture

Enjoy!


Published: Mar-20-10 | 16 Comments | 0 Links to this post

SP 2010: Getting started with LINQ to SharePoint in SharePoint 2010

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

In SharePoint 2010 you now have the ability to use LINQ syntax to fetch items from your lists instead of using the "traditional" approach of CAML queries. (Including SPSiteDataQuery and SPQuery objects)

In this article I will give you a brief introduction to how you can get started using LINQ queries in SharePoint, also known as LINQ to SharePoint.

Basics of LINQ?

As a prerequisite to this article, I'm going to imply that you know what LINQ is and how to write basic LINQ queries in any .NET application already. I'm not going to dive into the details about LINQ or the syntax itself here - please see MSDN for that!

LINQ to SharePoint!

In order to work with LINQ in SharePoint 2010, we need use a tool called SPMetal.exe which resides in the 14\bin folder. This tool is used to generate some entity classes which Visual Studio 2010 can use to get IntelliSense, and allows for LINQ-based queries to be performed on your lists.

Noteworthy:

  • LINQ to SharePoint queries are translated to proper CAML queries
  • CAML queries are in turn later translated to SQL queries

SPMetal.exe

Using the tool called SPMetal, we generate our entity-classes that are needed to perform these object oriented queries toward our SharePoint server.

These are the required steps to get hooked up:

  1. Launch a cmd-window and navigate to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\bin
    image
  2. Run the following command to utilize the SPMetal.exe tool with the following syntax:
    1. SPMetal.exe /web:http://yoursite /code:C:\YourEntityFile.cs
    2. Example:
      image
  3. Now navigate to C:\ (or wherever you chose to output your file) and make sure the file has been generated:
    image
  4. Open up the file and take a look at the content that SPMetal now have provided us with:
    image
    Note that the class name is now MyEntitiesDataContext. It's based on the name you specify as your code file in the SPMetal.exe command line tool.

    If you were to use /code:C:\Awesome.cs instead, it would generate a class called AwesomeDataContext.

With that done - all we need to do is import it to one of our projects and use it!

Visual Studio 2010 - Let's create a sample Web Part that utilizes LINQ to SharePoint

In this sample I will create a simple Web Part that will use LINQ to SharePoint syntax to fetch some information from the Announcements list. A basic sample I use in my training classes as well, and should be fairly easy to grasp!

  1. Create a new project (I'm going to create a new Visual Web Part project)
  2. Import your DataContext-file by choosing your Project -> Add -> Existing Item:
  3. Specify your file (mine is called MyEntities.cs):
  4. Make sure it's properly placed in your project structure - then we're good to go:
    image

Alright - that's easy enough. Thus far we have created an entity file using SPMetal.exe and now we have successfully imported it into our project.

Add proper references

Now in order to use LINQ to SharePoint, you also need to reference the Microsoft.SharePoint.Linq assembly. Point to references, right-click and choose "Add Reference" and select the Microsoft.SharePoint.Linq.dll file:
image

In your code, reference the assemblies:
image

Ready to code?

What you should've done up until now is this:

  1. Generate your entities using the SPMetal.exe tool
  2. Reference the newly created file from your SharePoint project
  3. Make sure you're using the proper references for System.Linq and Microsoft.SharePoint.Linq
  4. Be ready to code :-)

Code!

In my example I will have a Visual Web Part that will use LINQ to SharePoint to fetch all Announcements from my Announcement-list and work with those results. If you want to see the entire project, look at the bottom of this article where you can download it.

image

IntelliSense!

While you code your queries using LINQ to SharePoint, you will now have access to IntelliSense, which you did not have with CAML queries:
image

I'm going to leave it at that - very (very) easy to get started with LINQ to SharePoint, and all you really need to know is to start using the SPMetal tool to generate your entity classes and hook'em up with Visual Studio to start coding.

Summary & Download

As you can see, there's not a lot of things you need to do in order to work with LINQ in your SharePoint applications with your SharePoint-data.

I've been pinged plenty of times on how you can get started with this, and there you have it. More in-depth articles to come later - this is just to get your wagon rolling!

To download the sample project, click here: [Download]

Enjoy!


Published: Feb-19-10 | 14 Comments | 0 Links to this post

SP 2010: Programmatically work with External Lists (BCS) using the Client Object Model

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

Article 3 in the small BCS-series:

1. SP 2010: Getting started with the Business Connectivity Services (BCS)
2. SP 2010: Programmatically work with External Lists (BCS) in SharePoint 2010
3. SP 2010: Programmatically work with External Lists (BCS) using the Client Object Model

In my previous article in the series, I talked about how easy it is to fetch information using the standard SharePoint server API-approach. In this article I will talk about how you can access data in your BCS data source, by utilizing the Client Object Model.

Client Object Model code to read from the external list

Just like I described in my previous article, you now have the awesome ability to work with data in your External Lists (connected to a data source using BCS) - namely, you can use the standard SharePoint APIs.

Since I've shown you how you can do this using the Server Object Model, I thought I could take another spin at it and show you the code for doing basically the same with the Client Object Model.

The underlying data

As with my previous article, I'm still using the same data source as I set up in my first article - the "ProductList" table in my SQL Server database called "Zimmergren_DB"

As seen in the SQL Server Management Studio:
image

Let's fetch the data using a Windows Forms application that utilizes the Client Object Model!

I've designed a Windows Forms application to utilize the .NET Client Object model (in contrary to using the Silverlight client object model or JavaScript client object model).

It looks like this:
 image

When you click the fancy button called "Get External Data", it will use the Client Object Model to fetch the records from the external list (from the SQL server) and display them in a DataGridView. Nothing fancy.

The code!

With no further delays or chit-chat, here's the simple code!

    // Define the Client Context (as defined in your textbox)
    SP.ClientContext context = new SP.ClientContext(tbSite.Text);
    SP.Web site = context.Web; 

    var ProductList = site.Lists.GetByTitle(tbList.Text); 

    SP.CamlQuery camlQueryAwesomeness = new SP.CamlQuery();  

    IQueryable<SP.ListItem> productItems =
                                      ProductList.GetItems(camlQueryAwesomeness); 

    IEnumerable<SP.ListItem> externalList =
                                      context.LoadQuery(productItems);

    // This is where we actually execute the request against the server!
    context.ExecuteQuery(); 

    // Retrieve the products from the product list using some fancy LINQ
    var productListData = from product in externalList
      select new
      {
          // We're never pointing to the field at the 0-index
          // because it's used by the BDC Identity itself. Hence our elements start at 1.
          ProductID = product.FieldValues.ElementAt(1).Value.ToString(),
          ProductName = product.FieldValues.ElementAt(2).Value.ToString(),
          ProductDescription = product.FieldValues.ElementAt(3).Value.ToString()
      }; 

    // Simply clear the rows and columns of the GridView
    gvProducts.Rows.Clear();
    gvProducts.Columns.Clear(); 

    // Add the columns we need (ProductID, Name, Description)
    gvProducts.Columns.Add("ProductID", "ProductID");
    gvProducts.Columns.Add("Name", "Product Name");
    gvProducts.Columns.Add("Description", "Product Description");
    foreach (var product in productListData)
    {
        // For each product in the list, add a new row to the GridView
        gvProducts.Rows.Add(
                                 product.ProductID,
                                 product.ProductName,
                                 product.ProductDescription
                                 );
    }

References and recommended reading

  1. Getting Started with the Client Object Model in SharePoint 2010
  2. Getting Started with Business Connectivity Services in SharePoint 2010

Summary & Download

At this point, I've showed you three short articles in which I describe how you can set up a Business Connectivity Services data source - then utilize the Server OM or Client OM to fetch information from that external data storage.

Worth to note is that this is still a Beta product, which of course means that it may differ in functionality and performance in comparison with the final (RTM) version of SharePoint 2010.

Download the complete Visual Studio 2010 project here: [ Zimmergren.SP2010.ClientOM.BCS.zip ]


Published: Jan-21-10 | 6 Comments | 0 Links to this post

SP 2010: Programmatically work with External Lists (BCS) in SharePoint 2010

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

Article 2 in the small BCS-series:

1. SP 2010: Getting started with the Business Connectivity Services (BCS)
2. SP 2010: Programmatically work with External Lists (BCS) in SharePoint 2010
3. SP 2010: Programmatically work with External Lists (BCS) using the Client Object Model

In my previous article I talked about how you can set up a simple BCS configuration to fetch and work with external data in SharePoint 2010. In this article I will talk about how you can utilize the SharePoint 2010 object model to work with that external data, directly from the SharePoint API. It's all really simple!

Working with data in an External List using the SharePoint Object Model

The code in this sample doesn't really differ from the way you fetch information from any other list in SharePoint (2007 or 2010). This - of course - is very welcomed news, as we do not need to learn any new frameworks or tools to work with the data in our external lists. It simply works as any other SPList, basically.

Retrieving external data, made simple:

When fetching items from an external list, you can simply do that by utilizing the good-old SPList object. We do not need to work with any other types of namespaces or frameworks in order to do this.

In my SQL Server I've got a table called "ProductList".
This list is filled with the following data:

image

Fetching some items from the external list, and displaying them in a console app:

// Product List is my external list, that is working with data in the SQL Server!
SPList list = web.Lists["Product List"];

SPQuery q = new SPQuery();
q.Query =
    "<Where><IsNotNull><FieldRef Name='ProductID' /></IsNotNull></Where>";
q.RowLimit = 100;

SPListItemCollection col = list.GetItems(q);

foreach (SPListItem item in col)
    Console.WriteLine(item["Name"].ToString());

This will render the following result (fetched from the database):

image

The things you see in the console windows is fetched straight from the SQL Server (using a BCS connection through the External List).

Writing data to the External List (hence, writing to the SQL Server)

Seriously, this is way too easy as well...

// Get the external list
SPList list = web.Lists["Product List"];

// Use the traditional approach to create SPListItems and hook it up with the list
SPListItem item = list.Items.Add();
item["Name"] = "Sample Product Wohoo";
item["Description"] = "Sample Description Wohoo";
item.Update();

Upon running this code in your SharePoint application, it will create the SPListItem object and add a Name and Description. When you hit .Update() it will push this data through the data source connection, to your SQL server.

Here's what the updated data looks like:
image

We're running a Beta-product!

As you can imagine, there's a ton of new cool things to work with in SharePoint 2010 - where the BCS is one. This article discuss the very basics of how you can retrieve information from these lists using the normal API-approach.

At the time of this writing (during Public Beta) there isn't any measures on performance and what impact it has on the server in comparison to alternative ways to fetch and work with the data.

As time goes on, there will be probably be some new information on this - I'll keep you posted when I know more.

Summary

As you can see, working with external data from the SharePoint API isn't very hard to do. What you need to make sure is to have an external list set up somewhere (see this article for how you can do that) and then you can simply use the normal SPList object from the SharePoint object model to work with the external list and it's external data from the SQL server (in my case).

So if you haven't already: Get on the SharePoint 2010 wagon and enjoy the ride!


Published: Jan-19-10 | 7 Comments | 0 Links to this post

SP 2010: Getting started with Business Connectivity Services (BCS) in SharePoint 2010

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

Article 1 in the small BCS-series:

1. SP 2010: Getting started with the Business Connectivity Services (BCS)
2. SP 2010: Programmatically work with External Lists (BCS) in SharePoint 2010
3. SP 2010: Programmatically work with External Lists (BCS) using the Client Object Model

BCS in SharePoint 2010 is an awesome refinement of the Business Data Catalog from MOSS 2007. With BCS - or Business Connectivity Services - you get the possibility to connect external data and work with it from SharePoint.

In this article I will not cover the basics of what BCS is all about (MSDN/TechNet does this very well) - I will rather give you a walkthrough of how you can setup a BCS connection to an external database, and then work with this information directly from a SharePoint list - without the user actually knowing anything about the connection to the database.

BCS Poster: Business Connectivity Services Poster
BCS Team Blog: http://blogs.msdn.com/bcs/

A sample SQL database

I'll just show you how my sample database is set up - simply create a new database in your SQL Server and have it filled with some example data. In my case, this is the data in my SQL database, called Zimmergren_DB:
image

In this sample database, I've added a table called ProductList which in theory will represent some products in this database, like this:
image

I'm filling the database with some sample data, so we will be familiar with this data when we later watch this information from SharePoint:
image

Alright - we have some sample data in our SQL Server. Nothing fancy, just some very simple data. Great, let's get going with the fun stuff!

Creating an external content type

The most effective and easy way to set up a simple BCS connection, is to use SharePoint Designer 2010. You heard me, we can now get up and running with BCS by using SPD instead of modeling complex ADF files and things like that.

In order to do this, we need to create a new External Content Type!

Here's how do create our External Content Type and hook it up with our database, step by step:

  1. Open the site you want to work with using SharePoint Designer 2010
  2. Select "External Content Types" in the left hand navigation:
    image
    Loading this page might take some time, be patient!
  3. Click to create a new External Content Type like this:
    image
  4. Click the link that reads: "Click here to discover external data sources and define operations":
    image
  5. Click "Add Connection"
    image
  6. Select "SQL Server" as your Data Source Type:
    image
  7. Enter the details about your connection to your SQL Server:
    image
  8. When the connection is made, your Data Source Explorer will be filled with the database you have specified. Now choose the table you want to work with, and right-click and select "Create All Operations":
    image 

    You'll be presented with a wizard-like dialog where you can specify the operations, elements and other properties for your BCS connection.
  9. Click "Next" to get to the Parameters page
  10. Select the field that you want to act as an Identifier. In my case I've selected my ProductID just to get on with it:
    image
  11. Click "Finish"
  12. You'll be presented with a list of operations that your External Content Type can do, like this:
    image

That's it. A few points, a few clicks - and you're done. Let's create an external list (using the Browser to show how simple it is..) and hook up our external content type with it!

Creating an external list

There's a few ways to create an external list in SharePoint 2010. We will create it using the Browser UI to show you how simple it can be.

  1. Open your site and choose Site Actions - More Options…
    image
  2. Select the External List template, and click Create
    image
  3. Enter a name for your list, e.g. Product List
  4. You'll see a field in this list called External Content Type, click the browse-button beside it:
    image

    What is really awesome here, is that you're now presented with a dialog where you simply can choose the data source for this list. That means, you'll select the data source you've created (mine is called Zimmergren_DB). Then your list will automatically work against the SQL database, but still have the look and feel of a SharePoint 2010 list.
  5. Select your data source and click OK:
    image
  6. Now simply click the button called Create:
    image

Would you look at that! You're now working with external data, from your (what looks to be) normal SharePoint list! This is brilliant!

You now have the ability to create new items, update existing items, delete items and do all your normal CRUD-operations (CRUD = Create, Read, Update, Delete) straight from the SharePoint 2010 list.

Proof of concept - Adding a new product

Let's just for the fun of it add a new product called "Awesome Product 1.0" like the following screenshot:
image

Now go to your SQL Server and see the changes take effect immediately. The data is NOT stored in SharePoint, it's stored in your SQL Database.

This is what my table now looks like in the SQL Server, after adding a new item in the SharePoint list:
image

Summary

With a few points, followed by a few clicks - you've set up your external data connection. Basically it's that simple.

Of course there's a lot of things to consider when doing these configurations - and you might not want to auto-generate the CRUD-operations, but rather create them one by one and specify more fine-grained permissions etc.

This is merely a sample to show you how easy it is to actually get up and running with the SharePoint 2010 Business Connectivity Services (BCS) and work with external data!

Enjoy


Published: Jan-18-10 | 14 Comments | 0 Links to this post

SP 2010: How To - Relational lists in SharePoint 2010

Author: Tobias Zimmergren
http://www.zimmergren.net | http://www.tozit.com | @zimmergren

Introduction

One of the new cool things in SharePoint 2010 is the fact that we now have relational lists. In my previous article about List Joins, I talked about how you programmatically can fetch and join information from more than one list with the improved SPQuery object.

In this article I will give you an overview of what capabilities you get out of the box when installing SharePoint 2010 - in terms of relational data in lists.

Relational Lists in SharePoint 2010 - Overview

By utilizing Lookup fields in SharePoint 2010, we can enforce a relationship behavior that we previously would have to work very hard to achieve.

Microsoft have now provided us with a few new options when working with Lookup Fields:

  1. Joins between lists
  2. Projected Fields
  3. Relational integrity

Joins between lists

As mentioned, we have the capability to create relationships between lists in SharePoint 2010. This is quite easy to do using the browser UI, which I will soon demonstrate step-by-step.

Projected Fields

With projected fields we have the capability to pull information from a parent list into the view of the child list.

This basically mean that you can reference and display information from a parent list, in your child list. The fields are Read-Only but enables you to get a much nicer joined view.

Relational integrity

With SharePoint 2010 and relations in lists, you would of course wonder how it handles the relational integrity. E.g. what happens if I delete or try to delete something in the parent list?

Well, there's generally two relational integrity options:

  1. Restricted delete
    Basically the restricted delete option enables you to enforce a behavior that means that you can't delete any items that have relations from the list. E.g. if the item you're trying to delete have a bunch of child-items, you cannot delete them.
  2. Cascade delete
    Cascade delete on the other hand, means that when you're trying to delete an item which has relations - it'll delete the related items as well.

Delete and Recover related items - Recycle Bin

A question I got the other day was:

"If I delete an item in my parent list and have cascading delete so all my child items are deleted, how do I restore them if I made a mistake?"

Quite simple my dear Watson, you utilize the recycle bin. When you delete an item using Cascading Delete, the item and it's related items are placed in the Recycle Bin. From there you can obviously easily recover the items as well. This is what an item with relations looks like in the recycle bin:

[PIC]

Step by step - Do it yourself

Alright - so we've covered some of the basics of relational lists, nothing fancy. But now we want to create some lists and have relationships between them - so let's get on with it!

1. Create a parent list

  1. Create a new Custom List named "ParentList"
  2. Create a new Coumn in that list as per the following settings:
    image 
  3. Add some sample items in the list like this:
    image

2. Create a child list

  1. Create a new Custom List named "ChildList"
  2. Create a new Column in that list as per the following settings:
    image
    Please note that I checked the City checkbox. This will create a Projected Field against the lookup automatically so you can view that information which exist in the parent list - directly in the child list.

3. Test out the projected fields functionality

Add some new items in the ChildList to see that when you add an item and choose a company from the ParentList it will automatically show the projected field ("City") as a read-only field in the child-list:
image

4. What about enforcing relational behavior?

I'm glad you asked. When you create (or change settings for) a lookup field (like the "ParentLink" field), you have the ability to change settings for the relational behavior.

Go to your "ParentLink" column, or when you create a new lookup field - and see the following dialog:
image

From this dialog as you can see, you have the ability to make the necessary settings for your fields.

Restricted Delete

If you choose the "Restricted Delete" option, you will see the following behavior when trying to delete an item that has related items:
image 

Cascade Delete

If you choose the "Cascade Delete" option for your lookup field instead, you'll be sending the items directly to the Recycle Bin instead. Then it'll look like this in the recycle bin:
image

Note, that you have the icon that looks like a relational diagram in your recycle bin - this means that you've deleted an item that may have deleted linked items. If you restore this item (in our case, TOZIT) it will automatically restore all of the items that were originally deleted.

So, we have the kind of enforced relationships we've longed for since the dawn of days!

Summary

Voila. Easy as 1-2-3, you have created two very simple lists and created a relationship between them - and optionally you can enforce this relationship using the "Enforce relationship behavior" settings for Restrict Delete or Cascade Delete.

Enjoy!


Published: Jan-05-10 | 19 Comments | 0 Links to this post
 Next >>