SharePoint 2010: Extending a SharePoint Node in Server Explorer

SharePoint Server Explorer is a new addition to Visual Studio 2010 along with the Visual Studio Tools for SharePoint.

image

It is a very good tool if you want to browse the contents (site columns, content types, features etc.,) of the SharePoint site from Visual Studio. By default, it doesn’t do nothing much than showing what are available in the site.

image

As you can see, the context menu has very fewer items. Below is the Properties pane for the Holds list in the screenshot. The properties are stored in Annotations. To understanding what Annotations are, it is best to consider them as a Class with Properties. Those properties is what you see in the Properties pane below.

image

Again, its read only.

Can I Extend?

So, the next obvious question you would ask yourself (if you are a SharePoint developer) is – Can I extend this and add my own commands or nodes to the SharePoint Server Explorer?

Yes, you can extend the SharePoint Server Explorer to:

1) Create new nodes

2) Extend existing nodes

Give me an example?

Lets take the Features node

image

The Features node displays all the active features in the site. If you right click on a feature, you get very less options

image

How cool would be to add Deactivate option to the context menu and deactivate the selected feature? :)

image

[ By the way, the above screenshot is an actual extension built and not a Photoshop trick :) ]

Understanding the SharePoint Server Explorer

Before you start writing an extension, you should get to know the different types of SharePoint Server Explorer nodes.

image

The node that we are interested in is the FeatureNode.

Getting Started

MSDN has excellent articles explaining how to extend the Visual Studio Tools for SharePoint

Here is a pictorial representation of what we would be doing:

image

 

1. Create a class that implements IExplorerNodeTypeExtension

2. Handle the events

3. Access the properties of that node using Annotations

4. Perform SharePoint operations using Client Object Model

Step 1

Create a Windows Class Library project and add references to

  • Microsoft.VisualStudio.SharePoint

  • Microsoft.VisualStudio.SharePoint.Explorer.Extensions

  • System.ComponentModel.Composition

 

Step 2

Create a class and implement IExplorerNodeTypeExtension:

internal class FeatureNodeExtension : IExplorerNodeTypeExtension
{

}

 

Step 3

As we are interested in adding an item to the context menu, handle the NodeMenuItemsRequested. This is done in the Initialize method:

public void Initialize(IExplorerNodeType nodeType)
{
nodeType.NodeMenuItemsRequested +=
new EventHandler<ExplorerNodeMenuItemsRequestedEventArgs>
(nodeType_NodeMenuItemsRequested);
}

 

And here is the event handler:

void nodeType_NodeMenuItemsRequested(object sender, ExplorerNodeMenuItemsRequestedEventArgs e)
{
IMenuItem deactivateMenu = e.MenuItems.Add("Deactivate");
deactivateMenu.Click +=
new EventHandler<MenuItemEventArgs>(deactivateMenu_Click);
}

We add the new menu item in the event handler above and also handle its own click event.

Step 4

As we want to deactivate a feature, we need to know the Feature Definition Id. They are already available in the Properties pane for a feature:

image

To access the Properties we need to access it via the Annotations object. Here is the code to access the Feature properties:

IFeatureNodeInfo fn = e.Node.Annotations[typeof(IFeatureNodeInfo)] as IFeatureNodeInfo;
definitionId = fn.Id;
featureName = fn.Name;

 

Next thing is to get the site at which this feature is installed. As the Server Explorer has already established the connection to the site, we can get it from its current context.

IExplorerNodeContext siteContext = e.Node.Context;

 

Here is how my event handler looks:

void nodeType_NodeMenuItemsRequested(object sender, ExplorerNodeMenuItemsRequestedEventArgs e)
{
siteContext = e.Node.Context;
IFeatureNodeInfo fn = e.Node.Annotations[typeof(IFeatureNodeInfo)] as IFeatureNodeInfo;
definitionId = fn.Id;
featureName = fn.Name;

IMenuItem deactivateMenu = e.MenuItems.Add("Deactivate");
deactivateMenu.Click += new EventHandler<MenuItemEventArgs>(deactivateMenu_Click);
}

 

Step 5

