Tag Archives: SharePoint

Custom Folder ContentType in Bamboo File Share Library Displays Debug Rendering

In a previous post I wrote about creating a child content type of the BambooFileShareLibrary content type. This was to enable items created in SharePoint via the Bamboo File Share timer job to be set to the custom content type directly and make the additional fields immediately available when users view and edit items.

While following similar steps to make these same fields available when folders were created through the UI, I ran into an unusual problem. The control hierarchy of the page was being written to the output and the text rendered in the browser!

What I Did to Trigger the Problem
To get the functionality I was looking for, I created a new content type based on the Folder (0x0120) content type. I then added the site columns used in the previously mentioned child content type. When the new folder content type was added to the File Share Library, I saw output I wasn’t expecting. I tried the same content type on another document library and it worked as expected.

Continue reading

Extending Bamboo File Share for SharePoint

Recently I started at a new company doing in-house work. The environment is a bit different than that to which I’m accustomed by its large reliance on 3rd party utilities and solutions. While these are great for companies lacking in development staff, many of these solutions are overly generic and can be frustrating to users who are looking for a more integrated experience.

Enter me and my first project.

In my current environment, just as in every other environment I’ve seen, we have users who use and love their file shares. These bastions of untamed digital wilderness have been the bane of many an IT person but their existence continues. To help mitigate some of the drawbacks of these audit-free, backup-less storage areas, Bamboo created a product which synchronizes file share content with a SharePoint document library. The solution uses a timer job to occasionally crawl the share looking for files and folders that have been added/changed and comparing against the files it has in the SharePoint library to see if anything has been deleted. The library is kept in sync (though with the option of archiving deleted items to soften the blow of those occasional accidental share deletes) and each item has a status which reflects the synchronization type.

Continue reading

3 Report Viewer Versions, 1 Web Application

I was debugging a problem with SharePoint 2007 Site Usage reports on a client farm and I finally figured out the problem.

Out of the box, SharePoint 2007 uses Report Viewer controls to render Site Usage reports. These reports target Report Viewer version 8 assemblies which correspond with the Visual Studio 2005 report designer. In the recent past we deployed some reports which were designed in Visual Studio 2010. To support these reports, the SharePoint web.config was modified to use the Report Viewer version 10 assemblies. This worked to get the new reports to render but a few days later it was discovered the Site Usage reports were no longer working.

Continue reading

Pro Tip: Return the same object for WCF service methods

In a previous post I made reference to a consistent return type from my WCF services for Silverlight to consume. Here’s what it is and why I think it’s useful.

WebServiceVoidWrapper
{
    public string ExceptionMessage { get; set; }
    public DateTime LastUpdated { get; set; }
    public bool IsGroupActive { get; set; }
}

WebServiceWrapper<T> : WebServiceVoidWrapper
{
    public T Results { get; set; }
}

Each of our calls, regardless of what they’re returning, need to let the client know about certain conditions. At first we only cared to grab the exception message. Then we added the LastUpdated to be populated when working with data pieces so we could query the server to see if any changes had occurred since. Using the structure above, we could expect all our methods to at least have those members. (The VoidWrapper version is for those times we’re not returning an data from the service but we still want those fields.)

When this was our approach, we had methods scattered in various XAML pages to check for and react to these conditions and this was fine if not anemic since we were short on time and didn’t really implement nice UI interaction to deal with errors.

At some point the business requirements changed and a user could now be part of multiple groups and could be added and removed at any time. We needed a way to react to that. We easily added the field to the base response class and use exception catching on the server side to populate the field. This also meant we were going to need to handle this case all over our Silverlight application because any call could signal the IsGroupActive as false which means the user shouldn’t be able to work with local data they already have.

Rather than peppering checks for this field, popping a child window to prompt the user for a new Organization and then react to the new data we decided to handle this a little more generically. I had constructed a singleton class to act as the interface for the Silverlight application’s communication to the server. Since this singleton is active for the life of the user’s interaction with the application we used this as our starting point.

With this layer in place, we could easily wire up listeners to all our WCF service events and attach a delegate to check for the field and react to it. A quick glance shows 42 methods we’re interested in and these methods grow and shrink and change names constantly during our development cycle. Rather than putting in 42 calls to SomethingCompleted += … I wrote a bit of code to wire up the listener automatically. See previous post for info on that: Dynamically Attach Delegates to WCF Service in Silverlight.

