Monthly Archives: November 2007

You Can’t Beat SharePoint’s Reach

During the last two days, I have participated in two meetings during which we presented the results of a SharePoint project.  The CIO and his team joined the first meeting.  That’s standard and not especially notable.  The IT department is obviously involved in an enterprise rollout of any technology project.  The second meeting expanded to include a V.P. from marketing, several directors representing HR, Logistics, Manufacturing, Capital Projects, Quality, Purchasing, Corporate development and other departments (some of whom were not even directly involved in the current phase).  That’s a mighty wide audience.

In my prior life, I primarily worked on ERP and CRM projects.  They both have a fairly wide solution domain but not as wide as SharePoint.  To be fully realized, SharePoint projects legitimately and necessarily reach into every nook and cranny of an organization.  How many other enterprise solutions have that kind of reach?  Not many.

SharePoint clearly represents an enormous opportunity for those of us fortunate enough to be in this space.  It provides a great technical opportunity (which is somehow turned on its head here under "Technologies You Must Master").  But even better, SharePoint exposes us to an extensive and wide range of business processes through these engagements.  How many CRM specialists work with the manufacturing side of the company?  How many ERP consultants work with human resources on talent acquisition?  SharePoint exceeds them both.

Like anything, it’s not perfect, but it’s a damned good place to be.

For the love of [fill in your most loved person/higher being], don’t change the ‘Title’ site column.

 

On the SharePoint forums, someone occasionally asks about "changing the label of Title" or about "removing title from lists".

Bottom line: Don’t do it!

Sadly, the user interface allows a one-way change of that column label as shown:

image

Title is a column associated with the "Item" content type. Many, many, many CT’s use this column and if you change it here, it ripples out everywhere.  There’s a good chance that you didn’t intend for that to happen.  You were probably thinking to yourself, "I have a custom lookup list and ‘Title’ just doesn’t make sense as a column name, so I’m going to change it to ‘Status Code’ and add a description column."  But if you follow through on that thought and rename ‘Title’ to ‘Status Code’, every list’s title (including document libraries) changes to "Status Code" and you probably didn’t intend for that to happen.

The real problem is that this is a one-way change.  The UI "knows" that "title" is a reserved word.  So, if you try and change "Status Code" back to "Title", it will prevent you and now you’ve painted yourself into a corner using paint that never dries 🙂

So what happens if you already changed it?  I haven’t seen the answer we all want, which is a simple and easy method to change the label back to ‘Title’.  Right now, the best advice is to change it to something like "Doc/Item Title".  That’s a generic enough label that may not be too jarring for your users.

I have few other ideas which are on my to-do list of things to research:

  • Contact Microsoft.
  • Do something with the object model, maybe in conjunction with a feature.
  • Figure out the database schema and manually update SQL.  (You should contact Microsoft before doing this though; it will likely void your support contract).

If anyone knows how to solve this, please post a comment.

Update late afternoon, 11/15: I found this link that describes a method for creating a type of list that does not have a title column: http://www.venkat.org/index.php/2007/09/03/how-to-remove-title-column-from-a-custom-list/

BDC ADF and your friend, CDATA

I’ve noticed some awkward and unnecessary hand-encoding of RdbCommandText in some examples (including MSDN documentation).

I wanted to point out to newcomers to BDC that commands can be wrapped inside a CDATA tag in their "natural" form.  So, this awkward construction:

<Property Name="RdbCommandText" Type="System.String">
SELECT dbo.MCRS_SETTLEMENT.id, dbo.MCRS_SETTLEMENT.settlement from dbo.MCRS_SETTLEMENT
    WHERE (id &gt;= @MinId) AND (id &lt;= @MaxId)
</Property>

can be better represented this way:

<Property Name="RdbCommandText" Type="System.String">
  <![CDATA[
    SELECT dbo.MCRS_SETTLEMENT.id, dbo.MCRS_SETTLEMENT.settlement from dbo.MCRS_SETTLEMENT
      WHERE (id >= @MinId) AND (id <= @MaxId)
 
]]>
</Property>

</end>

BDC Primer

Intro to BDC

Functional Example: BDC ADF that connects to SQL database with embedded user id and password

