There have been several reports of users experiencing an error when creating a view with an out the box SharePoint 2013 Team Site.
Requests made via a load balancer that strips out the Accept-Encoding header cause an error creating a view on a SharePoint 2013 site with MDS activated.
My current environment is SharePoint 2013 with up to the August 2013 CU applied, on a Windows 2012 server, and I too had reports from users that when they were creating a view on a document library that they would see a page with the details:
Cannot complete this action.
Please try again.
Troubleshoot issues with Microsoft SharePoint Foundation.
GO BACK TO SITE
The view was created successfully, but the user is presented with this error page and that is not something we want to be seeing.
Of interest here is that the url of the page ends with (more on this later) and the fact there is no correlation id presented either:
A SharePoint 2013 Team Site has the MDS (Minimal Download Strategy) feature enabled by default, and I had read that with the MDS feature deactivated that the creation of a view would succeed. So to test I created a simple team site, tried creating a view on the Documents library. Was presented with the error as above. I then deactivated the MDS feature on the site, tried creating the view and this time it succeeded.
So, we have a scenario where it appears that deactivating the MDS feature removes the error from creating a view. I was not satisfied with this as the MDS feature is not something I think we should just deactivate, and so started down a route to see if there was any errors reported on the server.
In our environment we use a load balancer in front of SharePoint (F5 BigIP version 11.3.0 build 3144.0 Hotfix HF8) so the first thing I wanted to do is to point my browser directly at a specific SharePoint server so I examine the logs on that server.
So I modified my local HOSTS file to point my SharePoint hostnames directly at a server, bypassing the load balancer. And…I no longer experienced the error!
So, it would appear that the load balancer was “getting in the way” of the request to create a view. The next thing I did was fire up fiddler and execute a request first via the load balancer (and therefore see an error) and then a request bypassing the load balancer (with no error) and examine the raw request and responses.
The key request to examine was the POST request to the endpoint:
Both the request and response bodies were almost identical, but for the request via the load balancer fiddler in fact reported a protocol violation. Further examination of the response , the response headers for the load balancer seemed strange, the header:
Was causing the protocol violation as the response does in fact have a body. Of note here is that the response code with MDS activated is a 200 with a response body containing some | separated values including the view page url to redirect to.
The scenario mentioned earlier where we deactivate the MDS feature and create a view with no error, the fiddler trace shows that the POST request to owssvr.dll is met with a 302 redirect response (so the code path inside the owssvr.dll must choose a different response type based on the fact that is has received a MDS request.) All MDS requests have an HTTP form variable:
This must be used by the code path inside owssvr.dll to decide if the response code is a 200 with a response body, or a 302 with no response body (more on this at the end of this article).
Now, from what I can tell the fact that the response contains a Content-Length: 0 header I’m guessing the client side code on the browser “gets it’s knickers in a twist” as we would say in Scotland. And that is why the user is presented with an error as the browser then attempts to make subsequent incorrect requests (the subsequent incorrect requests are not the issue, it’s the response to the POST to the owssvr.dll that is the issue).
I then went to our load balancer team and we setup a temporary load balancer configuration where the load balancer would only target one server (just to isolate out the investigation of log files to one server only).
On the single server that the load balancer was pointing to I started wireshark to capture the incoming requests. I then repeated my earlier set of steps: make a request to the server directly by bypassing the load balancer (no error) and make a request via the load balancer (see an error). I then started to examine the request as captured by wireshark to compare both.
The difference between the requests was as follows, for the POST to owssvr.dll the request that bypassed the load balancer had the following header:
Accept-Encoding: gzip, deflate
The request sent via the load balancer did not have this header. Of note here is earlier when I was examining the requests via fiddler the Accept-Encoding header was present in both, so it would appear that the load balancer is removing the Acccept-Encoding header.
We then proceeded to look at the load balancer configuration and lo and behold there is a setting:
Keep Accept Encoding
And this request was disabled (and from what I understand is the default setting) so the Accept-Encoding header is not sent on by the load balancer.
We then enabled the Keep Accept Encoding header and re-tested – and this time creating a view with MDS enabled and going via the load balancer succeeded.
Further examination of the headers in fiddler and wireshark showed that the Accept-Encoding header was sent through as part of the request and that the Content-Length header is returned with the correct value.
So this would appear to be a bug in the code for owssvr.dll, specifically concerning the fact that there is no Accept-Encoding header present for the code path that handles the MDS requests. It would appear that the owssvr.dll response to a request with no Accept-Encoding header is to send back a Content-Length: 0 header, even though it does in fact send back a response body.
At the browser end of things, I can only assume that the low level error handing in the XMLHttpRequest object (MDS makes use of XMLHttpRequest to make server side calls) has found a Content-Length: 0 header and this does not match up with the fact that there is actually a response body and it then tries to make the request again using an HTTP GET to owssvr.dll which the server responds to with an error.
Going back to the start of the article, my current patch level is August 2013 CU, we do have a plan to apply SP1 but just not gotten around to this.
Would be useful to know if anyone else has experienced the same issue with SP1 applied.