November 2009 - Posts

I have a talk coming up on Code Access Security at SharePoint Saturday Kansas City next month so I have been investigating sandboxed solutions quite a bit.  After all, sandboxed solutions are just another flavor of using CAS with some additional things thrown in.  However, after I got my SharePoint server installed and configured, I found that sandboxed solutions were not working.  When I configured my solution to use the sandbox and tried to deploy it, I got the following error.

Error occurred in deployment step 'Activate Features': Cannot start service SPUserCodeV4 on computer 'servername'.

I found that to be odd, so I decided to do some looking around.  I ended up in the Windows Services MMC snapin and found that the service called Windows SharePoint Services UserCode Host v4 was in fact set to disabled.  I changed this to automatic and started the service up.  I tried to deploy again, but unfortunately things still weren’t working.  Here is the error I got this time.

Error occurred in deployment step 'Activate Features': This feature cannot be activated at this time. The contents of the feature's solution requires the Solution Sandbox service to be running.

This one took a little bit more digging, but I ended up going to Central Administration and looking at the Services on Server page.  I thought what I needed would be under Service Applications, but that was not the case.  I took a look at Services on Server and quickly discovered that the Microsoft SharePoint Foundation User Code Service had not been started.  I started the service and then I tried to deploy again and the errors went away and my sandboxed web part worked as expected.  I’m not sure why neither of these started.  It could be because I don’t have enough memory allocated to the virtual machine or maybe it’s always disabled by default.  Anyhow, be sure and check these two things before you try to work in the sandbox.

UPDATE: @MSwannMSFT confirmed for me that this is by design.  It’s disabled for performance and security since it spins up three new processes.

In SharePoint 2010, there is the concept of a UI Version and it has a value of 3 or 4.  When you upgrade your existing site, it will leave you at Version 3 which looks just like WSS3.  However, you have the capability to upgrade to the new SharePoint 2010 visualizations which is version 4.  If the administrators have the options enabled, you can change your UI version using the UI itself.  It provides the capability to run on Version 3 but get a preview of 4 and then ultimately they can convert to version 4 completely.  However, you may want to do this programmatically or you may want to revert back to version 3 after you have turned off preview mode.  This quick snippet of code is how you do it. 

using (SPSite siteCollection = new SPSite("http://sp2010-server"))

{

    SPWeb site = siteCollection.OpenWeb()

    {

        site.UIVersion = 3;

        site.UIVersionConfigurationEnabled = true;

        site.Update();

    }

}

Here, we are using the new UIVersion property and we are reverting back to Version 3.  I’m also enabled the Version Configuration in the User Interface.

By now, you have heard about how the SharePoint 2010 development experience has been improved.  We can easily deploy web parts and other code without having to manually manipulate any XML files.  What about under partial trust though?  Many of you that know me know that I have pushed using Code Access Security quite a bit through a series of blog posts and talks.  So it would be irresponsible of me not to talk about how we can do that in Visual Studio 2010.  The good news is that it is a lot easier.

Let’s start by creating a new SharePoint project in Visual Studio 2010 and creating a new Web Part project item.  In this case we are talking about deploying a Farm Solution, not a Sandboxed Solution.  Note: we are going to talk about a traditional web part today, and not a Visual Web Part.  Visual Web Parts are simply not supposed under partial trust.  More on that later below.  My web part has some simple code which uses ASP.NET and also hits the SharePoint object model to display the title of the site in a label.  Here is what the code looks like.

protected override void CreateChildControls()

{

    Controls.Add(new Label(){Text = "<div>My Cool Web Part!</div>"});

    Controls.Add(new Label() { Text = string.Format("Site Title: {0}", SPContext.Current.Web.Title) });

 

    base.CreateChildControls();

}

When you create a new project, it deploys to the GAC by default.  We start by changing this on the project properties.

CASWebApplication

This effectively changes the DeploymentTarget attribute on Assembly element in the Manifest.xml.  At this point, you may be asking.  “Sweet, is that it?  Does it take care of the CAS policy for me?”  The answer to that of course is “No.”  However, it is quite easy to add it.  Let’s see what happens if we try to deploy it as is.  I’ll just hit F5 to start debugging.  I then add my web part to any existing page, and I immediately get hit with the following in Visual Studio.

CASSecurityExceptionYellowScreen

System.Security.SecurityException: Request for the permission of type 'Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' failed.