We can now write code to deactivate the feature in the new menu item’s event handler using the Client Object Model:

void deactivateMenu_Click(object sender, MenuItemEventArgs e)
{
if (MessageBox.Show(confirmationMessage,String.Format("Deactivate {0} feature",featureName),
MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation) == DialogResult.Yes)
{
IExplorerNode parentFeatureNode = e.Owner as IExplorerNode;
IExplorerNode featureNode = parentFeatureNode.ParentNode;

ClientContext clientContext = new ClientContext(siteContext.SiteUrl.AbsoluteUri);
Web site = clientContext.Web;
FeatureCollection siteFeatures = site.Features;

clientContext.Load(site, s => s.Title, s => s.Features);
siteFeatures.Remove(definitionId, false);

clientContext.ExecuteQuery();

clientContext.Dispose();

featureNode.Refresh();
}
}

Very simple indeed. Query and get only the Web and Features object, and then remove (deactivate) the feature from the site.

You can also do this asynchronously using the Asynchronous Pattern for Client OM.

Deploying the Extension

To deploy the extension, we need to include it in a .vsix package.

You can use the VSIX template to create the .vsix package.

image

Include the extension in the manifest file.

image

Chose the content as MEF Component  and select the extensions project as your source.

Build the project to generate the .vsix package and install the package.

‘Deactivate Extension’ for FeaturesNode done

And here is our menu item in the context menu:

image

 

 

When you click on it, you will get a confirmation message:

image

Clicking Yes will deactivate the feature and refresh the Features node.

You can download the source code and VSIX package below:

SharePoint 2010: Asynchronous Query Pattern for Client Object Model

In the SharePoint 2010: Getting Started With Client Object Model blog post, we built a simple SharePoint console application using Client OM. We queried synchronously which is good for simple operations, but you would like to query asynchronously too if you intend to have more queries to the SharePoint server. Below are simple yet easy steps to query asynchronously.

Step 1 – Create a new class for our Asynchronous operations

Create a new class ClientOMAsync

Step 2 – Create a delegate for our Query

public class ClientOMAsync
{
delegate void ExecuteAyncQuery();
}

Add the required variables you want to use

Step 3 – Declare our variables

public class ClientOMAsync
{
delegate void ExecuteAyncQuery();

    Web site;
ClientContext context;
}

Step 4 – Create the Run method