Now with a generic listener in place to catch the user org becoming invalid, we can deal with the UI aspect. Continuing the theme of least-amount-of-code-change we targeted the MainPage object as the best place to handle the interaction with the user. MainPage is available as our Application.Current.RootVisual and can pop child windows and control other UI aspects. It also has access to the NavigationService which we’ll be using as well.

To let the MainPage know the user org has become invalid, I decided to fire a custom event from the service where we detected the error.

[In ConnectionService.cs]
public event EventHandler OnUserOrganizationNotValid;

And subscribe to that event in MainPage.

[In MainPage.xaml.cs]
public MainPage()
{
    InitializeComponent();
    ConnectionService.GetInstance().OnUserOrganizationNotValid +=
        new EventHandler(MainPage_OnUserOrganizationNotValid);
}

void MainPage_OnUserOrganizationNotValid(object sender, EventArgs e)
{
    PopUserOrganizationPicker();
}

From the event delegate we’re calling out to another function. This is because we also have the ability to allow the user to choose a new organization whenever they wish. Rather than have a duplication of code somewhere else, we made a public method that can be accessed from other views.

private OrganizationDialogActive = false;
public void PopUserOrganizationPicker()
{
    if (!OrganizationDialogActive)
    {
        OrganizationDialogActive = true;
        Dispatcher.BeginInvoke(() =>
        {
            OrganizationPicker.InitializeForm();
            OrganizationPicker.Show();
        });
    }
}

void OrganizationDialogClosed(object sender, EventArgs e)
{
    OrganizationDialogActive = false;
    ContentFrame.Refresh();
}

I’m using a property for the org dialog window which wires up the callback event on Closed event. This is nice since the window is late loaded on first use instead of at load time and since nothing really changes, we just keep it in memory.

private SelectOrganizationDialog _OrganizationPickerBackingField;
private SelectOrganizationDialog
{
    get
    {
        if (null == _OrganizationPickerBackingField)
        {
            _OrganizationPickerBackingField =
            new SelectOrganizationDialog(OrganizationDialogClosed);
        }
        return _OrganizationPickerBackingField;
    }
}

To get the user’s screen to update, we could place code to navigate in the MainPage but we’ve stuck it in the org picker child window instead. This is because our service method returns a new URL if the newly chosen org makes the user a power user which will need to send them to a new page. From the service callback in the org picker child window we call a helper method NavigateToPage.

//DefaultPage holds a relative url string for the destination page.
public static void NavigateToPage()
{
    MainPage mp = Application.Current.RootVisual as MainPage;
    Uri defaultUri = new Uri(DefaultPage, UriKind.Relative);

    if (mp.ContentFrame.Source.OriginalString.Equals(DefaultPage))
        mp.ContentFrame.Refresh();
    else
        if (!mp.ContentFrame.Navigate(defaultUri))
            mp.ContentFrame.Refresh();
}

Faleminderit!
-Erik

Creating Silverlight + WCF Apps in SharePoint 2007

I’ve seen people asking how to create WCF services from within SharePoint 2007. It’s actually really easy – much easier than ASMX web services. I could go into a lot of detail but here’s the basic steps:

  1. Create or get a package to modify the SharePoint 2007 web.config to understand WCF URL requests.
    • WCF Service requests start with ‘~’ which SharePoint doesn’t like. You need a custom HTTPModule you can add to SharePoint’s web.config to provide a virtual path provider to strip this character from the request. This is easy to find.
  2. Create a solution that contains your projects.
    • WCF Service Project. You can only target up to .NET 3.5 because SharePoint can’t run in the .NET 4 runtime and if you want your service hosted in SharePoint (to get the nifty SPContext stuff) your service will have to run in the same runtime. See notes below about specific web.config settings.
    • Web Project. This is typically a very simple project and is likely just a simple ASP.NET page with the SharePoint master page instructions and basic layout with the Silverlight app referenced.
    • Silverlight Project. The meat of your application. Create a Web Service reference to your WCF service and watch the magic. Oh, it’s not working? Yeah, there’s a few things you need to do here.

The above is pretty straight forward but won’t work until you sprinkle in some magic.

Decorate your service method with the AspNetCompatibilityRequirementsMode.Required attribute:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

WCF Services can run in an optimized pipeline to speed them up. Unfortunately this means they will run outside the traditional pipeline for ASP.NET applications. Decorating your service method this way forces your service to run in the ASP.NET pipeline. This is necessary in order for IIS to give the request an HTTPContext and for SharePoint to make an SPContext available.

