Archive for the ‘SharePoint’ Category

Web Service access + internal traffic + 407 Proxy Authentication Required

Friday, March 2nd, 2012

This had me stumped for a while. I was developing a SharePoint-based client to consume a simple web service. I started by writing a console app version of the code before deploying to SharePoint. Fairly straight-forward – added a web reference to my VS2010 project, and used

MyWebService srv = new MyWebService();
srv.DoSomething();

Early on in the project, I didn’t give much to the fact that when calling the method on the web service, I was given a 407 Proxy Authentication Error. I just setup a simple proxy for it:

WebProxy prox = new WebProxy("192.168.0.1:80"); // where 192.168.0.1 is the address of the proxy.
prox.UseDefaultCredentials = true;

// Tell the service to use the proxy
srv.Proxy = prox;

This “fixed” the issue – until the point where I deployed the code in to SharePoint with multiple application / frontend servers, and I unwittingly encountered the double hop authentication problem. In short, by using the “UseDefaultCredentials” option, you’re saying “use the credentials of the person currently logged in”. This will therefore work in a Windows Auth / NTLM scenario (assuming that user is allowed to authenticate against the proxy) where everything is all happening on the same server. But when you have multiple servers, and the action happens on Server A, which triggers something on Server B, to authenticate against Server C (i.e., your web service), then things fall over because NTLM does not support user delegation. See here for a really neat explanation of it.

After faffing about a lot with credentials, and the proxy server involved, googling and so on, my brain finally engaged: All traffic is internal, why is the proxy server even involved?! The proxy server is designed to marshal access to the outside world. All internal traffic should be fine! I went back to basics. My console app still suffered the error, but the excellent SoapUI which I use for testing web services didn’t need any proxy authentication! It turns out that by default, .NET applications will attempt to use a proxy, even if it doesn’t need one. Allegedly, if it doesn’t have a proxy override configured, then it will attempt to use the Internet Options configured on the machine it’s running on. The problem though is that if you do need a proxy for some stuff, and don’t need a proxy for other stuff (in this case) then you’re in a spot of bother. The trick is to tell your .NET app (or indeed your IIS website) to not use a default proxy. This can be done by adding this to your app.config or your web.config:

<system.net>
  <defaultProxy
    enabled="false"
    useDefaultCredentials="false">
    <proxy/>
    <bypasslist/>
    <module/>
  </defaultProxy>
</system.net>

Enjoy.

Creating SharePoint 2010 Content Organizer Rules programmatically

Thursday, February 23rd, 2012

The Content Organizer (gah! Organiser!) in SharePoint 2010 is a nifty new feature that enables documents to be added to a single library (the “Drop Off Library”) and then let SharePoint route them through to the correct final resting position based on a set of configured rules. Rules can be configured per content type and allow conditions to be set based on metadata on the item. You can even use it to send documents – and document sets – between site collections, e.g., to a Records Center. Very cool.

Depending on your requirements, you may find you need to create a lot of rules which as with most things SharePoint can be cumbersome if you need to do it all through the UI. Fortunately, creating the rules programmatically is straight-forward.

(more…)

Quick tip: SharePoint powershell – get items in a list based on custom columns and other hints

Tuesday, February 14th, 2012

This may be handy when trying to find specific items in a list based on values of various fields:

$web = Get-SPWeb http://yourweb
$list = $web.Lists["Your Library Name"]

// this is the bit - get items of a particular content type
// ? is shorthand for where, and $_ is the item in the pipeline
$listItems = $list.Items | ?{$_.ContentType.Name -eq "Content Type Name"}

// or items based on a custom column - if using -like then the wildcard is *
$listItems = $list.Items | ?{$_["InternalFieldName"] -like "*this*"

// you could join them up using -and
$listItems = $list.Items | ?{$_.ContentType.Name -eq "Content Type Name" -and $_["InternalFieldName"] -like "*this*"

// or iterate the loop and print them out
foreach($item in $listItems) { Write-Host $item.Name, $item["InternalFieldName"] }

or more directly

$list.Items | ?{$_.ContentType.Name -eq "Content Type Name" -and $_["InternalFieldName"] -like "*this*" | foreach { $_.Name, $_["InternalFieldName"]

// or count them
$listItems.Count

or

$list.Items | ?{$_.ContentType.Name -eq "Content Type Name" -and $_["InternalFieldName"] -like "*this*" | foreach {$count++}
$count

Powershell can be infuriating – but when you find the syntax, it can be pretty helpful.

P.S For a bonus tip, next time you’re in Powershell, hit F7 ;)

SSRS error: Operation is not valid due to the current state of the object

Friday, February 10th, 2012

If you’re using SSRS in SharePoint integrated mode, you may come across this error when using report parameters that have a high number of items in them. A recent security bulletin highlighted some issues and vulnerabilities in ASP.net, and a patch was released to cover some of the items. One of these was the maximum number of items you can have in a collection. If you exceed the limit, then you’ll likely get an error like:

System.Web.HttpException:
The URL-encoded form data is not valid. —> System.InvalidOperationException: Operation is not valid due to the current state of the object.
at System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded()
at System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding)
at System.Web.HttpRequest.FillInFormCollection()
— End of inner exception stack trace —
at System.Web.HttpRequest.FillInFormCollection()
at System.Web.HttpRequest.get_Form()

The workaround to this is to add the following to your web.config for your IIS application:

<appSettings>
<add key=”aspnet:MaxHttpCollectionKeys” value=”5000″ />
</appSettings>

where 5000 is a number big enough to cover the number of items in your collection. Be aware of the security implications this could have. There’s some really useful info around the issue, here.

SharePoint 2010 Foundation + SQL Server Reporting Services Integrated mode installation issues: Failed to establish connection with report server, 401 errors and more

Thursday, February 9th, 2012

You may be trying to set up SharePoint 2010 to act as the report repository for SQL Server Reporting Services report. This is a pretty nifty feature, especially as it’s available in the Foundation (i.e., Free) version of SharePoint. There is a pretty exhaustive guide on how to set it up and for extra help, this blog post is pretty good too, and if you follow the steps, you get pretty far. However, if you’re in a multiple server setup (i.e. your SQL server isn’t on the same server as your Central Admin) you will likely encounter configuration issues surrounding authentication, and there is a great deal of confusion about what it all means – especially when it comes down to Kerberos. That’s beyond the scope of this post – what I’m covering here is one very annoying issue that there was no definitive answer to on the web.

Assuming you get all the server parts setup and Reporting Services configured, you might find that you can browse to your report server address on the machine hosting reporting services, but, if you try to browse to that address from anywhere else, you’ll get an endless stream of login boxes, and no credentials will work. Also, if you go to Central Admin and go to General Application Settings > Reporting Services Integration, when you fill in the details to connect to reporting services, you’ll hit an error like:

Failed to establish connection with report server. Verify the server URL is correct or review ULS logs for more information. Product area: SQL Server Reporting Services, Category: Configuration Pages

and, in the ULS logs, an error like:

SQL Server Reporting Services Configuration Pages Failed to retrieve RS configuration information: System.Net.WebException: The request failed with HTTP status 401: Unauthorized.

Here’s how I fixed it my workaround.

(more…)