public void Run()
{
context =
new ClientContext(http://<your-site>);
site = context.Web;
context.Load(site, s => s.Title);
ExecuteAyncQuery executeQueryAsync = new ExecuteAyncQuery(context.ExecuteQuery);
executeQueryAsync.BeginInvoke(callback, null);
}
Pretty basic Asynchronous programming model and notice again that we are fetching only the Title property.
Step 5 – Create our Callback method
void callback(IAsyncResult arg)
{
Console.WriteLine("Aync Callback!");


Console.WriteLine("Title before changing: {0}",site.Title);
site.Title = site.Title + " Async";
site.Update();


context.ExecuteQuery();


Console.WriteLine("Title after the change: {0}",site.Title);
Console.WriteLine("Query completed!");
}
Step 6 – Perform the Asynchronous Client OM

Below is the code block that starts this asynchronous query operation from the Main method in the console application

static void Main(string[] args)
{
ClientOMAsync clientOMAsync = new ClientOMAsync();
clientOMAsync.Run();


Console.WriteLine("This is end of the Main program");

Console.Read();
}
And here is our Output:
 
image
 
Below is the full code for ClientOMAsync class:
 
public class ClientOMAsync
{
delegate void ExecuteAyncQuery();

Web site;
ClientContext context;

public void Run()
{
context =
new ClientContext("http://demo2010a");
site = context.Web;
context.Load(site, osite => osite.Title);
ExecuteAyncQuery executeQueryAsync = new ExecuteAyncQuery(context.ExecuteQuery);
executeQueryAsync.BeginInvoke(callback, null);
}

void callback(IAsyncResult arg)
{
Console.WriteLine("Aync Callback!");

Console.WriteLine("Title before changing: {0}",site.Title);
site.Title = site.Title + " Async";
site.Update();

context.ExecuteQuery();

Console.WriteLine("Title after the change: {0}",site.Title);
Console.WriteLine("Query completed!");
}
}

Set Available PageLayouts for your Site

Below is a code snippet for setting available page layouts for your site:

 

List<String> strPageLayoutsToPersist =

        new List<string> { "Home Page", 
                           "General Detail Page", 
                           "Email Me Page", 
                           "Category Page" 
                         };
using (SPWeb spWeb = spSite.RootWeb)
{
        PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(spWeb);
        
        // Get avaialble page layouts for our content types
        PageLayout[] myPageLayouts = pubWeb.GetAvailablePageLayouts().Cast<PageLayout>()
            .Where(p => strPageLayoutsToPersist.Contains(p.AssociatedContentType.Name))
            .ToArray();
 
        // Set the available page layouts to our content type
        pubWeb.SetAvailablePageLayouts(myPageLayouts, false);
 
        // Update the web
        pubWeb.Update();
}

 

This will hide every page layouts except those you specify in the strPageLayoutsToPersist

Highlighting the current page (site) in a custom navigation

When you build your custom navigation menu in SharePoint, highlighting the current page in the navigation menu is one of the various things we like to do. Something like this:

image

You can see how People and Skills Development funding is highlighted and also their parent items – ANZBPF programmes and Australia and New Zealand Biotechnology Partnership Fund

I hope you are using PortalSiteMapProvider to build your custom navigation. Below is a code snippet which gets all the pages in a particular site

PortalSiteMapProvider psmp = PortalSiteMapProvider.CurrentNavSiteMapProvider;
psmp.IncludePages = PortalSiteMapProvider.IncludeOption.Always;
    
SiteMapNode siteMapNode = psmp.FindSiteMapNode(elevatedWeb.ServerRelativeUrl);
List<SiteMapNode> nodes=new List<SiteMapNode>();
 
foreach(SiteMapNode node in siteMapNode.ChildNodes)
{
    nodes.Add(node);
}
 
// now bind the List to repeater or ListView etc.,

Given a SiteMapNode, here is a method which can find whether that particular node is current page

private bool IsCurrentPage(SiteMapNode node)
{
    return node.Url.ToLowerInvariant() == 
             HttpContext.Current.Request.Url.LocalPath.ToLowerInvariant();
}

Now you can easily change the CSS styling for the selected node in your navigation based on whether it is current page or not.

 

 

You can also manipulate the URL and find out whether it is your current site too

Retrieving an Item from the RootWeb and Subwebs using its UniqueId

Sometimes, it is necessary to retrieve an item given its ID (unique identifier). There is always the SPWeb.GetFile(Guid itemGuid) method, but that does not return an item if that item exists in a sub site. The sub site may be a level down or two or ‘n’ levels down.

Using SPWeb.GetSiteData, it is much easier to query for the Item anywhere from your root web.

Below is the code snippet:

SPSiteDataQuery oQuery = new SPSiteDataQuery();
oQuery.Lists = "<Lists BaseType='1'/>";
oQuery.RowLimit = 100;
oQuery.Webs = "<Webs Scope=\"Recursive\" />";
 
queryBuilder.Append("<Where><Eq><FieldRef Name=\"UniqueId\" />");
queryBuilder.Append("<Value Type=\"Lookup\">");
queryBuilder.Append("e5d483ac-1c4a-4699-bcd1-dd0bb0455a71");
queryBuilder.Append("</Value></Eq></Where>");
 
oQuery.Query = queryBuilder.ToString();
 
DataTable dtResult = web.GetSiteData(oQuery);
 
if (dtResult.Rows.Count > 0)
{
    foreach (DataRow row in dtResult.Rows)
    {
        string listId=row[0].ToString();
        string webId=row[1].ToString();
        string itemId = row[2].ToString();
    }
}

 

There is also the SPSite.GetSiteData method if you want to use. If you are planning to use the CrossListQueryCache class, then make sure you read this blog entry!

Using SharePoint Object Model to add entries to web.config

When working with SharePoint projects, sometimes it is necessary to add some entries to the site's web.config. The web.config file is always there in the virtual directories for you to open and edit, but it is a tedious and repetitive process to do the same thing across various environments.

The SharePoint object model has a neat way to add entries to the web.config. This is a much easier and better way to add entries to your web.config.

Below is the code snippet from MSDN:

SPWebService service = SPWebService.ContentService;
 
SPWebConfigModification myModification = new SPWebConfigModification();
myModification.Path = "configuration/SharePoint/SafeControls";
myModification.Name = 
"SafeControl[@Assembly='MyCustomAssembly'][@Namespace='MyCustomNamespace'][@TypeName='*'][@Safe='True']";
myModification.Sequence = 0;
myModification.Owner = "User Name";
myModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
myModification.Value = 
"<SafeControl Assembly='MyCustomAssembly' Namespace='MyCustomNamespace' TypeName='*' Safe='True' />";
service.WebConfigModifications.Add(myModification);
 
/*Call Update and ApplyWebConfigModifications to save changes*/ 
service.Update();
service.ApplyWebConfigModifications();

As you can see, it is pretty simple and if you want to apply to the site rather than the whole farm (as shown in the code):

oWebSite.Site.WebApplication.WebConfigModifications.Add(MyModification)

Using the WebConfigModifications Property it is very easy to add/remove your web.config modifications

How should I approach and use it in my projects?

Given that you now know how to add entries to web.config, what would be the best way to take it forward and use it in your projects?

Here is my suggestion – Create a new feature which will add values to the web.config. In this way it is very easy to maintain. You just activate the feature to add values to the web.config.

Feature Receivers and SPContext.Current and SPFeatureReceiverProperties

Another day, another discovery! – MOSS Rocks! :)