Luckily we know how to fix this.  Hopefully, this will also help new developers when they get this error in the future and aren’t sure what to do.  We need to grant permissions to this assembly to use the object model as well as a few other things.  We’ll start by using a standard set of IPermission elements that I have used in past posts.  This gives me basic ASP.NET, SharePoint object model, and Security permissions.

<CodeAccessSecurity>

  <PolicyItem>

    <PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for VisualWebPartProject1.">

      <IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />

      <IPermission class="SecurityPermission" version="1" Flags="Execution,ControlPrincipal,ControlAppDomain,ControlDomainPolicy,ControlEvidence,ControlThread" />

      <IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

                   version="1" ObjectModel="True"  />

      <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="UserName" />

      <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="$AppDir$" Write="$AppDir$" Append="$AppDir$" PathDiscovery="$AppDir$" />

    </PermissionSet>

    <Assemblies>

      <Assembly Name="VisualWebPartProject1"  />

    </Assemblies>

  </PolicyItem>

</CodeAccessSecurity>

You can use this in your code almost exactly but two small changes are required.  First, you need to change your assembly name to whatever you have called yours.  Secondly, if you look at that SharePointPermission, you’ll notice it says version 12.0.0.0.  We need to change this to 14.0.0.0 since we are working with SharePoint 2010 now.  Adding this to your package is quite easy.  In the Solution Explorer, locate Package and then Package.package and open it.  This will bring open the package designer.  Click on the Manifest tab at the bottom and then expand Edit Options.  The way this works is that you can paste any additional elements here and it will merge your items with the ones it automatically generates.  Here is what I would paste in.

<?xml version="1.0" encoding="utf-8"?>

<Solution xmlns="http://schemas.microsoft.com/sharepoint/">

  <CodeAccessSecurity>

    <PolicyItem>

      <PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for VisualWebPartProject1.">

        <IPermission class="AspNetHostingPermission" version="1" Level="Minimal" />

        <IPermission class="SecurityPermission" version="1" Flags="Execution,ControlPrincipal,ControlAppDomain,ControlDomainPolicy,ControlEvidence,ControlThread" />

        <IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

                     version="1" ObjectModel="True"  />

        <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="UserName" />

        <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="$AppDir$;C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\CONTROLTEMPLATES\VisualWebPartProject1" Write="$AppDir$" Append="$AppDir$" PathDiscovery="$AppDir$" />

      </PermissionSet>

      <Assemblies>

        <Assembly Name="VisualWebPartProject1"  />

      </Assemblies>

    </PolicyItem>

  </CodeAccessSecurity>

</Solution>

Here is what it would look like on the screen.

CASPackageEditor

If everything is correct, you will see the merged result up top.  If there is an error in your XML, you will also see it there.  Now let’s deploy the solution and see if we can add the web part to an existing page. 

CASAPTCAError

Unfortunately, this is the error we get and it actually gives us good information.  We simply forgot to add the APTCA attribute (or AllowPartiallyTrustedCallers).  Just open your AssmeblyInfo.cs file and add the following line.

[assembly: AllowPartiallyTrustedCallers()]

Redeploy your solution and try to add your web part again.  If all goes well, you will have a lovely web part on the screen that looks like this.

CASWorkingWebPart

With the above set of CAS policies, you can probably get most of the code you want to do to work.  I mentioned Visual Web Parts above.  Here is the issue I am currently seeing.  If you remember my post on the Visual Web Part, you will know that this is just a web part with a Page.LoadControl() method calling a User Control (.ascx).  Page.LoadControl requires a ton of permissions and I haven’t been able to figure them out.  This means, it simply will not work.  I posted something to the forums about it.  Paul Andrew was nice enough to respond to my post and state that Page.LoadControl simply will not function under partial trust.  It has a check in it to verify that it is not running under partial trust.  He also goes on to explain this is why you can’t use Visual Web Parts in sandboxed solutions.

This may seem like a lot of steps, but really I just posted a lot of pictures.  Trust me it’s a lot fewer steps than it was before in MOSS 2007.  Just look at my old post if you don’t believe me.  Now, you might ask why would I do this instead of a Sandboxed solution?  Sandboxed solutions are severely limited on what they can do with the SharePoint object model.  By default, the CAS policy that defines them can’t even connect to a database.  I can specify at a per assembly level here what each one can do.  That is a big advantage.