The downside to this is that you can just forget about using polling duplex communication mode. (Well, you don’t have to forget about it but you’re on your own for solving this problem…) Why? Long story short the session state manager locks access on each request. The polling duplex communication works by initiating long-timeout requests to the server. If the server has nothing to say, the request eventually times out and a new request is initiated. This timeout isn’t super long in order to ensure you haven’t lost connection rather than the server has nothing to say but it is long enough to cause a slight problem. When the request is active, all other service calls are queued up because they can’t access the session state! As soon as the polling connection times out, the other requests can try their hand at executing while the polling connection reconnects and starts blocking again.

This is almost never what you want since the biggest advantage to the forced-async programming environment of Silverlight enables highly responsive designs. You could write your own session state handler with different locking mechanisms or tweak the polling timeout at the cost of increasingly talkative connections or you can go the route I prefer: create a heartbeat method using a Timer and firing an event if the service response contains something in which you’re interested. This gives you good granularity for how often your clients should ping the server with not too much more trouble. (It took me less time to roll this in a singleton connection class than it did to figure out how to configure the service endpoints for the polling duplex connection and then debug the queued service requests until I figured out what was happening.)

Configure your endpoints to use NTLM transport. This is to enable the user authentication to be passed over the wire and for SharePoint to treat the connection as if it were a browser user. SharePoint will even return the correct user in the SPContext if you interactively sign in as a different user in SharePoint. You don’t have to maintain separate user account management in your application.

<?xml version="1.0"?>
<configuration>
   <connectionStrings>
      <add name="WRDataConnectionString" connectionString="[...];Integrated Security=True" providerName="System.Data.SqlClient"/>
   </connectionStrings>
   <system.web>
      <compilation debug="false" />
      <customErrors mode="Off"></customErrors>
   </system.web>
   <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <bindings>
         <basicHttpBinding>
            <binding name="customBasicHttpBinding">
               <security mode="TransportCredentialOnly">
                  <transport clientCredentialType="Ntlm" />
               </security>
            </binding>
         </basicHttpBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="AppServiceBehavior" name="App.WCF.Services.AppService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="customBasicHttpBinding" contract="App.WCF.Services.IAppService">
               <identity>
                  <dns value="localhost" />
               </identity>
            </endpoint>
         </service>
      </services>
      <behaviors>
         <serviceBehaviors>
            <behavior name="AppServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
               <serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
               <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
</configuration>

One thing to note in the above is no address in our endpoint. This is because we have to deploy to many environments, all of which use different naming. Instead of specifying a static address, we actually provide the service base address to the Silverlight application as part of its initial startup parameters in its hosting page using SPContext.Current to pass the current web URL. We just concatenate the service name to the end. This makes it much easier to deploy to various SharePoint environments.

If you happen to run SSL you will need to modify your web config to handle this.

<?xml version="1.0"?>
<configuration>
   <connectionStrings>
      <add name="WRDataConnectionString" connectionString="[...];Integrated Security=True" providerName="System.Data.SqlClient"/>
   </connectionStrings>
   <system.web>
      <compilation debug="false" />
      <customErrors mode="Off"></customErrors>
   </system.web>
   <system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <bindings>
         <basicHttpBinding>
            <binding name="customBasicHttpBinding">
               <security mode="Transport">
                  <transport clientCredentialType="Ntlm" />
               </security>
            </binding>
         </basicHttpBinding>
      </bindings>
      <services>
         <service behaviorConfiguration="AppServiceBehavior" name="App.WCF.Services.AppService">
            <endpoint address="" binding="basicHttpBinding" bindingConfiguration="customBasicHttpBinding" contract="App.WCF.Services.IAppService">
               <identity>
                  <dns value="localhost" />
               </identity>
            </endpoint>
         </service>
      </services>
      <behaviors>
         <serviceBehaviors>
            <behavior name="AppServiceBehavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
               <serviceMetadata httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
               <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
</configuration>

Your Silverlight clientconfig will need to match your endpoint to get a successful connection.

With these slight tweaks, creating SharePoint 2007 hostable WCF Services consumable by Silverlight is easy! Use a packager like WSPBuilder and building the deployment WSPs are easy too (just follow the necessary folder structure). For simplicity we deploy to subfolders in the LAYOUTS directory but you can get as creative as you like.

See you space cowboy.
-Erik

Dynamically Attach Delegates to WCF Service in Silverlight