I had to create a List using a Feature. So, I added my code in the FeatureActivated method. The first thing I did was to get the current web (site)

public override void 
FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb CurWeb = SPContext.Current.Web;
// Rest of the code follows....
}

 

I went ahead and installed the feature using stsadm command. It worked fine. I then activated the feature and ended up getting this error!

Object reference not set to an instance of the object

If I remove the code inside the FeatureActivated method, it works! And, If I activate the feature from the web browser, it works!

Googling, I found that you cannot use SPContext.Current inside FeatureActivated when using stsadm (via command prompt) to activate the feature

Why? – Very simple, cmd.exe process does not understand or know how to get your current context! If you are running via browser, you have the w3wp.exe process from which you can get the context!

 

So, is there a way I could get the Web or Site to which the feature is getting deployed? Of course, YES!

Below is an extension method for you! (from here - Matt Smith’s blog, who is now enjoying his vacation!):

public static class Extensions
{
/// <summary>
/// Gets the web.
/// </summary>
/// <param name="properties">The properties.</param>
/// <returns></returns>
public static SPWeb 
GetWeb(this SPFeatureReceiverProperties properties)
{
SPWeb site;
if (properties.Feature.Parent is SPWeb)
{
site = (SPWeb)properties.Feature.Parent;
}
else if (properties.Feature.Parent is SPSite)
{
site = ((SPSite)properties.Feature.Parent).RootWeb;
}
else
{
throw new Exception("Unable to retrieve SPWeb - 
this feature is not Site or Web-scoped.");
}
return site;
}
}

Depending on the scope of your feature, you cast the Parent.

And you use it like this:

public override void 
FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb CurWeb = properties.GetWeb();
Guid listId = CurWeb
.Lists
.Add(ListTitle, ListDescription, SPListTemplateType.GenericList);
CurWeb.Update();
}

Simple way to use LINQ with SharePoint ItemCollections

Here is a simple way to make use of LINQ with SharePoint item collections, for example, with List Items

SPListItemCollection listPages = pagesList.Items;
var latestPages = listPages.Cast<SPListItem>().Where(p => p.Name != defaultPageName);

And this becomes really cool if you use with Dynamic LINQ

var latestPages = listPages.Cast<SPListItem>()
                                .Where(p => p.Name != defaultPageName)
                                .OrderByDescending(p => p[Constants.Modified].ToString())
                                .Take(3);

How cool is that? :)