I was working on my first SharePoint 2010 post today since I actually installed some bits and quickly discovered that I did not have Copy Source As Html working with Visual Studio 2010 Beta 2.  If you’re a blogger like me, you will find that you are quite addicted to this useful tool as it makes pasting good looking code segments quite easy.  Unfortunately, they haven’t released an installer that works with Visual Studio 2010 yet, so I decided to see if I could figure out how to get it to work.  Now, I’m not expert on Visual Studio Addins, so it took me some experimenting.  I installed the product as normal, but when I opened Visual Studio, I did not find the addin loaded.  After some investigating, I decided to copy the CopySourceAsHtml.AddIn file into my user folder.  Specifically this goes in C:\Users\<UserName>\My Documents\Visual Studio 2010\Addins.  Note: the My Documents folder is actually the Documents folder if you are looking at it directly on the file system.  Also to note is that the Addins folder probably will not exist so you need to create it.

After I did this, I tried opening Visual Studio again and again did not see my addin loaded.  I then decided to open the file and take a look.  I quickly saw something that stood out at me.

<?xml version="1.0" encoding="utf-8" standalone="no"?>

<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">

  <HostApplication>

    <Name>Microsoft Visual Studio Macros</Name>

    <Version>9.0</Version>

  </HostApplication>

  <HostApplication>

    <Name>Microsoft Visual Studio</Name>

    <Version>9.0</Version>

  </HostApplication>

  <Addin>

    <FriendlyName>CopySourceAsHtml</FriendlyName>

    <Description>Adds support to Microsoft Visual Studio 2008 for copying source code, syntax highlighting, and line numbers as HTML.</Description>

    <Assembly>JTLeigh.Tools.Development.CopySourceAsHtml, Version=3.0.3215.1, Culture=neutral, PublicKeyToken=bb2a58bdc03d2e14, processorArchitecture=MSIL</Assembly>

    <FullClassName>JTLeigh.Tools.Development.CopySourceAsHtml.Connect</FullClassName>

    <LoadBehavior>1</LoadBehavior>

    <CommandPreload>0</CommandPreload>

    <CommandLineSafe>0</CommandLineSafe>

  </Addin>

</Extensibility>

This is version 10 of Visual Studio so I decided to increment the new two version elements as shown below.

<?xml version="1.0" encoding="utf-8" standalone="no"?>

<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility">

  <HostApplication>

    <Name>Microsoft Visual Studio Macros</Name>

    <Version>10.0</Version>

  </HostApplication>

  <HostApplication>

    <Name>Microsoft Visual Studio</Name>

    <Version>10.0</Version>

  </HostApplication>

  <Addin>

    <FriendlyName>CopySourceAsHtml</FriendlyName>

    <Description>Adds support to Microsoft Visual Studio 2008 for copying source code, syntax highlighting, and line numbers as HTML.</Description>

    <Assembly>JTLeigh.Tools.Development.CopySourceAsHtml, Version=3.0.3215.1, Culture=neutral, PublicKeyToken=bb2a58bdc03d2e14, processorArchitecture=MSIL</Assembly>

    <FullClassName>JTLeigh.Tools.Development.CopySourceAsHtml.Connect</FullClassName>

    <LoadBehavior>1</LoadBehavior>

    <CommandPreload>0</CommandPreload>

    <CommandLineSafe>0</CommandLineSafe>

  </Addin>

</Extensibility>

After I saved the changes, I restarted Visual Studio and sure enough the addin loaded and worked correctly.  In fact I pasted the above snippets using the tool in Visual Studio 2010.  If you have never used Copy Source as Html before, go check it out.  It’s a handy tool for pasting code snippets.

with 8 comment(s)
Filed under:

Last weekend, I gave my introduction to Enterprise Search talk where I showed the basics of using search.  One of the topics I covered is how to use federated search to display results from an external web site.  I’ve seen this topic come up in the forums as well, so I thought I would write something up on it.  Typically when people do this is they have federated results from their public facing corporate web site display along side the results from a regular search on the SharePoint farm.  Everything we are doing today can be done without writing any code.

For today’s demonstration, we will pretend DotNetMafia.com is a corporate web site and federate results from it.  When the user executes a document search on my SharePoint site, we will show those results as well as results from DotNetMafia.com that match the user’s keyword query.  To be able to show results from the corporate web site, we will need these results available in a search index.  For today, we will index DotNetMafia.com on the same search server, but this could also be an external server as well.  You can use anything that returns an RSS feed of results following the Open Search 1.0 / 1.1 standard.  Since, we are using the same server, we will just create a new content source to index our corporate web site.  I specify the URL of the start address and then I start a full crawl on this content source.

