- First we need to open up SharePoint 2010 Management Shell (in Start Menu )
- Type something like the following to export your site.
PS> Export-SPWeb https://mysp/abc -Path "c:\temp\abc.cmp" -IncludeUserSecurity -IncludeVersions all
This will create a file at c:\temp\abc.cmp - Move the file to the new server. For example you can move it from DEV to Production.
- (Optional) Go to new server and open up SharePoint 2010 Management Shell (in Start Menu)
- Create a subsite at the desired destination url. You MUST use the SAME template that the source site uses. This is the url where you will replace with what you previously backed up. If you try to restore without an existing url it will give you an error.
- Type something like the following to import your site to the path specified.
- PS> Import-SPWeb http://mysp2/abc2 -Path "c:\temp\abc.cmp" -UpdateVersions Overwrite -IncludeUserSecurity
This will replace the site at the url http://mysp2/abc2 with the site that we backed up earlier to c:\temp\abc.cmp
Monday, December 2, 2013
Moving a SharePoint site (not site collection), list, or library from DEV to Production
Wednesday, November 20, 2013
Permission issue with subsite when using FBA with SharePoint
The problem is that the Master Page Gallery for the site collection needs to have the permissions changed. You can verify that this is the problem by
- Navigate to your Master Page Gallery (http://yourSPhostHere/_catalogs/masterpage/Forms/AllItems.aspx).
- Once there you can get permissions on that library. Next Click the Check Permissions button and enter the user that is being denied access. If you see that they don't have access then this is likely your problem.
The solution is simple. From the permissions for the Master Page Gallery do the following:
- Click the Grant Permissions button.
- For Users/Groups textfield enter: All Authenticated Users
- For Grant Permissions select Add users to a SharePoint group (recommended)
- Select Style Resource Readers from the drop down list.
- Click the OK button.
- Try to login again. This time it should work.
Tuesday, September 10, 2013
SSRS in SharePoint integration mode gets HTTP status 401: Unauthorized error on only one server
Exception encountered for SOAP method GetSystemProperties: System.Net.WebException: The request failed with HTTP status 401: Unauthorized. at Microsoft.SqlServer.ReportingServices2010.RSConnection2010.SetConnectionProtocol() at Microsoft.SqlServer.ReportingServices2010.RSConnection2010.SoapMethodWrapper`1.ExecuteMethod(Boolean setConnectionProtocol)
System.Net.WebException: The request failed with HTTP status 401: Unauthorized. at Microsoft.ReportingServices.SharePoint.UI.RSConnectionInfo.get_SPManagementProxy() at Microsoft.ReportingServices.SharePoint.UI.RSItemPickerNavigator.ListParents(String item) at Microsoft.ReportingServices.SharePoint.UI.RSItemPickerNavigator.GetParentItemUrl(String enumerableLocation) at Microsoft.ReportingServices.SharePoint.UI.ItemSelectorDialogControl.ValidatePath(String unvalidatedPath, Boolean useFallbackPath, String& itemPathParent, String& itemPathGrandparent, String& invalidReason) at Microsoft.ReportingServices.SharePoint.UI.ItemSelectorDialogControl.OnPreRender(EventArgs e) at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Control.PreRenderRecursiveInternal() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
If I use a url that goes directly to one of the servers, I soon see that predictably I get the error for only one of the servers. How weird. I also found that if I add the Reporting Services web part to a page and then try to select a report I get the same error. The good thing is that I then got a correlation id which I could then use to find the exact error in the SharePoint logs.
So I verified a bunch of things:
- Changed Reporting Services to be a single server deployment instead of a scaled out deployment (just to make things easier to troubleshoot).
- The patch level is the same for the servers
- The files are identical on both servers
- Tried using the IP address of the reporting server instead of the host name in Central Admin | Reporting Services Integration | Report Server Web Service URL.
- Changing logging in Reporting Services to verbose. Click here for instructions.
- Disable loopback check. Click here for instructions and security risks.
- Selected Authentication Mode to Trusted Account in Central Admin | Reporting Services Integration | Authentication Mode. I was using a service account before that.
I believe the last thing I tried was the key change that solved it, but the other items could also have helped (though it never worked until I made the last change).
Lots of docs I read through to try to figure out what was wrong. If the above doesn't work, you may want to start with one of the links below.
- The one stop shop for FIXING your Reporting Service's Issues
- Configuring Reporting Services for SharePoint 2010 Integration
- Server Deployment Checklist
- How Do I learn About SharePoint Integrated Mode
- Storing and Synchronizing Report Server Content With SharePoint Databases
- Troubleshooting Configuration Problems
- Security Overview for Reporting Services in SharePoint Integrated Mode
- How to: Install and Configure SharePoint Integration on Multiple Servers
- Deployment Topologies for Reporting Services in SharePoint Integrated Mode
- Granting Permissions on Report Server Items on a SharePoint Site
- How to: Set Permissions for Report Server Items on a SharePoint Site (Reporting Services in SharePoint Integrated Mode)
- How to: Configure a Report Server on a Network Load Balancing Cluster
- Reporting Services Log Files
- Reporting Services SharePoint Integration Troubleshooting
- How to: Configure Report Server Integration in SharePoint Central Administration
- Configuring the Report Server Service Account
- Integrating SharePoint 2010 and SQL Reporting Services 2008 in 6 easy steps
- SharePoint 2010 & SQL 2008 Reporting Services Integration (forum question)
- Error message when you try to access a server locally by using its FQDN or its CNAME alias after you install Windows Server 2003 Service Pack 1: "Access denied" or "No network provider accepted the given network path"
- Recommended configuration for Verbose Logging in Reporting Services
Wednesday, September 4, 2013
Creating a FBA (Forms Based Authentication) (Extranet) site in SharePoint 2010
You can use FBA (Forms Based Authentication) and still use Active Directory as the security store to query, but in my case I didn't want to do that either because there were some domain trust issues. Also, it made provisioning new users for the extranet more difficult. The ideal solution I chose was using ASP.NET Membership provider that can be used in any ASP.NET application. Mainly because it is standard and SharePoint supports it, and others have already used it.
Unfortunately, doing all this is not trivial and is actually quite tedious. Fortunately, many people have done this with some variation.
I looked at several sites that showed how to do this to varying levels of detail. I found this one that showed lots of details, screenshots, and explained why in many cases. I did learn some things along the way that were not explicitly noted.
- When creating the ASP.NET database, use the farm service account or whatever you run the application pools as. This will guarantee that the service account has access to the database. This was important to me since I didn't have direct access to my SQL Server. Alternatively, you can do it like the article describes as well. The reason is I needed to use Windows Integrated Security to connect to my SQL Server database. This can be easy if the Service account can RDP to a server, but if the user can't (like my scenario) then you need to run the aspnet_regsql.exe as the service account. To do that, do the following:1. Open a command prompt by right-clicking on it and choosing Run as Administrator2. At the command prompt type
This will give you a command prompt running under the service account (mine is called SPServiceUser in this example). Now you can do whatever you want as that user.runas /user:SPServiceUser cmd.exe
3. In this case, we want to run aspnet_regsql.exe, so do something like:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe - When it came to the SecurityTokenServiceApplication, I didn't have much luck with the default providers being set the way the author suggested. I changed removed the defaultProviders Attribute for roleManager and membership tags. New Default could be FBA,FBARoles, but the CA user look test (later in this doc) only seems to work with c,I as defaults. Curious if others have the same issue.
- You will need to make these changes on each node in the SharePoint web farm, probably want to just copy the web.config files from server to server. If you aren't sure if the corresponding web.configs on each server is the same, then maybe just copy the key parts outlined in my diagram. I was surprised my web.configs had variations from server to server. I don't think they should be though.
Once you are all done, you will likely realize that you have no way to manage users yet. A good choice for adding this functionality to the Site Settings of SharePoint 2010 is SharePoint 2010 FBA Pack. I have tried it (password change and reset, add, edit, delete users manually) and found that it works well. I am not letting users request access to the site, so I didn't try that functionality.
Other things I tried
I ran into trouble trying to extend an existing web application and have FBA on one url and Windows Authentication on another url. I was able to get a single site to have both FBA and Windows Authentication, but we didn't want the users to have to decide if they were FBAor Windows Authentication. I also tried converting an existing site using Powershell, but I didn't have much luck with that either. In the end, it was best to just create a site that only used FBA.
If you are doing the same thing for SharePoint 2013, you may want to look at this one. I haven't studied it in detail,but it looks like it is good. From what I remember reading, the configuration is basically the same, but IIS doesn't support adding the users so you have to do it another way.
The key links you need in one place:
Step by Step Instructions
My Visual Summary and Web.Config examples
Add FBA User and Role management to SharePoint 2010
A good place to start if you are using SharePoint 2013 instead of 2010
Tuesday, August 27, 2013
Troubleshooting Reporting Services Access Denied Error when using Forms Based Authentication (FBA) in SharePoint 2010
The Solution
- In Central Administration| Reporting Services | Reporting Services Integration| Clicked Activate feature in all existing site collections and then the OK button.
- In Central Administration| Reporting Services |Add a Report Server to the Integration changed Server Name to a wrong value then changed back to the server name where Reporting Services is installed. Click OK after each change. When prompted for credentials I entered the farm service account and password.
- I tried the report and it worked. I’m not sure exactly which step fixed it, but it works now.
Some other things to try if it still doesn't work:
Wednesday, August 14, 2013
How to copy a SharePoint SiteCollection to a new server
Here are the steps
- Backup the site collection
You can use Central Administration | Backup and Restore | Perform a site collection backup. You can use a UNC share path or you can specify a local disk path.
Alternatively, you can use Powershell to do the backup as well.
PS> Backup-SPSite "http://yourSPServerHere/sites/siteCollection1" -Path "C:\temp\siteCollection1.bak" - Copy the backup file to the new server or use a file share that both server can access to avoid copying the backup file. In this example, I kept the same path on the local disk for ease of syntax.
- Restore the site collection at a desired url
PS> Restore-SPSite "http://yourNewSPServerHere/sites/siteCollection1" -Path "C:\temp\siteCollection1.bak"
NOTE: Unfortunately, there is ability to do this in Central Administration like there is for the backup.
Also, notice I kept the same basic url (minus the server change)
Troubleshooting Powershell
If you get an error like the following:The local farm is not accessible. Cmdlets with FeatureDependencyId are not registered.
Check here for details on how you can get access.
Patching or Updating SharePoint 2010 is a two step process
- Open an Administrative command prompt.
- cd C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\BIN
- Run PSConfig.exe -cmd upgrade -inplace b2b -force -cmd applicationcontent -install -cmd installfeatures
For more details, check out this blog. I summarized some key info from it:
Tuesday, August 13, 2013
Troubleshooting: Cannot start service SPAdminV4 on computer
- In Registry Editor, locate, and then right-click the following registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
- Point to New, and then click DWORD Value. In the right pane of Registry Editor, notice that New Value #1 (the name of a new registry entry) is selected for editing.
- Type ServicesPipeTimeout to replace New Value #1, and then press ENTER.
- Right-click the ServicesPipeTimeout registry entry that you created in step c, and then click Modify. The Edit DWORD Value dialog box appears.
- In the Value data text box, type TimeoutPeriod, and then click OK
Note TimeoutPeriod is a placeholder for the value of the time-out period (in milliseconds) that you want to set for the service. For example, if you want to set the time-out period to 24 hours (86400000 milliseconds), type 86400000. - Restart the computer. You must restart the computer for Service Control Manager to apply this change.
- Alter the computer policy
- Click on Start-Run
- Type in "GPEdit.msc" and click "OK"
- Expand Computer Configuration-Windows Settings-Security Settings-Public Key Policies
- Double-click "Certificate Path Validation Settings"
- Click on the "Network Retrieval" tab
- Check the box "Define these policy settings"
- Uncheck "Automatically update certificates in the Microsoft Root Certificate Program (recommended)" and uncheck "Allow issuer certificate (AIA) retrieval during path validation (recommended"
- Click on "OK"
- Close out of GPEdit.msc
- Click on Start-Run
- Add host file entries
- Click on Start-Run
- Type in "C:\Windows\System32\Drivers\Etc" and click "OK"
- Double-click the file "Hosts"
- Select "Notepad" as the program to open the file
- Insert the following lines into the hosts file
- 0.0.0.0 crl.microsoft.com
- 0.0.0.0 crl.verisign.com
- 0.0.0.0 ocsp.verisign.com
- 0.0.0.0 SVRSecure-G2-crl.verisign.com
- 0.0.0.0 SVRSecure-G3-crl.verisign.com
- 0.0.0.0 www.download.windowsupdate.com
- 0.0.0.0 SVRSecure-G2-aia.verisign.com
- 0.0.0.0 crl.microsoft.com
- Save the file and exit notepad
- Click on Start-Run
Monday, August 5, 2013
List of Best Practices for C# and SharePoint development
Thursday, July 25, 2013
Convert existing SharePoint Web Application from Classic Mode Authentication to Claims based Authentication
- Open SharePoint Management Shell by going to Start Menu | All Programs | Microsoft SharePoint 2010 Products. Now right-click SharePoint 2010 Management Shell and choose Run as administrator.
- Now go the following Powershell commands:
PS> $app = Get-SPWebApplication "http://yourSpHost:7777"
PS> $app.UseClaimsAuthentication = "True"
PS> $app.Update() - To verify the change: Go to Central Administration | Manage web applications, and select the application you modified.
- Click the Authentication Providers button in the Web Applications ribbon. It will now show Claims Based Authentication.
NOTE: if you get the error: "The local farm is not accessible. Cmdlets with FeatureDependencyId are not registered." try some of my fixes outlined here
Resolving: The local farm is not accessible. Cmdlets with FeatureDependencyId are not registered.
The local farm is not accessible. Cmdlets with FeatureDependencyId are not registered.
Things to try.
1. Make sure you run the command as Administrator. For example, Go to Start Menu | All Programs | Microsoft SharePoint 2010 Products. Now right-click SharePoint 2010 Management Shell and choose Run as administrator.
2. If that doesn't work then it is likely you don't have access to the SharePoint configuration database. On solution would be to grant your users access to the configuration database, but that probably is not the best plan.
3. A better option is use a user that does have rights to the configuration database. This is often a SharePoint service account. If that service account has RDP access you one of your SharePoint front end servers then login as that service account and execute the command. If you want to be able to execute it with your specific account, then we need to do some more things. You can do the same thing as #1 to bring up the SharePoint 2010 Management Shell, and then execute
powershell prompt>Add-SPShellAdmin -UserName yourdomain\yourusername
This should make it so your specific user can now do #1.
If the SharePoint service account does NOT have RDP access then things are a bit trickier. In that case, follow these instructions:
- RDP to the SharePoint server using an account (usually in the adminstrators group in Windows) that can execute RunAs command.
- Go to Start Menu | All Programs | Accessories. Then righ-click on the Command Prompt item and select Run as administrator.
- Now we need to open the PowerShell prompt as the SharePoint service account. To do this, do the following command:
cmd promopt>runas /user:yourdomain\yourusername C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe - Type whoami at the prompt to verify that you are indeed the service account.
- At this point we have a standard Powershell prompt, but it doesn't know about SharePoint, so we need to add it. Use the following command to do so:
powershell prompt>Add-PSSnapin Microsoft.SharePoint.Powershell - Now you should be able to grant your specific user rights to use SharePoint powershell commandlets. To do so, use the following command:
powershell prompt>Add-SPShellAdmin -UserName yourdomain\yourUserName - Now you should be able to use method #1 with your specific user and not have to do all this fancy stuff everytime.
Monday, June 24, 2013
Hide Columns in a SharePoint list based on SharePoint group
I am working on an internal instance of SharePoint 2010 and simply hiding the data on the forms using CSS is sufficient because the user would have to look in the source of the page to see the data.
WARNING:
Note: This is NOT a true security solution! All data (even for hidden columns) is sent to the browser, but is just hidden from user's view in the browser.
In my case, it would not be the end of the world if users viewed source to see all the data. We are all part of the same company after all. If this is your scenario, then you may want to consider the solution outlined below.
My solution uses a JavaScript library called SPUtility.js. It makes hide and showing a field simple. It also makes changing a field to readonly simple as well. I can't take credit for the library, but I am very happy I found it. The only problem left to solve was how to get the current user and the groups that the user is in. This is something I had to come up with. It requires CSOM (Client Side Object Model) which requires SharePoint 2010 or later. I read that you can use SPServices if you are using MOSS 2007, but I have not tried to do it.
To implement the functionality to get user and group information, I wrote the following methods.
You can download the source here.
function getCurrentUserObject(callbackFunc)
function isCurrentUserInSharePointGroup(sharePointGroupID, callbackFunc)
function isUserInSharePointGroup(userLogin, sharePointGroupID, callbackFunc)
CSOM uses asynchronous calls for everything which makes it difficult to code if you are not accustomed to it. The good news is all you have to do is provide the callback function to make use of these functions. While that may sound difficult, just follow the example I have provided. In the example code the first thing it does is make sure the CSOM library (sp.js) is loaded and then executes our code. It takes the approach of getting the current user then seeing if the user is in the owner group and setting column visibility appropriately. If the user is not in the owner group it then looks in the members group and sets the column visibility appropriately. If they are not in either of those groups it sets the column visibility appropriately. You could continue on with different checks if desired.
Here is a snippet of what the solution code looks like:
function doOwnerChanges(userLogin, isInGroup)
{
if (isInGroup)
{
SPUtility.GetSPField('Title').Show();
SPUtility.GetSPField('Cost').Show();
SPUtility.GetSPField('Customer Comment').Show();
SPUtility.GetSPField('Assigned To').Show();
SPUtility.GetSPField('Internal Comments').Show();
}
else // not in owner group let's see if they are in members group
{
isUserInSharePointGroup(userLogin, 7, Function.createDelegate(this, this.doMemberChanges));
}
}
As you can see it is easy to maintain because all the complexity is abstracted away. If another column is added you would just add a line to the above code.
Added solution to your page
- Download the following:
- SPUserGroupUtility.js My code that gets the current user and checks the groups the user is in.
- ShowHideColumnExample.js (only needed if you want an example of how to use this solution). You can replace or not use this in your specific implementation. This is the file you will need to specify your columns. The name is not important except that you reference it later.
- SPUtility.js This provides the functionality for hide/showing fields and making them readonly, etc.
- Prototype.js Required by SPUtility.js.
- sp.js - actually you don't need to download it. Ultimately, this is the CSOM library. It is provided by SharePoint 2010. Just use it in your code as needed.
- Upload the .js file to somewhere on SharePoint where all users can access the files. I recommend installing your .js file in your Site Assets directory on your site. You can find it by going to Site Action | View All Site Content | Site Assets.
- Navigate to form (EditForm.aspx or NewForm.aspx)
In SharePoint 2010, you can choose Form Web Parts -> Default whatever Form - Add a Content Editor Web Part to the page
- Edit the web part
In SharePoint 2010, click the arrow -> Edit Web Part. - Edit the content editor's HTML to add some JavaScript
In SharePoint 2010, under Editing Tools -> Format Text click the HTML button -> Edit HTML Source - Follow the instructions on installing the SPUtility.js
- <script src="/sites/someSite/SiteAssets/prototype.js" type="text/javascript"></script>
<script src="/sites/someSite/SiteAssets/SPUtility.js" type="text/javascript"></script>
<script src="/sites/someSite/SiteAssets/ShowHideColumnExample.js" type="text/javascript"></script>
<script src="/sites/Brent/SiteAssets/SPUserGroupUtility.js" type="text/javascript"></script> - Save the page / stop editing.
Troubleshooting
- NOTE: To just try SPUtility.js you can try the install instructions.
- If nothing happens on the page, make sure you don't have any errors. You may need to do an F12 in IE to see the error console. Also, you can look at the F121 | Network tab to see if the JavaScript files are able to be found.
- You can always start the JavaScript debugger and see where it is breaking.
Wednesday, May 15, 2013
Link on reporting service
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
Timestamp: Wed, 15 May 2013 22:03:02 UTC
Message: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near '
Line: 5
Char: 62099
Code: 0
The cause for me was the following
The Problem:
I have reporting services installed in SharePoint 201 SP1. I have two reports and they both take parameters. The main report has parameters that use the parameter panel and the user specifies the parameters they want. The second report uses the parameter panel, but it should not since it is taking the parameters from a link on the main report that passes the parameter to the second report. Only one report can use the panel. The Back to the Parent Report link in Reporting Services doesn’t seem to support the scenario where both reports are using the parameter panel.
To reproduce the problem, I did the following.
1. Bring up the main report and run with some parameters.
2. Click the link that takes me to the secondary report.
3. Click the Back to the Parent Report button.
4. Click the link that takes me to the secondary report
This time, the screen redraws and I get the above JavaScript error.
The Solution:
Change the parameter type on the second report to be Hidden. This will cause the parameter to not be shown in the UI when the second report is shown. This will fix the problem. Another solution is for the main report to not have any parameters, but that is usually not feasible since users typically will need to interact with it.
To change the parameter to Hidden do the following:
1. Open the report in Report Builder
2. Go to Report Data |
Parameters and expand the list of parameters
3. Right-click on each of the parameters and do the following
4. Select the Parameter Properties menu item.
5. Under the General tab change the Select parameter visibility radio button to Hidden.
Tuesday, March 26, 2013
Uploading large files to SharePoint Online (O365)
It seems amazing to me that Microsoft did such a poor job of giving developers a good way to upload large documents to Microsoft SharePoint Online (aka Office 365 or SharePoint 365). Ideally I would like to use the
Microsoft.SharePoint.Client.File.SaveBinaryDirect
method that is part of the CSOM (Client Side Object Model), but this does not work with SharePoint Online and only seems to work on SharePoint 2010 (probably 2013, but have not tested). I did get
Microsoft.SharePoint.Client.File uploadedFile = docLib.RootFolder.Files.Add(newFileFromComputer);
to work on SharePoint Online, but it not very useful because it is limited to files of about 3MB in size.
After lots of trial and error, I figured out that the most reliable was to do it is using a standard PUT request and passing the Claims Authentication cookies that are required to make most any request to SharePoint Online. This works well unless you are debugging and you still have the default exception warning enabled. In that case, for large files that take more than 60 seconds to upload you will get a message similar to this:
The CLR has been unable to transition from COM context 0x1fe458 to COM context 0x1fe5c8 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.
Depending on what you are doing this may be okay. In my case, I don’t care if my command line application waits for a long request to continue. This is caused by using the STA threading attribute on the main method of the application.
Below are two methods (one just an overload that calls the other basically) that upload a document to a shared library in SharePoint Online. It should also work on SharePoint 2010 plus if you replace the ClaimClientContext with a standard ClientContext that is needed for SharePoint 2010+. I’ll leave that to you to try on your own for now. You’ll notice I have also added functionality to change the created and modified date of the files after they are uploaded. For details (and source code click here). Or if you just want to understand more about Claims based authentication, sample code, options, etc definitely check out here.Lastly, the keyValues dictionary is just a dictionary of actual internal field names (see CAML field names) as keys and the values for each field are the values of the dictionary.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Client;
using MSDN.Samples.ClaimsAuth;
using System.Xml.Linq;
using System.Net;
using System.IO;
...
public static void AddDocument(string fileToUpload, string webUrl, string docLibInternalName, string docLibUIName, string documentSetName, string filenameToSaveAs, DateTime? createdDate, DateTime? modifiedDate, Dictionary<string, object> keyValues, int timeoutInMilliseconds)
{
string urlToSaveAs = webUrl + "/" + docLibInternalName + "/" + documentSetName + "/" + filenameToSaveAs;
AddDocument(fileToUpload, webUrl, urlToSaveAs, createdDate, modifiedDate, keyValues, timeoutInMilliseconds);
}
// Uploads most any size file to SharePoint Online (O365) using Claims Authentication. It does NOT use CSOM, and instead uses a standard PUT request
// that has the cookies from the Claims based authentication added to it.
// This solution is based on http://stackoverflow.com/questions/15077305/uploading-large-files-to-sharepoint-365
// and
// To get the claims authentiation cookie, this solution requires: http://msdn.microsoft.com/en-us/library/hh147177.aspx#SPO_RA_Introduction
// or if you want to get the cookies for claims authentication antoher way, you can use
// http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspx
public static void AddDocument(string fileToUpload, string webUrl, string urlToSaveAs, DateTime? createdDate, DateTime? modifiedDate, Dictionary<string, object> keyValues, int timeoutInMilliseconds)
{
//For example: byte[] data = System.IO.File.ReadAllBytes(@"C:\Users\me\Desktop\test.txt");
byte[] data = System.IO.File.ReadAllBytes(fileToUpload);
// get the cookies from the Claims based authentication and add it to the cookie container that we will then pass to the request
CookieCollection cookies = ClaimClientContext.GetAuthenticatedCookies(webUrl, 200, 200);
CookieContainer cookieContainer = new CookieContainer();
cookieContainer.Add(cookies);
// make a standard PUT request
System.Net.ServicePointManager.Expect100Continue = false;
HttpWebRequest request = HttpWebRequest.Create(urlToSaveAs) as HttpWebRequest;
request.Method = "PUT";
request.Accept = "*/*";
request.ContentType = "multipart/form-data; charset=utf-8";
request.CookieContainer = cookieContainer;
request.AllowAutoRedirect = false;
request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
request.Headers.Add("Accept-Language", "en-us");
request.Headers.Add("Translate", "F");
request.Headers.Add("Cache-Control", "no-cache");
request.ContentLength = data.Length;
request.ReadWriteTimeout = timeoutInMilliseconds;
request.Timeout = timeoutInMilliseconds;
using (Stream req = request.GetRequestStream())
{
req.ReadTimeout = timeoutInMilliseconds;
req.WriteTimeout = timeoutInMilliseconds;
req.Write(data, 0, data.Length);
}
// get the response back
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
Stream res = response.GetResponseStream();
using (StreamReader rdr = new StreamReader(res))
{
string rawResponse = rdr.ReadToEnd();
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (response != null)
{
response.Close();
}
}
// NOTE: the file that was uploaded is still checked out and must be checked in before it will be available to others.
// The method includes a checkin command. If the method below is removed for some reason,
// a checkin method call should be added here so that the file will be available to all (that have access).
// NOTE: The method calls add keyValues passed in as well. These would need to be done also if the method is removed.
UriBuilder urlBuilder = new UriBuilder(urlToSaveAs);
string serverRelativeUrlToSaveAs = urlBuilder.Path;
ChangeCreatedModifiedInfo(webUrl, serverRelativeUrlToSaveAs, createdDate, modifiedDate, keyValues);
}
…
Monday, February 25, 2013
Get all sites in a SharePoint web application using PowerShell
I realize the title of this entry is ambiguous. Specifically, you might be wondering if I mean site or site collection. The answer is: Yes. To make it less ambiguous, I will be referring to how things are in code, not the UI. The difference is that in code SPSite is actually a Site Collection (in the UI) and in code SPWeb is actually a Site (in the UI). The hierarchy of objects goes: SPWebApplication | SPSite | SPWeb where SPWebApplication and SPSite have Collection of the other objects below them. Below are example of how to get both SPSites and SPWebs.
Get number of SPWebs in your web application
$allwebs = Get-SPWebApplication http://www.sharepoint.com | Get-SPSite -Limit All | Get-SPWeb -Limit All
$allwebs.Count
Get urls of all the SPWebs in your web application
Get-SPWebApplication http://www.sharepoint.com | Get-SPSite -Limit All | Get-SPWeb -Limit All | select Url
Get number of SPSites in your web application
$allwebs = Get-SPWebApplication http://www.sharepoint.com | Get-SPSite -Limit All | Get-SPWeb -Limit All
$allwebs.Count
Get urls of all the SPSites in your web application
Get-SPWebApplication http://www.sharepoint.com | Get-SPSite -Limit All | Get-SPWeb -Limit All | select Url
Wednesday, January 16, 2013
Troubleshooting STSADM Command Line Error message
The stsadm.exe that is used to administer SharePoint has terrible error handling. The only error message it seems to ever give when there is something wrong with the syntax is Command Line Error. If you get the syntax then you can get better error messages.
I checked, there is nothing in the Event Log, or any other SharePoint logs that I am aware of. So, what can you do?
Here are the basic things I would check when you get the dreaded Command Line Error from stsadm.exe.
- Make sure you spelled everything correctly
- Make sure you didn’t forget any parameters
- Make sure you didn’t forget the –o
- Check for extra or missing spaces
If you copied the code from anywhere (especially a web page, or MS Word or Word Pad or Outlook) here are some additional things. Rich text editors such as MS Word and web pages often try to “help” you by using proper typographical characters. The problem is they are not what you want to use for command line or coding in general. I have listed the special characters that often fall into this category and should be checked
- Use hyphens, not En Dash or Em Dash. For details on the differences, see here.
- Use double quotes, not smart quotes, curved, slanted, etc. For details on the differences, see here.
- Use single quotes, not smart quotes, curved, slanted, etc. For details on the differences, see here.
Don’t be fooled, sometimes you can’t visibly see the difference in Notepad or the like. They are valid characters so Notepad will still display them just fine. One way I know to fix the problem is to go and do a search and replace or manually retype all the suspected characters over to make sure they are right.
How to remove a user from the People Picker in SharePoint
The People Picker in SharePoint is quite clever and confusing. The reason is that it brings in results from more than one source.
It pulls information from:
- The Site Collection User Information List (UIL)
- The Profile Database (User Profile Service Application)
- Active Directory
So, the only way to remove a user from the People Picker is to make sure you have removed them from all 3 locations. Let’s start at the bottom of the list. Active Directory is usually where users are deleted from first. You can delete the users from the Profile Database using the Central Administration UI for the User Profiles Application.
Most people expect that they would not show up in SharePoint anymore, but that is not the case because once a user accesses a site collection in SharePoint they are added to the UIL (User Information List). This is basically a list of users that have accessed SharePoint that the People Picker also uses also. You will need to remove them from the UIL if you don’t want them to show in the People Picker. To do that you can check out an excellent post here that tells you how to do it using PowerShell or using the UIL interface. The UI is hidden, but can easily be located by going to the root of your SharePoint installation and appending _catalogs/users/simple.aspx. An example would be http://mysp/_catalogs/users/simple.aspx. The UI is ok if you don’t have a lot of users, but if you do, paging through results can be very time consuming. In that case, I would recommend the PowerShell route.
Wednesday, August 22, 2012
Q&A on SharePoint Architect from MetaVis Technologies
Below are answers (in my own words and some of my own commentary) I got from a Q&A meeting with MetaVis Technologies on their SharePoint migration tooling called Architect Suite. They recommend their Architect Suite and the questions are answered based on the assumption that is the tool you will be using. However, depending on your needs some of the individual products in that suite can be purchased instead.
Q: What are the limitations of this product
A: The following are not supported:
· Highly customized look and feels
· Copying of assemblies for web parts that are installed. This must be manually BEFORE the content is copied.
· Best to copy solutions to target before copy content.
· Many workflows are not supported, but no clear way to tell.
· Running workflows are not supported.
· Workflow history is not preserved.
· Can on preserve either Workflow Approval Status or Last Modified By, but not both.
· Users must be in both active directories, otherwise the current user will be used.
Q: Are OOTB workflows supported
A: It depends. If there are dependencies or customizations then no. We can try it and see if they work. The copying of workflows is not enabled by default. In most cases they recommend just recreating the workflows.
Q: What happens to workflows that are running?
A: Running workflows are not support. Workflows MUST be completed before they are copied.
Q: Is Workflow history kept?
A: No, no workflow history is kept.
Q: What is the copying of a workflow actually doing?
A: They are getting the xaml for the workflows and then replacing links in them.
Q: Where should I install the Metavis application?
A: The Metavis application should be installed close to the source or target system.
Q: What kind of performance can I expect from this application?
A: 250MB an hour is slow and up to 6GB is the fast. Multithreading is recommended. This varies greatly though based on structure, permissions, location, bandwidth, etc. For example, moving files is fast, but re-creating structure, permissions, etc takes longer.
Q: What is the recommended approach for migrating
A: Make sure all the users that you want to keep history for are in active directory in the source and target.
Make sure all workflows are completed or don't copy workflows.
Enable claims based authentication if needed for Office 354 SharePoint migration.
Use one of the three approaches for copying:
Use the UI provided by Metavis
This has the advantage of requiring no other tooling and is still fairly efficient. Its disadvantage is that you must be present each time new sites need to be selected.
- Take advantage of multi-threading.
- To do this create the top level sites on the target.
- Select a few sites at a time and start the copying.
- Repeat step 3 while taking care not to overwhelm any systems. Do this until all sites have been processed.
Script / Schedule the Migration
This has the advantage of being executed again easily and give you more control. Perhaps the biggest advantage of this is you can run with minimal interaction.
- Use the Metavis UI to migrate a site, but instead of executing, just generate the script. This script can be used on the command line, windows scheduler, etc.
- Copy the script, change the source and destination to match each site you want to migrate
- Execute the scripts in a parallel manner while taking care not to overwhelm any systems. Do this until all site have been processed.
Single-Threaded
This is the easiest because you just select all the sites and let it navigate the tree one site at a time. The downside is that it will take a lot longer to finish a large number of sites because it is only doing it one site at a time instead of in parallel as the other two approaches.
Test workflows that you may have copied. If they don't work, then re-create them.
Once everything is copied to the target have users do UAT to make sure everything is working ok. At this point keep the source system as the production one until UAT has finished. UAT will take some time. Don't expect everything to move over flawlessly, there will be issues in the beginning. Once everything looks good, go back and do an incremental copy from the source to the target system. No you can decommission the source system.
It is NOT recommended that you promise users that the system will be perfect on a given date. Plan to work with end users in UAT to solve issues. Once they have been solved it will be up to the users to start using the new system. This means that if you have a lot of users and sites you will likely have some users on the source system and some on the target system.
Q: Do site groups get copied over and over again
A: No they only get copied once, but there is a performance penalty the first time they are copied.
Q: There are a lot of settings on copy screen, should I just check everything.
A: No, the defaults are typically the best choice. Only change them if you know what they do (use the help icon near each option to better understand).
Q: How can script the migration
A: Use the UI and pretend like you are doing a migration using the UI. Before you get to the Finish / Execute step a button to generate a script will appear. Use that to generate a script you can use as a template for the other sites. You typically just need to change the source and target.
Q: Why aren't alerts copied by default?
A: Alerts are not copied by default, but you can enable them. Be careful though. The reason is that if you copy them when you are copying the site, the copying of the content will trigger alerts (lots of them). You can go back and copy the alerts after everything has been copied or you can leave it up to the end users to sign up for alerts again. Beware of copying alerts before you are sure you will not be doing any more incremental copies. Metavis recommends the later.
Q: How do I import data and metadata from other systems such as Lotus Notes, Alfresco, or even the file system?
A: In all cases, Metavis does not write custom connectors to different products. However, most products can be exported to the file system and the metadata put in CSV format. You can then drag and drop from the file system to the Metavis application. The application then allows you to map the metadata (including folder structure) to SharePoint. You can also map users, permissions, etc at this point.
Q: How can I keep history of users that are no longer with the company?
A: The users MUST be in the source and target active directory. If you are migrating to Office 365 SharePoint just be sure that these users are not assigned a license. You can mark them as disabled as well. Then you can map the usernames using the Metavis application.
Q: Can I expect 100% fidelity of my sites after a copy?
A: No, there are too many customizations that can be done to SharePoint to guarantee full fidelity copying. However, lists, calendars, master pages, permissions, users, groups, and most uncustomized functionality is copied without issue.
Q: Is there a way to compare two sites
A: Yes, the two provides a visual compare of two sites. Permissions can be ignored as well.
Q: In the trial version it is difficult to get my site to transfer all the files, how can I get the entire site copied.
A: The trial version will only copy the first 5 item in a list. You can go back and copy the ones that were missed. You can also use the compare features to see any differences. There are typically some hidden lists as well. If you right-click on lists you can choose to show hidden lists.
Q: Are there any tools to help migrate references in Outlook to SharePoint lists and calendars to the new locations after the migration?
A: Not that I am aware of, but a good place to start is Colligo.
Tuesday, August 14, 2012
Creating a more flexible master-detail layout in SharePoint 2010
In an earlier entry I gave instructions on how to easily create a master-detail layout in SharePoint 2010 using SharePoint Designer 2010. I found one limitation of it is that the initially selected item is always the first item in the topics list. Another one is that there is no way to link to the page with anything other than the first topic selected. To get past those short comings, it requires a little bit more of tweaking. Below is the updated instructions. I have copied the previous entry and modified it.
This assumes you have two Lists. One list is the lookup table (we’ll called it FAQTopics) that you want to group by. The other list is a table (I called it FAQ List) that has the rest of the data you want to display. In this scenario I want my lookup table to show on the left side of the screen and when I click one of the items on this table I want the list on the right to update and only show the rows that are in that match. In this case, the master is the FAQTopics list and the detail is the Topics list.- Create a new web part page
- Open SharePoint Designer 2010
- Go to Site Pages
- Click Web Part Page from the Pages ribbon and select the desired web part layout. Pick on that has at least a left and right web part area for our purposes since we want the list of topics on the left and the FAQs on the right.
- Rename the file as a desired. I called it FAQ.aspx
- Right-click new page and select Edit File in Advanced Mode.
- Add the FAQTopics to the page
- Click on one of the left web part zones
- Click the Insert ribbon and choose Empty Data View from the Data View button. This will create a DataFormWebPart. This will work best since it gives us access to the html directly and allows us to easily customize the selected row styles.
- Click the Click here to select a data source link in the middle of the DataFormWebPart and select FAQTopics (you may have called it something different). The screen won’t change much, but open the Data Sources Details panel (if it is not all ready visible). Here you will see a list of columns from the FAQTopics.
- Drag over the column you want to display in the FAQTopics list. In my case, I used Title. Please, note, this field should uniquely identify the row.
- On the Options ribbon, set any filters or sorting you may need by clicking the Filter and Sort & Group buttons.
- You can now test what we have done. Click the Home ribbon and then click the Preview in Browser button. This will open your page up in the browser. It should show a list of rows from your FAQTopics table.
- Add the FAQ List to the page
- Click on one of the right web part zones
- Click the Insert ribbon and choose FAQ List from the Data View button. This will create a XsltListViewWebPart. Note, we didn’t create an Empty Data View (like we did for the FAQTopics) and instead selected the FAQ List. This causes SharePoint Designer to use the default XsltListViewWebPart. You could use a DataFormWebPart like we did for the FAQTopics, but you may lose some functionality. For example, if you want to use the Rating stars to allow users to rate the FAQs, they don’t really work when you use the DataFormWebPart and instead you just get the number stored in the database. So, depending on your needs, pick the appropriate web part. The rest of the steps are the same regardless.
- You can now test what we have done. Click the Home ribbon and then click the Preview in Browser button. This will open your page up in the browser. It should show a list of rows from your FAQTopics table and also have the list of FAQs on the right side. They are independent of each other right now, but we’ll connect them next.
- Connect the two lists
- Right-click anywhere in the FAQTopics web part on the left and choose Add Connection.
- Choose Send Row of Data To (the default).
- Click the Next button.
- Click Connect to Web Part on this page (the default).
- Click the Next button.
- Choose FAQ List from the Target Web Part drop down list.
- Choose Get Filter Values From from the Target action drop down list.
- On the right set of columns (called Inputs to FAQ List) in the list of columns scroll down to the column you want to group by and will match the text in the FAQTopics. In my case the column is called Topic.
- Click the column (it shows as <none> initially) to the left of the Topic column. You will notice that <none> turns into a drop down list. Select the matching column from the list. In my case, I selected Title.
- Click the Next button.
- Select Title from the Create a hyperlink on drop down list.
- Check the Indicate current selection using checkbox.
- Click the Modify button and select the column that uniquely identifies the row. In my case, this is Title.
- Click the Next button.
- Click the Finish button.
- You can now test what we have done. Click the Home ribbon and then click the Preview in Browser button. This will open your page up in the browser. It should the two lists like before, except this time the first item in the FAQTopics (the one on the left) should be bold (the default style for the currently selected row). You can each row and the list on the right side (FAQ List) should update to show only the rows that match the selected FAQTopic.
- Add support for query string to Topics DataView
- Right-click on one of the DataViews and then choose Manage Connections.
- Remove the Connection we added earlier. We needed to add the connection in the first place so that it added support for current selected item.
- Select the Topic DataView
- Click the Parameters button and click the New Parameter button to create a new parameter called something like Topic.
- Change the Parameter Source drop down list to Query String.
- Enter Topic into the Query String textfield.
- For Default value, enter the topic you would like to be selected when the page loads for the first time or there is no topic specified in the url. For example, if you topics are Topic 1, Topic 2, Topic 3 and you would like Topic 2 to be selected by default then enter Topic 2. NOTE: You can change this in the future by selecting the DataView and then Parameters again.
- Make sure you have SharePoint Designer 2010 set to Split view so that you can see code and the Designer view at the same time.
- Click on one of the rows in your DataView. This will show something like this:
<td class="ms-vb">
<xsl:value-of select="@Title"/>
</td> - Replace or modify the snippet above to look like the following:
<td class="ms-vb" nowrap="nowrap" style="height: 23px">
<a target="_self">
<xsl:attribute name="href">
<xsl:text>?Topic=</xsl:text>
<xsl:value-of select="ddwrt:UrlEncode(string(@Title))"/>
</xsl:attribute> - Add support for query string to FAQ DataView
- Select the FAQ DataView
- Click the Filter button on the Data View Tools | Options ribbon.
- Select Topic from the Field Name drop down list.
- Select Create a New Parameter… from the drop down list.
- Change the Name of the parameter to Topic.
- Change the Parameter Source drop down list to Query String.
- Enter Topic into the Query String textfield.
- For Default value, enter the topic you would like to be selected when the page loads for the first time or there is no topic specified in the url. For example, if you topics are Topic 1, Topic 2, Topic 3 and you would like Topic 2 to be selected by default then enter Topic 2. NOTE: You can change this in the future by selecting the DataView and then Parameters again.
- Tweak the UI (optional)
- This step is totally optional if you are happy with the default styles, etc of the topics on the left.
- Do a search for bold in FAQ4.aspx. You will find a tag like this:
<xsl:attribute name="style">
<xsl:if test="$CurrentRowKey = $Topic">font-weight: bold;</xsl:if>
</xsl:attribute>
This adds the style=”font-weight:bold:” to the link tag. You can modify this or if you prefer, you can add a css class reference by adding the following lines after the lines for the style attribute.
<xsl:attribute name="class">
<xsl:if test="$CurrentRowKey = $Topic">selected</xsl:if>
</xsl:attribute>
In this case if the row is selected we the link tag to have class=”selected” to it. Then in your stylesheet you create a .selected style. The name (selected) is not important, but it does need to match what you have in your stylesheet.
<xsl:attribute name="style">
<xsl:if test="$CurrentRowKey = $Topic">font-weight: bold;</xsl:if>
</xsl:attribute>
<xsl:value-of select="@Title" />
</a>
</td>
NOTE: If you are showing a field different than Title you will need to change @Title to the name of your field. Also, if you name your parameter something other than Topic, you will need to change the $Topic to the name you used. If you typed something else in the Query String textfield you will need to change ?Topic to that as well. I have bolded each of the items you may need to replace depending on the values you entered in previous steps.