SharePoint: Customising the EntityEditorWithPicker

I am sure many SharePoint users will be familiar with the EntityEditorWithPicker. Well, if you are wondering what the hell is this EntityEditorWithPicker, below is a screen-shot:

image

Yes, that nice little TextBox portion along with the ‘Check for Names’ and ‘Browse’ button is the EntityEditorWithPicker. Don’t forget that ‘dialog box window’ which comes when you choose to browse ;)

SharePoint being extensible, it is very easy to create your own custom EntityEditorWithPicker. You can implement it such a way that it loads some data from a list and allows the user to select an list item. To do so, you should extend three classes:

Below is a diagram which represents the above:

image

The picker dialog represents that ‘dialog box window’. The results are returned from the simple query control to the picker dialog. The picker dialog is attached to the entity editor so that the entity editor is aware which is that ‘dialog box window’ to open.

Putting the respective classes to their user interface, it becomes:

image   image

Looks easy, isn’t it :)

For code sample, Igor Kozlov has an excellent sample on customising the EntityEditorWithPicker on his blog.

Wouter van Vugt has an advanced sample on creating a CustomField by using EntityEditorWithPicker (You can grab the code sample here)

SharePoint: Creating a custom field

In SharePoint, a site column is a reusable column definition, or template, that you can assign to multiple lists across multiple SharePoint sites. Site columns are associated to a particular Data Type. This Data Type is called a Field. For example, when you create a site column, you are also prompted to select the type of information, which is nothing but a Data Type or a Field.

creating-site-column

Sometimes, it is necessary for us to create our own custom field that does not conform to the field types included in SharePoint by default. Something like this:

custom-field-site-column

How do we do that?

All you have to do is – create a custom field which would result in creating a Field Class, Field Control and Field Type Definitions

image

The Field Class should inherit from any of the SPField classes shown above in the diagram.

The Field Control should have Field Rendering Control and a Field Rendering Template.

The Field Type Definitions is a XML file which contains some information about the custom field.

Custom Field Class - CustomField

Below is a custom field class which inherits SPFieldChoice

public class CustomField : SPFieldChoice
{
    public CustomField(SPFieldCollection fields, string fieldName) :

                                                                    base(fields, fieldName) { }

    public CustomField(SPFieldCollection fields, string typeName, string displayName) :

                                                                    base(fields, typeName, displayName) { }

    public override BaseFieldControl FieldRenderingControl

    {
        get
        {
            BaseFieldControl fieldControl = new CustomFieldControl();
            fieldControl.FieldName = InternalName; return fieldControl;
        }
    }
}

As you can see in the above code, it does nothing but creates a custom field control to render our custom field.

Field Rendering Template – CustomFieldControl.ascx

<SharePoint:RenderingTemplate Id="CustomFieldTemplate" runat="server" >    
    <Template> 
        <asp:CheckBox ID="YesNoCheckBox" runat="server"  Text="Yes/No" />    
    </Template>
</SharePoint:RenderingTemplate>

This is going to render a simple ASP.NET CheckBox

 Field Rendering Control – CustomFieldControl.cs

The name of the field rendering control should be same as the name of the field rendering template(ascx) name and must inherit from BaseFieldControl.

public class CustomFieldControl : BaseFieldControl
{    
#region Member Variables        
protected CheckBox YesNoCheckBox;    
private string _value;    
#endregion    
#region Overridden Methods       
#endregion    
#region Private Methods        
#endregion
}

The basic template(with our example’s member variables) code block is shown above. The member variables are nothing but the controls that we created in the field rendering template.

The field control class can be considered as the code behind for the field rendering template.

To make our custom field work, we first need to render the template and display our checkbox.

#region Overridden Methods
protected override void CreateChildControls()
{    
if (Field == null && this.ControlMode == SPControlMode.Display)    
{   return;  }        
base.CreateChildControls();    
FindDisplayControle();
}
#endregion
#region Private Methods
private void FindDisplayControle()
{    
YesNoCheckBox = (CheckBox)TemplateContainer.
FindControl(DefaultValues.YesNoCheckBoxName);    
if (DisplayLiteral == null || YesNoCheckBox == null)        
throw new ConfigurationErrorsException("Error: Cannot load the controls!");
}
#endregion