I needed to wire up MOSS to a SQL database via BDC.  For testing/POC purposes, I wanted to embed the SQL account user id and password in the ADF.  Starting with this template (http://msdn2.microsoft.com/en-us/library/ms564221.aspx), I created an ADF that connects to a particular SQL server instance and logs in with a specific user id and password and shown in this snippet:

  <LobSystemInstances>
    <LobSystemInstance Name="ClaimsInstance">
      <Properties>
        <Property Name="AuthenticationMode" Type="System.String">PassThrough</Property>
        <Property Name="DatabaseAccessProvider" Type="System.String">SqlServer</Property>
        <Property Name="RdbConnection Data Source" Type="System.String">actual server\actual instance</Property>
        <Property Name="RdbConnection Initial Catalog" Type="System.String">actual initial catalog</Property>
        <Property Name="RdbConnection Integrated Security" Type="System.String">SSPI</Property>
        <Property Name="RdbConnection Pooling" Type="System.String">false</Property>

        <!-- These are the key values: -->
        <Property Name="RdbConnection User ID" Type="System.String">actual User ID</Property>
        <Property Name="RdbConnection Password" Type="System.String">actual Password</Property>
        <Property Name="RdbConnection Trusted_Connection" Type="System.String">false</Property>

      </Properties>
    </LobSystemInstance>
  </LobSystemInstances>

It is not a best practice, but it’s useful for a quick and simple configuration for testing.  This was surprisingly difficult to figure out.  I never found a functional example with search keywords:

  • adf embedded userid and password
  • embed user id and password in adf
  • embed user id and password in adf bdc
  • sharepoint bdc primer
  • sharepoint embed user id and password in adf

</end>

 Subscribe to my blog.

SPD custom workflow actions — string manipulation enhancements

About a week ago, I started up a codeplex project that provides a simple and reasonably generic method for adding custom action functions to SharePoit Designer workflow.  It’s described here: http://www.codeplex.com/spdwfextensions.  Beyond simply providing a framework, it also aims to provide a set of useful functions that will make SPD more useful/flexible/powerful. 

Here are the current planned features for version 1.0: https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=spdwfextensions&ReleaseId=8280

If anyone has any interest in this project, please leave a comment or start/add to a discussion here: http://www.codeplex.com/spdwfextensions/Thread/List.aspx

Here are the current set of functions that have been coded (though not fully tested as of 11/08/07):

Function Description (if not same as .Net function)
Num-entries() Returns the number "entries" in a string as per a specified delimiter. 

For example: Num-entries in a string "a,b,c" with delimiter "," = 3.

Entry() Returns the nth token in a string as per a specified delimiter. 
Length String.Length
Replace() String.Replace()
Contains() String.Contains()
Returns the word "true" or the word "false".
Substring(start) String.Substring(start)
Substring(start,end) String.Substring(start,end)
ToUpper() String.ToUpper()
ToLower() String.ToLower()
StartsWith() String.StartsWith()
Returns the word "true" or the word "false".
EndsWith() String.EndsWith()
Returns the word "true" or the word "false".

Quick & easy url Encoding desktop utility

I’ve been needing to url-encode some strings this week and slapped together a a little utility that I thought I’d put up on SkyDrive for the community.

Get the binary here: http://cid-1cc1edb3daa9b8aa.skydrive.live.com/self.aspx/SharePoint/WinUrlEncode.zip

Get the visual studio solution here: http://cid-1cc1edb3daa9b8aa.skydrive.live.com/self.aspx/SharePoint/WinUrlEncodeVS2005.zip

Here’s a screen shot:

image

Quick and easy: Embed a hyperlink into data view web part XSLT

UPDATE (01/17/08): This blog entry talks about more hyperlink XSL goodness: http://www.sharepointsecurity.com/blog/sharepoint/sharepoint-2007-development/rewriting-links-in-search-results-xslt.

Overview and Objective: I had created a simple bar chart to serve as component on a dashboard.  I’ll save the details on building charts for another post, but I did not invent that technique (nor the question mark, for that matter).  It turned out there was a bug in the chart and while I fixed that, I took the opportunity to convert some labels into hyperlinks that pointed at the underlying list behind the graph.  For example, there is a label with value "Hold".  I wanted to turn the label into a hyperlink so that the user could click on it and drill down to the specific entries in the list whose status value is "Hold".

Steps:

  1. Use visual studio for sharepoint-aware intellisense.
  2. Copy the DVWP’s XSLT into visual studio (create a blank project, add an XSL file to the project).
  3. Copy the link you want to use into the clipboard.
  4. Paste it into the right location in the XSL.
  5. Convert URL argument separators on the query string from "&" to "&amp;"
  6. Url-encode individual arguments.
  7. Wrap that inside an <a href…> </a>

Example:

I have an URL:

http://[server]/[site]/Lists/Open%20Positions/AllItems.aspx?View={84EEA2F5-121B-40B7-946F-0FA704A1DAA1}&FilterField1=Recruiter&FilterValue1=Hold

I convert it into:

     <a href="Lists/Open%20Positions/AllItems.aspx?View=%7b84EEA2F5-121B-40B7-946F-
0FA704A1DAA1%7d&amp;FilterField1=Recruiter&amp;FilterValue1=Hold"> Hold: </a>

I have manually transformed the first argument from:

{84EEA2F5-121B-40B7-946F-0FA704A1DAA1}

to:

%7b84EEA2F5-121B-40B7-946F-0FA704A1DAA1%7d

(In this, the open brace transforms to %7b and the closing brace transforms to %7d)

The second and third arguments’ parameters ("FilterField1=Recruiter" and "FilterValue1=Hold" respectively) do not need to be url-encoded because they do not contain any unsafe characters.

Notes:

This technique should generally work anywhere you want to embed a hyperlink in XSLT where the hyperlink includes parameters on the URL such as:

http://[server]/[site]/Lists/Open%20Positions/AllItems.aspx?View={84EEA2F5-121B-40B7-946F-0FA704A1DAA1}&FilterField1=Recruiter&FilterValue1=Hold

I got the URL itself by accessing the custom list and manually filtering on the status column (labeled "Recruiter" above).

Quick and Simple: Enable SharePoint Designer workflow to update an InfoPath form

Scenario: I have an InfoPath form that front-ends a workflow process implemented using SharePoint Designer.  At one point, a manager must approve the form.  Since I cannot count on workflow history to meet my auditing requirements, I decide to store my own auditing message directly on the form itself.

Overview:

Design the form and publish it as a content type and the form itself to a document library.  Mark desired form fields as being updateable from MOSS.  The form is tied to the content type and the content type is "attached" to a forms library (or many, if you want).  Write a workflow that updates the field.

Specific Steps:

  1. Create a document library.  This will hold your InfoPath template.
  2. Create a forms library. 
  3. Create the InfoPath form.  Include a text field, "Audit Message". 
  4. Publish the form as a content type (NOT a document).
  5. While filling out the publishing dialogs:
    a) Save the .xsn file to the document library (step #1).
    b) Publish the "Audit Message" field and mark true: "Allow users to edit data in this field by using a datasheet or properties page".
    c) Create a new content type and give it an appropriate name.
  6. Access the forms library.
    a) Go to its advanced settings and enable the forms library to manage content types.
    b) Select the newly created content type (5c above).  It will be grouped under "Microsoft InfoPath" (or similar).
    c) Remove the default "Form" content type from the library.
    d) Mark the library to "show as web page" so that the form will launch from SharePoint and not the InfoPath workstation client.
  7. Go back to the forms library proper and click "New" to simply verify that the form is posted correctly and acting as you want.
  8. Fire up SharePoint Designer and navigate to the site that hosts your form library (from step 2).
  9. Create a new workflow attached to the forms library.
  10. Add a single action "Set Field in Current Item".  You should expect SharePoint Designer to list your your field, "Audit Message".  Assign it a value.
  11. Click Finish and go back to the form library.
  12. Create a new form and put some test value into the "Audit Message" field.
  13. Save it and go back to the form library.
  14. Right-click, select "Workflow" and start up your workflow.
  15. It should run almost immediately.  Pull up the form (from step 12) and if all has gone to plan, "Audit Message" has been assigned whatever value you provided in step 10.

