November 2008 - Posts
One of the most popular project types we see with clients is automating a manual process using SharePoint, in order to streamline a Line-of-Business operation. Typically, this starts out with a pain point that surfaces, where people have become fed up with a particular inefficiency and start figuring out what that problem is costing them. To illustrate this use, I’ll share a recent client example, where a financial services company had distributed sales agents who were independent contractors. These agents typically needed to be licensed or certified in order to sell products or deliver services for the company. The compliance department was “pained” by the time-intensive manual – and error-prone – processes of tracking which contractors in the network were currently licensed or needed license renewals, maintaining documentation on licenses, and providing audit support..
While a national company, the enterprise still faxed documents around to facilitate these processes, and the faxes needed to be filed and maintained for each subcontractor. Over time, this became costly, as an increasingly large amount of people, paper, processes, and places (storage) were allocated to this effort. Finally, a department head asked an employee to detail the hard and soft costs, as well as corporate sustainability factors associated with the processes. They included:
- Resources dedicated to managing the process, with full benefits and infrastructure overhead
- Cost of agents’ time to maintain compliance
- Storage of paper
- Retrieval of paper for audits
- Failure rate on audits and cost-per-incident
- Transmission costs - fax lines, hardware, and consumables
- Volume of paper waste contributing to the company’s overall carbon footprint
After an initial assessment, the compliance department understood the current processes to ensure current sales agent certification were screaming to be automated and optimized, and SharePoint – which the company was already using for other document management systems - was a great (simple) tool to handle the automation. With its built-in capabilities for workflow, approval loops, and document management, SharePoint jump-started the project and cut the development time by 75% over conventional “from-scratch” application development. The solution was implemented and deployed in a matter of a few months. Using the new process, the client now sees more green from:
- Personnel freed up for revenue-generating activities
- Eliminated paper usage and consumables in the printing process (going green!)
- Reduced storage and retrieval costs
- Increased audit success rates, reducing costs associated with failed audits
The project paid for itself in the same calendar year and will continue to work saving thousands every month. This sort of cost recovery project is a popular strategy in today’s business climate. Smart organizations are making strategic investments in technology where it can help them trim costs dramatically, and push more money to the bottom line every month. Almost every company has a challenge in some area of document management, from Human Resources to Sales to Operations. Using technologies such as SharePoint can help move these manual processes and forms online, for easier completion, retention, retrieval, and management.
I wanted to drop a last note and stay thanks to everyone who attended the show. I met some great people and talked a lot about SharePoint and associated technologies. It was fun to see what other people are doing with the platform and how they are using certain extensible pieces of SharePoint.
I particularly enjoyed the sessions from Erik Mau on some of the more advanced options for managing Enterprise Search in SharePoint. These were very informative and I will certainly find them useful in my SharePoint travels.
Thanks again,
-Ryan
At the Dev Connections conference, Doug Seven gave a great presentation on Visual Studio Team System (VSTS) and Team Foundation Server (TFS). He started by discussing Agile development and the Agile Manifesto (see http://agilemanifesto.org/) and then highlighted how VSTS and TFS can be used to facilitate Agile development. What was nice to see was how different types of users, project planners, developers etc, can use different tools, Excel and VSTS, to view and edit the same data, allowing them to both work in a comfortable environment. He also showed how easily continuous integration and builds can be setup in a few mouse clicks.
Following on from this Doug gave us a glimpse of VSTS 2010 AKA Rosario. There are a couple of minor changes that facilitate Test Driven Development (TDD), For example in VS2008 you need to create a class and method before you can create a Unit Test - this goes against the TDD "rules" in that you are supposed to write the test first which makes you write the code. In VS2010 - you can now create the Unit Test first and then Right Click to create a class and method stub.
Another nice feature, so that we as developers no longer have to have the "token of shame" for breaking the build, is the notion of Gated Check in. With a gated check in policy, the developer checks in their code change and it is stored in a "Shelf Set". The shelf set is then merged locally and used to do a build; only if this build is completed is the code committed to the mainline code for use by other team members.
The builds in VS2010 will now be controlled using Windows Workflow, what was not clear to me is if the build workflow can then access the Windows SharePoint Services workflow environment to create or update WSS / SharePoint data. I can see this may be hard to do since they could potentially be running on different database servers.
Finally of note is the test case selection process, which can be used as part of the check in process. With VS2008 if you require unit tests to be run as part of a build after check in, this can take considerable time, with potentially the bulk of the tests not executing any of the new code. With VS2010, you can select to run a subset of the tests, with the subset being selected based on which tests will execute the newly checked in code. The test selection is performed using the test coverage information from the previous test runs. This should reduce the test case selection and time to execute making running unit tests as part of the check in very appealing.
Ian.
We have attended some great sessions over the past couple days, I was especially impressed with Pej Javaheri's session on Excel Services and Michael Noel's session on MOSS Farm Redundancy.
Microsoft Data Protection Manager 2007 is one of the interesting discussions that has come up during Michael's session. It looks like a very interesting tool for backing up and managing Microsoft Server environments, including what I care about most: SharePoint and associated data. I'll make sure to grab a copy and run it through its paces and report back to you.
-Ryan
This morning was the official Keynote for the SharePoint part of DevConnections. Thomas Rizzo (who also gave last year's Keynote) gave us some hints into the the Office 14 release of SharePoint, including the ability to collaborate on Office documents simultaneously. The emphasis towards instant gratification from a collaboration perspective is exciting. He also mentioned some of the new downloads available from CodePlex and the community kits.
There was a lot of emphasis on the Office Online movement, allowing organizations to utilize shared hosting environments for Microsoft Server technologies. You won't get access to all the administrative functions, but it's a reasonably inexpensive way to get started with SharePoint, Exchange, OCS, and an ever-growing field of Microsoft Server technologies.
Another interesting point was the Content Management Interoperability Services designed to create a standard or API for connections between Enterprise Content Management systems. This will make it much easier to integrate these platforms and manage the content between them.
More to come...
-Ryan
Earlier this year I worked on a workflow project that required the fields of a list item be hidden based on the status of the record and the users application rights. After some digging around I found the ListFieldIterator class (see http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.listfielditerator_methods.aspx) which has a IsFieldExcluded method (see http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.listfielditerator.isfieldexcluded.aspx). This allows you to exclude fields from being displayed when iterating over the fields in a list item.
The next problem was how to create my own field iterator and use it with my content type. This led me to Custom Form Templates: Form Templates are the method by which SharePoint displays a content type in display, new, and edit form. By default lists all use the same template. The template is a combination of HTML markup and server control references; some of the controls are standard ASP.Net control and some are SharePoint TemplateBasedcControl controls (see http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.templatebasedcontrol.aspx). The TemplateBasedControls can take a template which is a combination of HTML markup, ASP.Net server controls and SharePoint TemplateBasedControl controls - and so it repeats. This is the way in which SharePoint builds the UI. You can find the templates, all of which have a name, in the 12\Template\ControlTemplates directory; most of them in one file - defaulttemplates.ascx.
Searching through this file you can find template for laying out such things as document items, standard toolbars, view selectors etc. You can modify the default behavior for a given template by creating a new template with the same name and deploying it to the 12 hive and restarting IIS. You should never modify the installed files in the 12 hive as the files are used by all sites on the farm and you could break functionality.
By creating custom form layouts it is possible to layout list items in any way you need, for example the SharePoint KPI edit pages are just custom layout forms. You can change the markup and control order in the template, additionally you can define alternate templates for use with a particular control - this separation of UI markup from the control code is very powerful and flexible.
Attaching a Form template to a content type
For our application we were defining new content types using CAML and a feature definition. Attaching the custom form is achieved by adding some additional CAML markup to the type declaration:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/" >
<ContentType Description="Licensing Task Content Type"
ID="0x01008F4414E2376E47d2A84745642AFA85E3"
Name="LicensingTask"
Group="Syrinx"
Version="0">...
<XmlDocuments>
<XmlDocument NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<FormTemplates xmlns="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms">
<Display>LicenseDisplayForm</Display>
<Edit>LicenseEditForm</Edit>
<New>LicenseEditForm</New>
</FormTemplates>
</XmlDocument>
In the above example the LicensingTask content type uses a form called LicenseEditForm for new and edit and LicenseDisplay form for displaying items.
The content of the template is :
1: <SharePoint:RenderingTemplate ID="LTCLicenseEditForm" runat="server">
2: <Template>
3: <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator=" " runat="server">
4: <template_rightbuttons>
5: <SharePoint:SaveButton runat="server"/>
6: <SharePoint:GoBackButton runat="server"/>
7: </template_rightbuttons>
8: </wssuc:ToolBar>
9: <table class="ms-formtable" style="margin-top: 8px;" border="0" cellpadding="0" id="formTbl"
10: cellspacing="0" width="100%">
11: <ltc:TaskListFieldIterator runat="server" />
12: </table>
13: <SharePoint:CreatedModifiedInfo ID="CreatedModifiedInfo1" runat="server" />
14: <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTblbottom" RightButtonSeparator=" "
15: runat="server">
16: <template_rightbuttons>
17: <SharePoint:SaveButton runat="server"/>
18: <SharePoint:GoBackButton runat="server"/>
19: </template_rightbuttons>
20: </wssuc:ToolBar>
21: </Template>
22: </SharePoint:RenderingTemplate>
23:
Line 11 is where the use of the custom field iterator is defined. The prefix ltc is used to identify the control to be used is from a specific assembly and namespace, at the top of the template ascx file there is a prefix definition:
<%@ Register TagPrefix="ltc" Assembly="Licensing, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6c1fd21dbc7fb55e"
Namespace="syrinx.SharePoint.Licensing.WebControls" %>
For more information on layout forms see http://msdn.microsoft.com/en-us/library/aa544142.aspx
I've been very busy the past few months on various SharePoint projects, but forced myself to get out for this conference because of how good it was last year. I'll try to report on the sessions and post some pictures of the happenings out here.
-Ryan
For those of you out there who have (or have not) written custom Event Receivers to manage the adding, updating, deleting, etc. of your list items at the coding level may have run into this problem. My particular problem was that I was writing a workflow application that needed to update the underlying List Item tied to the workflow at various points along the State Machine process. I'm sure this is extremely common, as permissions need to be managed, metadata needs to be updated, etc. as an item moves through business process. When this happens I don't want a version created or any of my custom event receiver code to fire.
What I found was disappointing. Using SystemUpdate() helps to prevent version incrementing, but will not disable event firing. You can call DisableEventFiring() in the context of a SPItemEventReceiver, but no where else in SharePoint seems to support this functionality. So, I used .NET Reflector to open the SharePoint assembly to track down what this method actually does.
If you open the assembly and look at the SPItemEventReceiver class, you see it has a base class called SPEventReceiverBase. In this class are only 2 methods: EnableEventFiring() and DisableEventFiring(). Both set SPEventManager.EventFiringDisabled (bool). If you look at this Class and property (all by using disassemble) in .NET Reflector, you can see what the actual property is doing in the image below
Before seeing what this code was doing under the covers, I was worried about creating my own Class that inherited from SPItemEventReceiver and calling the DisableEventFiring() and EnableEventFiring() methods manually. I had no idea if this was specific to the user context, or disabled events for that period of time across the entire application. Thanks to Reflector I feel comfortable calling this code because it is based on the thread and should not affect other users of the application and their subsequent list item updates.
The two images below show what I did to solve this problem. I created a lightweight class that contains methods for disabling and enabling event firing on the thread. All my code then uses this class when performing system level updates where I don't want to raise any of the List Item events.
Custom Class:
Code that uses the custom class to suppress event firing:
This code seems to be working fine, although I haven't put much testing into it yet.
I hope this helps,
-Ryan