SearchContentSourceDotNetMafia

The next thing I need is to create a scope for my corporate web site.  This will allow us to easily filter the results later so that we can get results from just DotNetMafia.com.  This scope will just have one rule which uses the DotNetMafia.com content source.  We’ll call my scope DotNetMafia.

SearchScopeDotNetMafia

At this point we are ready to create our new federated location to display the results of our corporate web site.  Click on the Federated Locations link on your search administration page.  At this point, it’s probably good to remind you that Federated Locations is only there if you are running the Infrastructure Update (or later) or Search Server.  This is pretty easy to do because we can start with the Local Search Results federated location and make a copy of it.  We can use a copy of the Local Search Results location because in my case the index is running on the same server.  If you are going against an external search server, it’s also pretty simple, you just have to know the URL to get the search results from.

SearchFederatedLocationsCopy

Once you have made your copy, edit your new location.  You will need to specify a name.  In my case I just went with DotNetMafia.  You can set this as you see fit.  Most of the other values you do not need to change, until you get to the Location Information section.  Here you will choose, Search Index on this Server for the Location Type.  We now need to change the Query Template to include the scope that you created earlier.  The query template passes what the user search for in the {searchTerms} token.  We can simply make use of the keyword query syntax here and append a Scope keyword like shown below.

{searchTerms} Scope:”DotNetMafia”

Specify the name of your scope in quotes.  We also need to add Scope:”DotNetMafia” to the “More Results” Link Template.  Here is what both of those changes look like after you have changed them.

SearchFederatedLocationDotNetMafia

These are the only fields that you need to change to get started.  Once you save your new federated location, we are ready to configure this on your search center results page.  I am assuming today that you already have an existing search center site.  If not, go create one.  Then go to your results.aspx page and edit it.  You may or may not have a federated results web part(s) already on this page.  If you don’t have one, click on the Right Zone and add a new web part and choose it from the list.  If you have an existing Federated Results web part, you may change your existing one if you don’t want to search bing any more.  You can also add another one to display multiple federated results at the same time.  Here is what one looks like.

SearchResultsFederatedResultsEditMode

Whether you use an existing Federated Results web part or a new one, you will want to configure it to use your new federated location.  Under Location Properties, choose the name of your Federated Location from the dropdown list.  Click ok, and publish your results page.

SearchFederatedResultsWebPartProperties

You can now try out your new federated search.  In my case I am searching my local SharePoint server for the keyword Accounting.  It will also return any results that match that keyword from DotNetMafia.com.  Here is what those results look like.

SearchFederatedResults

This is a simple way to quickly give your users results from multiple sources at once.  It requires very little configuration and no code at all.  It’s easy to test out, so try it out on your own SharePoint farm and see how your users like it.

I’ve been working with audiences again, so I recently wanted to set the target audience of a web part.  Sure anyone can set it in the UI, but I want to automate my deployment, so I wanted to do it programmatically using a feature receiver.  When I first started looking for more information on how to do this, I wasn’t finding exactly what I needed and I did find some conflicting information.  To be clear about what I am talking about today, I am discussing how to target a web part to an audience in MOSS that was defined and compiled in the SSP.  Since I couldn’t find much info on the Internet, I posted something on twitter and I got a response from Randall Isenhour (@sharepointdev) on the SharePoint SDK team who referred me to Jim Crowley.  Thanks to both of them for pointing me in the right direction.

For today’s discussion, we have two audiences: Audience 1 and Audience 2 as shown below.

AudienceList

You might think that you would apply an audience to a web part using the AudienceManager class but that in fact not the case.  We actually do this by making use of the AuthorizationFilter property on the WebPart class.  The problem is that this property takes a syntax that not too many people fully understand.  Luckily, Jim pointed me to this post by Gary Lapointe where he demystifies how the string is created.  The AuthorizationFilter property can be used to specify a GUID to an audience.  However, it can also be used to specify an  LDAP distinguished name or a SharePoint group.  In this case we only care about the GUID to the audience.  All three can be specified in one string and are delimited with a double semi-colon (;;).  The first group is where you specify Audience Ids, the second is the distinguished name, and the last is the SharePoint group.  You don’t have to specify all three though, we’ll only be specifying the audience today. 