Notes:

Not all controls may configured for this bi-directional communication.  For example, it does not seem to implement an SPD workflow that modifies text fields wrapped inside repeating sections. 

One of the key take-away’s here is that we’ve really created a content type with an associated template.  This also enables us to store multiple InfoPath form templates in the same form library.

This requires forms server.  It’s most certainly not going to work in a WSS 3.0 environment and probably even requires an Enterprise SharePoint environment.

The Beagle has Landed (October 2007 issue)

(This is actually a little old news, but as my favorite fire station motto proclaims, "Better late than never").

Check it out here: http://www.sharepointbeagle.com/

If you have not already, be sure to sign up.

Of course, be sure to read my article about a real-world SharePoint project (including requirements definition, KPI’s, content types, dashboards and more) as well as my colleague’s article about the content query web part. 

There’s lot of other good stuff too.

How to remove “View all site content” link

I’m asked this question nearly every week, normally in the context of a security discussion.  An administrator/site creator has provisioned a site, configured security, arranged web parts and customized the quick launch to provide that oh-so-perfect set of options to the end user.  But, out of the box, you can’t remove the "view all site content" link.

Mark Wagner provides the answer here (http://www.crsw.com/mark/Lists/Posts/Post.aspx?ID=36). His write-up is terrific on two levels. It provides an answer to the question, "How do I remove the View All Site Content" link?  Then, it answers the immediate follow-on question: How do I easily enable the view all site content link on a site-by-site basis?

As a bonus: His approach works for WSS, not just MOSS.

</end>

 Subscribe to my blog!