The code block finds the checkbox from our template container (field rendering template).

So, how is the value persisted?

We do that ‘magic’ by overriding the Value property

#region Overridden Methods
public override object Value
{    
get
{
EnsureChildControls();
SetValue();
return _value;    
}    
set
{
EnsureChildControls();
_value = value.ToString(); 
LoadCheckBox();
}
}
#endregion
#region Private Methods
private void LoadCheckBox()
{    
if(!string.IsNullOrEmpty(_value))
{ 
YesNoCheckBox.Checked = _value=="Yes";    
}
}
private void SetValue()
{    
_value = YesNoCheckBox.Checked ? "Yes" : "No";
}
#endregion

Looks very simple, isn’t it :)

One last thing to do is to tell SharePoint our default template name and display template name, which is nothing but the name of our field rendering template

#region Overridden Methods
protected override string DefaultTemplateName
{ 
get
{ 
return DefaultValues.RenderingTemplateName;    
}
}
public override string DisplayTemplateName
{ 
get
{
return DefaultValues.RenderingTemplateName;    
}
}
#endregion

Field Type Definitions – fldtypes_<custom-field>.xml

We now need to create a field type definition. The field type definition file is an XML file whose name is prefixed by fldtypes_ followed by a name. It is important that we follow this convention. Our field type definition for our custom field is called as fldtypes_customfield.xml

<fieldtypes>
<FieldType>
<Field Name="TypeName">CustomField</Field>
<Field Name="TypeDisplayName">Custom Field</Field>
<Field Name="TypeShortDescription">Custom field</Field>
<Field Name="ParentType">Note</Field>
<Field Name="FieldTypeClass">Chaks.Samples.SharePoint.CustomField, 
Chaks.Samples, Version=1.0.0.0, 
Culture=neutral, 
PublicKeyToken=****************
</Field>
<Field Name="UserCreatable">TRUE</Field>
</FieldType>
</fieldtypes>

You can read more about custom field type definitions here

 

Deploying

1) Place the .dll into the GAC

2) Copy the fldtypes_customfield.xml into 12hive->TEMPLATE->XML

2) Copy the CustomFieldControl.ascx into 12hive->TEMPLATE->CONTROLTEMPLATES

( It is always recommended to use STSDEV or WspBuilder for SharePoint projects. That makes your deployment (and development) very easy )

You can download the files below:

 

Consuming WCF Service in SharePoint

Today, I had to consume a WCF Service in my SharePoint Feature. I was sure of not using svcutil or Visual Studio 2008's Add Service Reference because that adds extra files that I might need to consider deploying along with my SharePoint solution. So, how do we consume our service ?

Below are the basic steps if you want to create your WCF Client manually via the code:

Put the necessary web.config entries into your SharePoint's application's web.config . A typical example would be:

   1: <system.serviceModel>
   2:     <bindings>
   3:       <wsHttpBinding>
   4:         <binding name="insert-your-binding-configuration">
   5:           <security mode="Message">
   6:             <transport clientCredentialType="Windows" 
   7:                        proxyCredentialType="None" realm="" />
   8:             <message clientCredentialType="Windows" 
   9:                      negotiateServiceCredential="true" 
  10:                      algorithmSuite="Default" 
  11:                      establishSecurityContext="true" />
  12:           </security>
  13:         </binding>
  14:       </wsHttpBinding>
  15:     </bindings>
  16:     <client>
  17:       <endpoint 
  18:         address="insert-your-address" 
  19:         binding="wsHttpBinding" 
  20:         bindingConfiguration="insert-your-binding-configuration" 
  21:         contract="insert-your-contract-description"
  22:         name="insert-your-endpoint-name">        
  23:       </endpoint>
  24:    </client>
  25: </system.serviceModel>
Create a Service Client Channel from your ServiceContract
public interface IMyServiceChannel : IMyService, IClientChannel {}

The IMyService is my service contract

Create a Channel Factory and associate with the endpoint configuration name