Let’s take a look at some code.  For today’s example, we can assume that we are writing code inside a FeatureActivated event handling method.  I’ll be getting a reference to an SPWeb object from there.  I am simplifying this example some because I only have one web part on my page and so I am just referencing it with an indexer value of 0.  You will want to change this to some code to find the appropriate web part on your page.  You’ll also need references to Microsoft.SharePoint, Microsoft.SharePoint.WebPartPages, and Microsoft.Office.Server.Audience.

using (SPWeb currentSite = (SPWeb)properties.Feature.Parent)

{

    using (SPLimitedWebPartManager webPartManager

        = currentSite.GetLimitedWebPartManager("default.aspx", PersonalizationScope.Shared))

    {

        AudienceManager audienceManager = new AudienceManager(ServerContext.Current);

 

        webPartManager.WebParts[0].AuthorizationFilter

            = string.Format("{0};;;;", audienceManager.GetAudience("Audience 1").AudienceID);

 

        webPartManager.SaveChanges(webPartManager.WebParts[0]);

    }

}

I then use the SPLimitedWebPartManager against the page I am working with (in my case default.aspx).  The AuthorizationFilter takes a GUID, so I need to look up the GUID for my audience using the AudienceManager.  It has a GetAudience method which takes a parameter which is the name of the audience (Audience 1).  I can then use the AudienceID property to write the GUID into the AuthorizationFilter property followed by “;;;;".  We have to specify the four semi-colons since other types of filters can be applied here in this case.  My AuthorizationFilter string would look something like this.

D2E05D3D-633F-4f0b-BA47-64E0F6A40A74;;;;

The last thing, you have to do is call SaveChanges on the SPLimitedWebPartManager object and pass a reference to your web part.  I’ll go ahead and point out now that, there is no error checking in the code above.  If you are to do this, you would want to add checks to verify that the page, web part, and audience exist to say the least.  If all goes well, when you view your page, you should be able to verify that the target audience is set like below.

TargetAudiences1

Now, I’m sure you know that you can target more than one audience on a web part, right?  It would be bad form for me not to show you how to do that, so here is what that looks like.  The key is using a comma to delimit each audience.  Here is what that code would look like.

webPartManager.WebParts[0].AuthorizationFilter = string.Format("{0},{1};;;;",

    audienceManager.GetAudience("Audience 1").AudienceID,

    audienceManager.GetAudience("Audience 2").AudienceID);

The result would then look like this.  SharePoint shows them delimited with a semi-colon when viewing them in the UI.

TargetAudiences2

As you can see, setting a target audience is actually quite easy once you know the syntax of the AuthorizationFilter string.  I have also found that sometimes when messing with audiences, that the Target Audiences property will completely disappear from the UI.  Although, I’m not sure what the cause of this is, I have found that you can bring it back by rebooting.  I have also found that you can restart the Windows SharePoint Services Administration service followed by an iisreset and it will come back as well.

with 22 comment(s)
Filed under: ,

I had a great time speaking again at Tulsa TechFest 2009.  I gave my intro talk on Enterprise Search again, but this time I updated it to talk about features upcoming in SharePoint 2010.  My slides are attached at the bottom of this post.  I always really enjoy TechFest and getting the opportunity to meet and talk with so many great people.  David Walker did an excellent job as usual putting everything together, but I would like to see the two day format return. :-)  Maybe if some of us get together and offer him a hand, we can have two days next year.

Ah, don’t you love COMExceptions?  Recently, I was adding two new site columns to a list and encountered a whole slew of errors when trying to create new items in the list.  This is the error I got when I was trying to create a custom folder.

System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x80040E14
[COMException (0x80040e14): Exception from HRESULT: 0x80040E14]
   Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +0
   Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +203

This is the error when I tried to check in a document.

[COMException (0x81020030): The URL 'Lists/MyList/MyDocument.docx' is invalid.  It may refer to a nonexistent file or folder, or refer to a valid file or folder that is not in the current Web.]
   Microsoft.SharePoint.Library.SPRequestInternalClass.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +0
   Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish) +203

Lastly, this is the error I got when trying to save a document from Microsoft Word after using the New Document command.

The internet address ‘http://moss-server/Lists/MyList/MyDocument.docx’ is not valid.

Wow!  That’s a whole lot of different errors that all are stemming from the same issue.  What’s the issue? Well after some quick Google research, I knew it had something to do with duplicate columns.  I just added two new columns, so I knew where to start.  In this case, I cut and paste one column and changed the values of the DisplayName, Name, and StaticName columns as well as the Id.  I figured that should be good, but that was not the case.  Look at my two columns and see if you can spot the issue.