My team has a Silverlight 4 application sitting in an ASPX page hosted from SharePoint 2007 consuming WCF Services targeting .NET 3.5 also hosted from within SharePoint. Using this setup, our service methods can access SPContext. This allows us to leverage SharePoint Groups as a way to assign roles to users to grant or deny them access to data we’re hosting in a custom database.

Through our design, we’ve been using a generic class as the response for all our methods. This lets us have fields for data we want to track during each response (an error message for instance) along with a generic field to hold specific typed data.

As our design progressed we discovered a need to see if a user has been removed from a SharePoint group which would signify their revocation of access to specific data. Rather than wait for the user to attempt access and throw an unfriendly message, we decided to add a field to our generic response wrapper. Now we only need to check this field and pop a picker dialog to let the user pick a new organization based on SharePoint Groups to which they belong.

The problem is we have 42 methods that can return this field. Attaching to all of them with specific callbacks for the different eventargs types that were generated by adding a Service Reference to the service in our Silverlight application would be ugly and a pain to maintain as our methods are added and removed as our application evolves.

Through an earlier design decision, I implemented a singleton instance for the communication to the service: ConnectionService. This seemed like a great place to implement the side-listener. Now I just needed to hook up to each of the methods and listen for the field. I accomplished this via reflection:

ConnectionService() //private constructor in singleton class
{
   …
   EventInfo[] events = WcfClient.GetType().GetEvents();

   events.ParallelForEach((evt) =>
   {
      if (evt.EventHandlerType.IsGenericType && null != evt.EventHandlerType.GetGenericArguments()[0].GetProperty("Result"))
      {
         Delegate handler = Delegate.CreateDelegate(
            evt.EventHandlerType,
            this,
            this.GetType().GetMethod("WcfClient_CheckForInvalidUserOrg", BindingFlags.NonPublic | BindingFlags.Instance));

         evt.AddEventHandler(WcfClient, handler);
      }
   });
   …
}

void WcfClient_CheckForInvalidUserOrg(object sender, AsyncCompletedEventArgs e)
{
   try
   {
      PropertyInfo pi = e.GetType().GetProperty("Result");
      if (null != pi)
      {
         WebServiceVoidWrapper result = pi.GetValue(e, null) as WebServiceVoidWrapper;

         if (null != result)
            if (!result.IsGroupActive)
               HandleUserOrgNotValid(sender, e);
      }
   }
   catch (TargetInvocationException exc)
   {
      Debug.WriteLine(exc.Message);
   }
}

Working backwards a bit you see I created a function to be attached to the events. Since all our WCF Service methods return Silverlight-generated EventArgs inheriting from AsyncCompletedEventArgs. The upside is that we can use one method and not have to much with any of the generated code to insert a different base class. The downside is we don’t have direct access to the field in which we’re interested. The Silverlight generated class contains a field called “Result” which is of the type we’re returning. In our case we’re returning from our service method. We reflect the object, ensure the Result field is present and then try to cast it to the base class of our response wrapper which contains the boolean flag we want. If the flag is false, the user’s org is no longer valid and we pass off to another function to handle it.

Now jumping up to the constructor for the singleton class I have code that will grab all the events contained in our service connection object. This object is what exposes the Async methods to our service methods and the events that are fired when the service calls complete. Then I iterate them. You can use a simple for loop for this but I decided to use an extension method that will execute the statements in parallel and wait for them all to complete before moving forward. Since the service connection exposes a couple built-in events that we don’t care about, we reflect the type to ensure it matches the signature we’re interested in from our callback.

Once we’re sure the event is probably one we’re interested in listening to, we create an event delegate of the type required by the event which is accessed from EventHandlerType. The remainder of the delegate is just grabbing the MethodInfo for our callback function and where it exists. We call AddEventHandler and that’s it!

Now when the singleton class is constructed (and the WcfClient object is connected to our service) we cycle through all the events it exposes and attach our generic handler. If we detect the user org is invalid we fire a custom event. This lets our UI pages listen if they want to react but for our purposes we’re using our Silverlight project’s MainPage to pop up a ChildWindow for the user. We do it this way because we actually have a heartbeat method which pulses the service to see if the user’s report data has changed and if so, pop a refresh message. Since this is done in a separate thread, we can’t interact with the UI directly. Instead we fire an event which is listened to by something already in the VisualTree. Calling Dispather.BeginInvoke() lets us marshal the UI work on the proper thread and show the ChildWindow.

I was pretty sure before I started this design that I could make it work but I didn’t expect it to be so succinct.

Happy Coding!
-Erik