ChannelFactory<IMyServiceChannel> channelFactory = 
    new ChannelFactory<IMyServiceChannel>("insert-your-endpoint-name")

With the factory, now we can create our Proxy

IMyServiceChannel proxy = channelFactory.CreateChannel()

You are now ready! Wrap these in a using statement and invoke your service methods using the proxy created above :)

Code Snippets: Upload and Download a file from Sharepoint Document Library

Here are sample code snippets to upload and download a file from Sharepoint Document Library

Upload a File:

   1: public static void UploadDocument(string siteCollectionUrl, 
   2:                             string siteUrl,string libraryName)
   3: {
   4:     using (SPSite hostSite = new SPSite(siteCollectionUrl))
   5:     {
   6:         #region Reading a file
   7:  
   8:         string filename = "C:\\TFS.doc";
   9:         FileInfo fInfo = new FileInfo(filename);
  10:         long numBytes = fInfo.Length;
  11:         FileStream fStream = 
  12:             new FileStream(filename, 
  13:                            FileMode.Open, 
  14:                            FileAccess.Read);
  15:         BinaryReader br = new BinaryReader(fStream);
  16:         byte[] fileBuffer = br.ReadBytes((int)numBytes);
  17:         br.Close();
  18:         fStream.Close();
  19:  
  20:         #endregion
  21:  
  22:         #region Fields
  23:  
  24:         Dictionary<string, string> DocumentFields = 
  25:                           new Dictionary<string, string>();
  26:         DocumentFields.Add("Status", "Received");
  27:  
  28:         #endregion
  29:  
  30:         #region Upload File into the Document Library
  31:  
  32:         using (SPWeb targetWeb = hostSite.OpenWeb(siteUrl))
  33:         {
  34:             DateTime submissionDate = DateTime.Now;
  35:             SPList submissionsList = targetWeb.Lists[libraryName];
  36:             SPFolder folder = submissionsList.RootFolder;
  37:  
  38:             string fileName = "Sample.doc";
  39:  
  40:             SPFile newSubmissionFile = folder.Files.Add(fileName,fileBuffer);
  41:  
  42:             SPListItem submissionItem = newSubmissionFile.Item;
  43:  
  44:             foreach (KeyValuePair<string, string> documentField in DocumentFields)
  45:             {
  46:                 submissionItem[documentField.Key] = documentField.Value;
  47:             }
  48:  
  49:             submissionItem.Update();
  50:         }
  51:  
  52:         #endregion
  53:     }
  54:  
  55:     Console.WriteLine("File Uploaded Successfully!");
  56: }

Download a File:

   1: public static void DownloadDocument(string siteCollectionUrl, 
   2:                     string siteUrl, string libraryName, string fileName)
   3: {
   4:     using (SPSite hostSite = new SPSite(siteCollectionUrl))
   5:     {
   6:         #region Download the File from the Document Library
   7:  
   8:         using (SPWeb targetWeb = hostSite.OpenWeb(siteUrl))
   9:         {
  10:             DateTime submissionDate = DateTime.Now;
  11:             SPList submissionsList = targetWeb.Lists[libraryName];
  12:             SPFolder folder = submissionsList.RootFolder;
  13:             SPFile targetFile=targetWeb.GetFile(folder.Url + "/" + fileName);
  14:  
  15:             if (targetFile.Exists)
  16:             {
  17:                 byte[] fileContents = targetFile.OpenBinary();
  18:  
  19:                 if (!File.Exists(fileName))
  20:                 {
  21:                     File.Create(fileName)
  22:                         .Write(fileContents, 0, 
  23:                                fileContents.Count());
  24:  
  25:                     Console.WriteLine("File saved successfully");
  26:                 }
  27:                 else
  28:                 {
  29:                     Console.WriteLine("File Already Exists");
  30:                 }
  31:             }
  32:         }
  33:  
  34:         #endregion
  35:     }
  36: }

Creative Commons License
Chaks' Corner Blog by Chakkaradeep Chandran is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
Based on a work at www.chakkaradeep.com.
Permissions beyond the scope of this license may be available at http://www.chakkaradeep.com.