<Field Type="Text" DisplayName="MyField1" Required="FALSE" MaxLength="255" Group="Custom" ID="{8e62a2e4-20b9-4689-b379-4674db156b25}" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="MyField1" Name="MyField1" Customization="" ColName="nvarchar20" RowOrdinal="0" />

<Field Type="Text" DisplayName="MyField2" Required="FALSE" MaxLength="255" Group="Custom" ID="{C133215B-053A-4a31-BD1E-724140A4663D}" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="MyField12" Name="MyField2" Customization="" ColName="nvarchar20" RowOrdinal="0" />

Everything might look ok at first, but it won’t look ok if you are familiar with what the ColName attribute does.  This specifies the specific field in the underlying database you want that column to use.  As you can see in my case, ColName for both fields is set to nvarchar20.  This causes a big problem (and all of the errors you see above).  Now you ask why on earth would I have ColName specified?  Well, that is actually a result of SPSource.  I assume, the way it works is by looking at the Schema property of the field when it exports it which contains this extra information.  The fix is quite simple.  Just remove the ColName attribute and everything will work fine.  Again, if you haven’t checked out SPSource yet, I recommend it for exporting content types and lists, but be sure to look over any XML before you use it.

with 5 comment(s)
Filed under: , , ,

@SPKyle let work get in the way of his speaking gig, so I get to fill his spot this year. :-)  I’m going to be giving my intro talk on Enterprise Search.  This is a good talk for anyone that isn’t very familiar with what Enterprise Search can do for their organization.  It’s also good for those that are looking to learn more about what other types of content can be indexed.  I’ve also updated it to include what’s new in search with SharePoint 2010.

It wouldn’t be a Tech Fest without a Dot Net Mafia event.  If you are coming in early to speak or attend the conference, we’ve got something for you to do Thursday night.  We’ll be meeting at our usual venue, Dirty’s Tavern (325 E. 2nd St – 2nd and Elgin) which is just a few blocks down from the Crowne Plaza hotel.  We’ll probably be meeting there around 7:00 or 8:00 and hanging out until whenever.  If you get hungry, there is a Pizza place right next door.  If you need more info, get a hold of me on twitter.  Look forward to seeing you all there.

Shared Services Provider.  Gone! 

The concept of the SSP is no more.  It has been replaced with a new concept called the Services Architecture.  Your SharePoint installation will not have a separate SSP site like you had in the past.  You now manage all of your familiar services like Search, the BDC, Excel Services directly through Central Administration on the new Manage Service Application page.  This is where you will go to find familiar screens like Search Administration, User Profiles, and the Business Data Catalog (now BCS).  The trick to getting to them, click on the item in the list and then use the Manage button on the toolbar. 

I’m not going to go into a lengthy explanation of how it all works (because honestly I don’t understand it all), but I’ll give you a quick run down.  Before we start, the term Service is highly overused.  In this case it does not refer to a WCF, Web, or Windows service.  In this case, Service refers to the actual program be it Search or something that you write yourself.  A Service Application is an the configuration of your service on the farm.  The provider of the Service will provide you the developer with a Service Application Proxy.  This is basically some type of assembly that interacts with the service via WCF.  If the Service Application is installed on multiple servers in the farm, a built-in load balancing scheme will be used to distribute request among servers.  From my understanding, all of the existing API calls for things like search have been updated to fit into this model.

Effectively the Services Architecture is a new pluggable architecture which makes it possible for third parties to create their own services.  I’ll also point out that you can now publish specific services and consume specific servers from remote farms which gives you quite a bit more flexibility.  As opposed to the all or nothing we had with sharing SSP services between farms in MOSS 2007.  Andrew Connell has a post that goes into more detail on why they shifted to this new architecture.  It’s definitely worth the read.

Since the SSP is gone, you may be wondering what’s going to happen with all my code that references the SSP.  If you using something like the UserProfile object and using the ServerContext object to reference the SSP, it may or may not work.  ServerContext has been marked as deprecated.  If you do try to use ServerContext, Visual Studio will tell you to use ServiceContext instead.  If you do have SSP specific code, be sure and test it specifically during your upgrade process.

BTW, the start of this post was an obscure reference to another presentation on a completely unrelated topic.  I’ll be truly impressed if anyone gets it. :)

Follow me on twitter.