Category: SharePoint

Activating Features after Solution Deployment via VS

Visual Studio allow a F5 Deployment. I guess you all know that. The part where you have to think carefully is, when you add Features to your project.

Should you activate “Activate On Default”? Well, it depends (as always). Usually I don’t enable that setting, because features tend to be activated on scopes you won’t expect.

The problem

Take a WebApplication scoped feature for example. It might create SafeControl entries for your controls. Do you really want them to be added to an Extranet WebApplication if your solution is solely for an Intranet Application?

The problem does not exist for you, if you auto activate your features and have set your deployment configuration to “Default”. But in my case, I use “No Activation” and “Activate On Default = false” most of the time. Then, after you deploy an update of your solution, SharePoint retracts and re-adds the solution. The consequence is a deactivate feature 🙂 (in case of Farm and WebApplication scoped features).

My solution

CKS rocks! What’s that have to do with this?

The CKS Extensions for Visual Studio (http://cksdev.codeplex.com/) can Update the solution like you would do via PowerShell or stsadm with a new Deployment option named “Upgrade Solution (CKSDev)”.

image

Unfortunately CKS isn’t available for Visual Studio 2013 preview. So I had to do something else to avoid the problem with non activated features after deployment.

Fortunately Microsoft provided some Command Line action for post-deployment. And since the SharePoint URL is known from the properties of the project, it can be used via variable $(SharePointSiteUrl). Combined with stsadm to activate the feature, I had all I needed.

image

So for now, Deployment from VS will work again 🙂

SPQuery for my tasks

Developing solution with multiple languages (or a language which is not English) sometimes can be a bit painful. To configure a Webpart to display only my tasks, I would filter for [Me] or [Ich].

image

To achieve the same via code / CAML, you can filter by UserID and not the string “Me”.

  1: <Where>
  2:   <Eq>
  3:     <FieldRef Name="AssignedTo" />
  4:     <Value Type="Integer">
  5:       <UserID />
  6:     </Value>
  7:   </Eq>
  8: </Where>
  9: <OrderBy>
 10:   <FieldRef Name="Status" />
 11:   <FieldRef Name="Priority" />
 12: </OrderBy>

This is just a reminder for me, so I can find the information more quickly. But maybe this is useful for some of you as well 🙂

Do long running operations on SPListItem creation

Events on SPListItems like ItemAdding or ItemAdded are nothing new. Many of you have already used them. Recently I had a requirement to create a new SPSite, when an item in a list has been created. So an ItemReceiver was my choice.

But the customer wants something special 🙂 During the creation process, which takes some seconds, the user should see a loading animation.

image

Here comes the problem. The ItemEventReceiver is running in the background, and has no knowledge about the GUI process. Well, at least if it is running asynchronous. A very good explanation can be found here: Using synchronous “after” events (e.g. ItemUpdated) in SharePoint 2010.

The short summary: If you use synchronous events, they get executed in the same thread and you have the HttpContext and SPContext!

You already tried this and didn’t have the context objects?

image

image

Here comes the trick…

image

Grab the objects in the constructor, store them and use later when you need them.

Ok. We’ve successfully redirected to another page in our creation page, which can be a modal dialog or full frame page. I’ve not been able to use the Page to start a SPLongOperation with. A NullReference Exception has been thrown. So my solution was another Layouts-Page, which then starts the SPLongOperation. When it is done, the Layouts-Page is closed. By closing it, the modal dialog from the Item Creation process also vanishes.

I’ve chosen the ItemAdded and not ItemAdding event, because ItemAdding did not like the redirect. The item did not get created.

The Layouts-Page uses SPLongOperation e.g. in CreateChildControls.

After the operation has been executed, the SPLongOperation is ended and a script passed as last parameter in the End() method is executed. You don’t need script tags here.

To register the ItemEventReceiver to execute synchronously, use the following code.

Basically that’s it. A combination of known tasks to create a new solution.

Summary

You can show a work-in-progress dialog to a user, when a new SPListItem is created. Here are the steps:

  1. Use a synchronous asynchronous event 🙂
  2. Redirect to a Layouts-Page
  3. Use the SPLongOperation class to do your work
  4. Have fun and happy customers

CKS – Dev for Visual Studio 2012

The Tools have been released for VS 2012. Great!

The CKS – Development Tools Edition for Visual Studio 2012 is a collection of Visual Studio templates, Server Explorer extensions and tools providing accelerated SharePoint 2010/2013 development based on Microsoft’s SharePoint 2010/2013 development tools.

The current 1.0 release includes the following features:

  • Server Exploration from CKSDev 2010 v2.4 – Visual Studio 2012 version of the Visual Studio 2010 exploration. Includes all the existing server explorer features.
  • Quick Deploy extensions from CKSDev 2010 v2.4 – Visual Studio 2012 version of the Visual Studio 2010 quick deploy. Includes all the existing quick deploy features.

About the Community Kit for SharePoint

The Community Kit for SharePoint is a set of editions, components, tools and recommended documentation for SharePoint development. You are currently viewing the edition project site for the Development Tools Edition. To learn about the other editions and components you can go to http://www.communitykitforsharepoint.org/default.aspx.

You can read more and download the tools here: http://visualstudiogallery.msdn.microsoft.com/cf1225b4-aa83-4282-b4c6-34feec8fc5ec

A CodePlex page also exists: http://cksdev.codeplex.com

Now Available: Office Developer Tools for Visual Studio 2012

Finally! Now Available: Office Developer Tools for Visual Studio 2012

There are some points to mention, where the final release of the tools differ from previous preview releases:

  • validation experience that helps you to find and fix common errors prior to submitting your apps to the Office Store
  • A continuous integration workflow
  • Windows Azure cloud service projects for creating provider-hosted Apps
  • A dramatically improved Workflow designer

The download link: http://aka.ms/OfficeDevToolsForVS2012

SharePoint Konferenz im März, ich bin dabei

SharePoint konferenz - Alles zu MOSS 2007 und Microsoft SharePoint 2010!

Im März ist wieder SharePoint Konferenz Termin. Ich werden mit zwei Vorträgen dabei sein.

 

 

SharePoint 2013 und Social. Was ist neu, was kann man machen?

Enterprise-Lösungen mit Business Connectivity Services

Nach der BASTA 2012, BASTA Spring 2012, BASTA 2011, BASTA 2010, BASTA 2009 und den SharePoint Konferenzen 2010, 2009 ist das mein 7. Auftritt als Speaker.

Cool. Es macht ja auch jedes mal aufs Neue Spaß 🙂

Using .NET 4 with SharePoint 2013

A while ago, I wrote an article about performing operations parallel with SharePoint 2010 (.NET 3.5). –> Execute code in multiple threads (even with SharePoint)

Since I am not the only guy with this kind of “problems”, others are writing about SharePoint and .NET. Especially .NET 4.5 and SharePoint 2013.

Stephane Eyskens hat posted a nice 6-post series about .NET within SharePoint 2013.

If you stumble across more great resources, please leave a comment.

Getting an “Object reference not set to an instance of an object” when accessing the User Profile Service via Code

This is one of the posts which shall remind me about something. And may help others as well.

Coding against the User "Profile Service Application requires Connection Permissions for the executing user account!

From the beginning. I wrote a console application which leverages the User Profile Store. Every time I created a new instance of the UserProfileConfigManager class, an exception was thrown:

Object reference not set to an instance of an object

at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_ApplicationProperties()
at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_ILMMachineName()
at Microsoft.Office.Server.UserProfiles.UserProfileConfigManager.Initialize(UserProfileApplicationProxy userProfileApplicationProxy, Guid partitionID)
at Microsoft.Office.Server.UserProfiles.UserProfileConfigManager..ctor(SPServiceContext serviceContext)
at ITaCS.UserProfileManager.GetUserProfileServer() in D:\Data\Development\tfs02\ITaCS\Components\UserProfileProperties\UserProfileProperties\UserProfileManager.cs:line 49
asf

Fiddling with Reflector and creating the object with Reflection didn’t help. The solution was much easier. Just grant the executing account, which was my user who executes the console application, Connection Permissions to the User Profile Store Service Application (UPS).

image

image

That’s it.

One other thing. If you are running your SharePoint with local accounts, you might not be able to verify a domain account. In that case, you can tell the people picker to use a domain account instead of the service account (which is a local account and does not have permissions in the active directory). See Configure People Picker (SharePoint Server 2010) and  Multi Forest/Cross Forest People Picker peoplepicker-searchadcustomquery.

What is the _layouts/15/start.aspx in SharePoint 2013

SharePoint 2013 immediately redirects you to an application page start.aspx when you call a website.

If you’ve ever wondered why, keep on reading…image

image

The pictures will also look familiar to you. So what happened? Why the start.aspx?

The start.aspx inherits Microsoft.SharePoint.ApplicationPages.MDSStartPage. That page simply looks, if the SPContext.Current.Site.CompatibilityLevel is above 14. If not, it’ll redirect to web.Url. That is the behavior, we know from previous versions of SharePoint.

Additionally it adds some caching information to the Response, and loads a JavaScript called… start.js. That file contains a method $_global_start, which is executed after the file has been loaded. There are some steps the JavaScript executes. Next I’ll try to tell you what the most important steps are.

The arrow basically shows what happens if a user requests a page, where the new logic has been implemented.

image

Next, I will write a little bit about each step. Don’t expect an in-deep explanation. This is just an overview to satisfy the first curiosity.

The Start.js

Show “Working on it…” either full-size for a newly called page, or a smaller one on the right side

But who calls the script? The answer is: the mighty masterpage.

The script does some magic to the Url. I’ll check for updates, which have to be loaded an passed to the client and modify the Url (inserts _layouts/15/start.aspx). If you want to take a closer look on what the script does, set a Breakpoint with e.g. Firebug on the line “function AsyncDeltaManager$_navigate(url, anchorName, bUpdatehash) {“ and reload a page.

The v5.master

SharePoint 2013 brings a new masterpage, which is called v5.master. That masterpage contains a control of type StartScript.

<SharePoint:StartScript runat="server" />

The TagPrefix SharePoint reflects the namespace Microsoft.SharePoint.WebControls. So lets look into the class.

The StartScript WebControl

If the current Page is of type DeltaPage, the class adds some JavaScript to the Page.

To shorten up here as well: If there is a hash in the Url (#), the script will tell the AsyncDeltaManager (from start.js) to hook up to the submit event and tell it where it needs to redirect in case of a postback.

That’s basically all the WebControl is doing.

The DeltaPage

The DeltaPage inherits System.Web.UI.Page. It decides, whether to render the full page, or just a delta. This is called the “Minimal Download Strategy”. There are already some interesting posts about this available. SharePoint 2013 – Introduction to the Minimal Download Strategy (MDS) or Minimal Download Strategy in SharePoint 2013

protected override void Render(HtmlTextWriter writer)
{
    if (this.RenderDelta)
    {
        this.RenderForRenderDelta(writer);
    }
    else
    {
        this.RenderToBase(writer);
    }
}

RenderDelta will look if the current page is the StartPage (that means there is no Page on which to depend)  or if SPContext.Current.Web.EnableMinimalDownload has not been enabled. RenderForRenderDelta add “pageStartRedirect” to the response. I won’t go into the details of this, because I simply haven’t looked into it deep enough for a blog post.

Summary

This image should visualize the steps.

image

Please keep in mind, that this post is written with a research on SharePoint 2013 preview!

There are plenty more features which I’d like to take a deeper look into. Let’s hope I find the time to do so 🙂

Start / Stop SharePoint Services via PowerShell

If you have installed SharePoint on your workstation, you might want to start the services only in case of active development. Otherwise the services consume memory and other resources.

The PowerShell script in this post will allow you to easily start and stop all required services for a local SharePoint Installation.

image

It will detect if you’ve installed SharePoint 2007/WSS, SharePoint 2010 or SharePoint 2013. Just copy the code below to a file, name it StartStopSharePoint.ps1 (yes, very creative :-)) and call it from a PowerShell (you don’t need the SharePoint Management PowerShell).

$SharePointV3Services = ('SQLSERVERAGENT','MSSQLSERVER','W3SVC','SPWriter','SPTrace','SPTimerV3','SPAdmin','OSearch','DCLoadBalancer','DCLauncher')
$SharePointV4Services = ('SQLSERVERAGENT','MSSQLSERVER','W3SVC','SPSearch4','OSearch14','SPWriterV4','SPUserCodeV4','SPTraceV4','SPTimerV4','SPAdminV4','FIMSynchronizationService','FIMService','DCLoadBalancer14','DCLauncher14')
$SharePointV15Services = ('SQLSERVERAGENT','MSSQLSERVER','W3SVC','SPSearchHostController','OSearch15','SPWriterV4','SPUserCodeV4','SPTraceV4','SPTimerV4','SPAdminV4','FIMSynchronizationService','FIMService','DCLoadBalancer15','DCLauncher15')

$Services = $SharePointV3Services
$version = 12
# check for SharePoint 2010
$hive = get-ItemProperty "hklm:\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0"
if ($hive -eq $null)
{
    if ((get-ItemProperty "hklm:\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\15.0" SharePoint).SharePoint -eq 'Installed')
    {
        $version = 15
        $Services = $SharePointV15Services
    }
}
else
{
    if ((get-ItemProperty "hklm:\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0" SharePoint).SharePoint -eq 'Installed')
    {
        $version = 14
        $Services = $SharePointV4Services
    }
}

Write-Host -ForegroundColor Green 'SharePoint Version' $version 'found'
Write-Host -ForegroundColor Yellow 'Press'
Write-Host -ForegroundColor Green '1' -NoNewline
Write-Host -ForegroundColor Yellow ' to start SharePoint Services'
Write-Host -ForegroundColor Green '2' -NoNewline
Write-Host -ForegroundColor Yellow ' to stop SharePoint Services'
Write ''

function StartSharePoint($Services)
{
    Write-Host -ForegroundColor Yellow ('Starting ' + $Services.Length + ' services')
    foreach ($serviceName in $Services)
    {
        $service = Get-Service $serviceName -ErrorAction SilentlyContinue 
        if ($service)
        {
            $startMode = (get-wmiobject win32_service | where-object {$_.Name -eq $serviceName}).StartMode
            if (($service.Status -ne 'Running') -and ($startMode -ne 'Disabled'))
            {
                Write-Host -ForegroundColor Green ('Starting "' + $service.DisplayName + '"')
                Start-Service $serviceName
            }
        }
        else
        {
            Write-Host -ForegroundColor Red ('Service "' + $serviceName + '" does not exist')
        }
    }
}

function StopSharePoint($Services)
{
    Write-Host -ForegroundColor Yellow ('Stopping ' + $Services.Length + ' services')
    for($i = ($Services.Length - 1); $i -gt -1; $i--)
    {
        $serviceName = $Services[$i]

        $service = Get-Service $serviceName -ErrorAction SilentlyContinue 
        if ($service)
        {
            $startMode = (get-wmiobject win32_service | where-object {$_.Name -eq $serviceName}).StartMode
            if ($service.Status -ne 'Stopped')
            {
                Write-Host -ForegroundColor Green ('Stopping "' + $service.DisplayName +'"')
                Stop-Service $serviceName -force
            }
            else
            {
                Write-Host -ForegroundColor Green ('"' + $service.DisplayName + '" is already stopped')
            }
        }
        else
        {
            Write-Host -ForegroundColor Red ('Service "' + $serviceName + '" does not exist')
        }
    }
}

function UserInput($strMsg, $intStyle)
{
  #$strMsg: Message displayed on the console sreen
  #$intStyle: User Input Style:
    #1 = Read-Host (Multiple characters, require to press Enter);
    #2 = $host.ui.rawui.readkey() (Single character, do not require to press enter)
  switch($intStyle)
  {
    1 { $strInput = Read-Host $strMsg ; $host.ui.rawui.foregroundcolor = $Global:fgColor ; return $strInput }
    2 { Write-Host $strMsg; $strInput = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown"); return $strInput}
  }
}

$userInput = UserInput "Enter Choice" 2
switch ($userInput.VirtualKeyCode)
{
    49 { StartSharePoint($Services) }
    50 { StopSharePoint($Services) }
    default { Write-Host -ForegroundColor Red 'Press "1" or "2"' }
}

Hint: In case you haven’t set the Script-Execution-Policy yet, you will be prompted to do so. –> Using the Set-ExecutionPolicy Cmdlet

Happy Coding!

BrandMySharePoint.de

Soeben ist ein neues Community-Portal online gegangen. Auf diesem Portal bin auch ich als Autor für Artikel vertreten. Mehr Werbung möchte ich jetzt erst einmal nicht machen 🙂 Schaut es euch einfach mal an.

www.brandmysharepoint.de

Was erwartet Euch auf diesem Portal?

Wir starten zunächst mit zwei Rubriken: Artikel und Shots. Die Artikel befassen sich mit allen möglichen Themen rund um das Design. Dabei werden nicht nur die klassischen (Web-)Designer angesprochen, sondern auch Entwickler, IT-Pros oder einfach nur „SharePoint-Interessierte“. Zu finden werden sein Codebeispiele, Anleitungen, Screenshots oder Erfahrungsberichte aus unterschiedlichen Projekten.

Die Shots veranschaulichen, welche Möglichkeiten und Ansätze es gibt, die SharePoint-Oberflächen zu gestalten, anzupassen oder grafisch komplett „umzubiegen“. Hier veröffentlichen wir regelmäßig Screenshots von diversen SharePoint-Portalen, möchten Euch aber vor allem einladen, eigene Beispiele beizusteuern.

Für die Zukunft haben wir noch mehr geplant…

Caching objects with HttpRuntime

I won’t go into the arguments for using a caching mechanism or not. This post is simply an example for an easy way to cache data.

So if you want to store some object in the cache, you can do so very easy.

var localizedString = Caching.EnsureObject(resourceName,
                                           () => GetOperation(parameter));

As you can see, it really doesn’t matter what type of object the cache will store.

class Caching
{
   private static readonly TimeSpan Duration = new TimeSpan(1, 0, 0);

   /// <summary>
   /// return cached value, or add and return from cache
   /// </summary>
   /// <typeparam name="T"></typeparam>
   /// <param name="cacheKey"></param>
   /// <param name="getObject"></param>
   /// <returns></returns>
   internal static T EnsureObject<T>(string cacheKey, Func<T> getObject)
   {
      var value = HttpRuntime.Cache[cacheKey];
      if (value != null)
      {
         return (T) value;
      }

      value = getObject.Invoke();

      if (value != null)
      {
         var expiration = DateTime.UtcNow.Add(Duration);
         HttpRuntime.Cache.Insert(cacheKey, value, null, expiration, Cache.NoSlidingExpiration);
      }
      return (T) value;
   }

Adjust the duration, or pass it as parameter. Additionally you could pass another delegate for Exception-Handling. This example is meant as a reminder to think about caching again…

Error in SharePoint Search

I’ve had the error message “The SharePoint item being crawled returned an error when requesting data from the web service.   (0x80042616)” when I tried to crawl a SharePoint WebApplication. The search crawler account had access to a site by a WebApplication policy. But somehow, that didn’t work.

After removing and re-adding the account policy on the WebApplication, the search crawled my content again.

Hopefully this post can help others as well.

Execute code in multiple threads (even with SharePoint)

Since SharePoint 2010 uses .NET 3.5, you can not use the fancy new functions from .NET 4 🙂

So if we need e.g. multi-threaded execution of code, we’ll need to write the code ourselves. But, as you can see, this really isn’t so hard. The basic idea behind this solution of executing code parallel in threads, is that you have an IEnumerable<T> of some kind. This can be a List, or any other IEnumerable.

So let us for example take a list of Guids, which are the IDs of all SPWebs in a SiteCollection. Then we are iterating each web, and write the itemCount of all lists to the Console.

class ParallelExecutionTest
{
   private static int _overallItemCount;
   private static readonly object Lock = new object();

   public static void AddItemCount(int itemCount)
   {
      lock (Lock)
      {
         // only let one thread write to the setter 
         _overallItemCount += itemCount;
      }
   }

   public static void CountListitemsInAllWebs(string siteUrl)
   {
      using (var site = new SPSite(siteUrl))
      {
         // perform the method/action on any web in the sitecollection 
         site.AllWebs.Select(w => w.ID).EachParallel(webId =>
         {
            CountListitems(site.ID, webId);
         }, Environment.ProcessorCount);
         Console.WriteLine("Overall Itemcount: " + _overallItemCount);
      }
   }

   private static void CountListitems(Guid siteId, Guid webId)
   {
      // use new instances for each web 
      using (var site = new SPSite(siteId))
      using (var web = site.OpenWeb(webId))
      {
         var itemCount = web.Lists.Cast<SPList>().Sum(list => list.ItemCount);
         Console.WriteLine("Web {0} has {1} items in all lists.", web.Title, itemCount);
         AddItemCount(itemCount);
      }
   }
}

That doesn’t look too complicated, does it? The little method EachParallel is all it takes for running the code in multiple threads. You have to decide if your code can run parallel, and if makes sense!

Note: Remember that SharePoint will most likely not work, if you access the same objects in multiple threads. So to be safe, create new instances of SharePoint objects in each Thread!

The sample above will create as much threads, as your system has CPUs. On my notebook with i7 and HyperThreading in 8 threads. And here comes the point to remember. Think carefully about the pitfalls on running your code parallel. Here are some drawbacks, compared to the sequentiell execution:

  • Overhead for creating new SharePoint objects (calls to the SQL server)
  • Additional load on the SQL server by querying more data simultaneously (think about a 4 processor server board with x cores and HyperThreading)
  • Possibly more load on the local SharePoint server by writing logfiles
  • Exception handling. With sequential code you can abort. Multiple threads keep running

Enough for now. Lets look at the Extension method which makes all this possible.

public static class Extensions
{
   /// <summary> 
   /// Enumerates through each item and start the action in a new thread 
   /// </summary> 
   /// <typeparam name="T"></typeparam> 
   /// <param name="enumerable"></param> 
   /// <param name="action"></param> 
   /// <param name="maxHandles">e.g. Environment.ProcessorCount</param> 
   public static void EachParallel<T>(this IEnumerable<T> enumerable, Action<T> action, int maxHandles)
   {
      // enumerate the passed IEnumerable so it can't change during execution 
      var itemArray = enumerable.ToArray();
      var count = itemArray.Length;

      if (count == 0) return;
      if (count == 1)
      {
         // if there's only one element, just execute 
         action(itemArray.First());
      }
      else
      {
         // maxHandles must not be greatet than the count of actions, or nothing will be done 
         if (maxHandles > count) maxHandles = count;
         var resetEvents = new ManualResetEvent[maxHandles];

         for (var offset = 0; offset <= count / maxHandles; offset++)
         {
            EachAction(action, maxHandles, itemArray, offset, resetEvents);
            // Wait for all threads to execute 
            WaitHandle.WaitAll(resetEvents);
         }
      }
   }

   private static void EachAction<T>(Action<T> action, int maxHandles, IEnumerable<T> itemArray, int offset, ManualResetEvent[] resetEvents)
   {
      int i = 0;
      foreach (var item in itemArray.Skip(offset * maxHandles).Take(maxHandles))
      {
         resetEvents[i] = new ManualResetEvent(false);

         ThreadPool.QueueUserWorkItem(data =>
         {
            var index = (int)((object[])data)[0];
            try
            {
               // Execute the method and pass in the enumerated item 
               action((T)((object[])data)[1]);
            }
            catch (Exception ex)
            {
               // Exception handling 
               Console.WriteLine(ex.ToString());
            }

            // Tell the calling thread that we're done 
            resetEvents[index].Set();
         }, new object[] { i, item });
         i++;
      }
   }
}

All items in the IEnumerable are iterated. If there is free slot, the action will be executed in a new thread. There is no guarantee, that the code is executed in the same order, as the items in your IEnumerable. Here is an examples of IDs in an array, and the execution order:

Order in ListExecution order
03
16
27
31
44
50
62
75

Summary: Depending on your code, and its requirements, multiple threads can be a good way to improve the speed of you code. It even can be a life-saver (thx Christopher!) for very long running operations. Take your time to think about it, before you implement the “little” change to your code to run in multiple threads!

One last word. I mentioned .NET 4 at the beginning. Here is a sample.

var ids = new List<int> { 0, 1, 2, 3, 4, 5 }; 
ids.AsParallel().ForAll(id => { Console.WriteLine("Id: " + id); });

Nice, ain’t it?

Major Update to the Fileserveraccess Web Part

In 2008 I’ve released a Web Part, which enables your users to access files on your fileservers through SharePoint. Original post. This Web Part has been downloaded many times. With this new version, I’ve tried to deal with the most asked questions (like Kerberos), which will make the Web Part easier to use. Naturally new features have been implemented, to get you to upgrade to the new version.

With this release, the Web Part requires SharePoint Foundation / Server 2010. For the users who are still using WSS V3, please stick to the old version, or upgrade your farm 🙂

First some screenshots, so you know what I am talking about.

image

imageimage

Features

  • Download files from your fileservers via SharePoint
  • Download a folder with all containing files as zip-file
  • Upload files to a fileserver
  • Delete files from a fileserver
  • View the file properties
  • By default, the fileserver path has to be UNC. Local paths are not allowed, so a user cannot enter C:\ to access e.g. the web.config or other files on the local server
  • Multilanguage

Of coarse the access to the files is security trimmed. Meaning that if your users would not be able to access files with their logon from their client, they won’t be able from the Web Part!

Requirements

For authorization against the fileserver, the credentials of the currently logged on user is used. For SharePoint (and any other application as well), it is necessary to configure the WebApplication which is hosting the Web Part to use Kerberos instead of NTLM. Otherwise a server cannot pass the user credentials forward to a second server. This is called the “Double-Hop problem”. To get a glimpse about the topic, take a look at an article I wrote some time ago. Configuring Kerberos for SharePoint. That post has been written for SharePoint V3! But thereimage are plenty of Kerberos Guides out there for SP 2010. And a whitepaper from Microsoft: Configuring Kerberos Authentication for SharePoint 2010 Products http://technet.microsoft.com/en-us/library/ff829837.aspx

If you do not configure Kerberos for the WebApplication, the Web Part will detect that, and show a notification in the properties section.

A small sidenote: If you are going to use local paths (meaning a folder on your SharePoint server), you can continue using NTLM. 

Another good starting point for Kerberos-Troubleshooting can be found here: http://blogs.msdn.com/b/friis/archive/2009/12/31/things-to-check-when-kerberos-authentication-fails-using-iis-ie.aspx

Configuration

image

To use the WebPart, you’ll need to at least configure a path. Files – and subfolders – from that path will be shown.

Additionally, there are some properties, which modify features of the Web Part.

The Paging size defines, how many files are displayed on one page. With the next three checkboxes, you can allow files to be downloaded as zip, allow files to be uploaded and to be deleted.

I recommend to leave the caching activated. Deactivate only, if you have specific reasons, because there will be more todo for your SharePoint server and fileserver.

Using a local path as source

In case you want to use a local path as source for the Web Part, you have to allow the path to be used. To do so, follow the steps below.

  1. locate the feature.xml file ("C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\FEATURES\FileserverAccess\Feature.xml")
  2. Edit the file in your favorite editor
  3. Look for the property with the key “AllowLocalPaths” and modify the value to correspond to the driveletter you wish to use
    image
    Replace “Driveletter” with e.g. “C”. You can specify more than one drive letters. In that case use a “;” as divider
  4. Save the feature.xml
  5. Restart your IIS (iisreset)

Remember that you’ll need to modify the file on all of your FrontEnd SharePoint Servers! After an upgrade of the Web Part, the file has to be modified again. If you do not allow local drives, the Web Part will show an error.

image

This version is compatible to the old version. So you can simply upgrade the solution and benefit of the new features!

Download the new version for SharePoint 2010 (Foundation and Server): RH.FileserverAccess.wsp

Download the old version for WSS V3 / MOSS 2007: RH.FileserverAccess.wsp

Update March 2012

  • I did not get the Web Part working in my claims based authentication test-environment. Additionally, the Web Part properties will show the current user and authentication method. If you see Negotiate, your environment is set up correctly (for classic authentication).

imageimage

  • Another small update, which prevented the upload from working in Chrome

Update: WarmupScript

A long time ago, I posted a program which will hit all your sites. With parameters you can specify to hit all sites within a sitecollection.

image

This program has been updated. You can not omit a start Url, and specify “Farm” as parameter. This way, all sites in all sitecollections in all webapplications in all… 🙂 will be warmed up.

The warmup will use a HttpRequest to query all homepages. It will not hit every page in the pages libraries, but hitting each web is sufficient for most scenarios.

One thing to mention. If you want to warmup your Central Administration, you’ll have to call the program with the Url, as the CA will not be included in the webapplication enumeration of a SharePoint farm.

Usage:

WarmupSharePoint http://your.server.url [AllSites] – will hit one site only, unless the AllSites parameter is specified. Then all sites will be dealed with.

WarmupSharePoint Farm – iterates through all sitecollections and hit all sites within

Download the program
Download the sourcecode

What to know about the feature folder

One of the first things I used to tell guys new to SharePoint development is: Never ever name the folder of your feature “Feature1”. If you create a solution with WSPBuilder, or did some time ago with VS 2008, you have to rename the folders immediately!

image

This is how a typical SharePoint project looks like, if you create features. I guess most of us have used the mighty WSPBuilder (http://wspbuilder.codeplex.com) for developing with SharePoint.image

After building the VS solution and creating a WSP package with WSPBuilder, the wsp contains two folders. They reflect the names, we defined in VS.

 

 

Now lets take a look at the same features in a Visual Studio 2010 SharePoint Solution.

image

It almost looks the same as a WSPBuilder solution in VS 2008.

The features have been created by right-clicking on the Features folder in the Solution Explorer. This is important.

In many places VS uses tokens to replace strings with certain solution specific values like the assembly name. You can take a look at the tokens here: Replaceable Parameters

If we look at the wsp again, we notice the difference. Visual Studio 2010 hasimage added the solution name as prefix to the feature folders. Great. Thank you Microsoft. Now we can name our feature folders e.g. after the scope. (Site, Web, Webapplication of Farm), and do not have to worry about duplicate names.

The magic of this can be seen, if we take a look at the properties of the feature folders.

image

Conclusion: VS 2010 is a great improvement to us SharePoint developers. We don’t have to know all the places where it helps, but it can’t hurt, either. I hope this article brings a little light to the magic 🙂

Use Powershell ISE for SharePoint 2010

To be able to use the ISE for SharePoint, you can configure it to load the SharePoint cmdlets automatically.

Scot Hillier wrote a great article about it. Read “Setting up PowerShell ISE for SharePoint 2010”.

If you only want to use the SharePoint cmdlets once, you can register them with this two lines:

If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null )
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell }