This post is a contribution from Charls Tom Jacob, an engineer with the SharePoint Developer Support team.
Scenario:
You have a SharePoint library in which “Require documents to be checked out before they can be edited?” is set to Yes. You have a WorkflowStarting event receiver associated to the list, with the following very basic implementation:
public override void WorkflowStarting(SPWorkflowEventProperties properties)
{
SPList list = properties.ActivationProperties.List;
int id = properties.ActivationProperties.ItemId;
SPListItem currentitem = list.GetItemById(id);
}
Issue:
When the event receiver is triggered, the above code will fail with the following exception while getting the item:
ArgumentException was unhandled by user code: Item does not exist. It may have been deleted by another user.
at Microsoft.SharePoint.SPList.GetItemById(String strId, Int32 id, String strRootFolder, Boolean cacheRowsetAndId, String strViewFields, Boolean bDatesInUtc)
at Microsoft.SharePoint.SPList.GetItemById(Int32 id)
at WorkflowEventTest.EventReceiver1.EventReceiver1.WorkflowStarting(SPWorkflowEventProperties properties)
at Microsoft.SharePoint.Workflow.SPWorkflowEventManager.RunWorkflowEventReceiverHelper(Object receiver, SPUserCodeInfo userCodeInfo, Object properties, SPEventContext context, String receiverData)
at Microsoft.SharePoint.SPEventManager.<>c__DisplayClassc`1.<InvokeEventReceivers>b__6()
at Microsoft.SharePoint.SPSecurity.RunAsUser(SPUserToken userToken, Boolean bResetContext, WaitCallback code, Object param)
Reason:
When “Require documents to be checked out before they can be edited?” is set to Yes, the uploaded item gets exclusively checked out to the user who uploaded it. This means item won’t be viewable/accessible to ANY other user. This is because the workflow starting event is triggered way before the upload process is fully complete. When “Require documents to be checked out ” is Yes, user is presented with an additional page which says “The document was uploaded successfully and is checked out to you. Check that the fields below are correct and that all required fields are filled out. The file will not be accessible to other users until you check in.”
Event receiver executes while the user is presented with this popup screen, and it executes in the context of SHAREPOINT\SYSTEM account and runs into this error.
Solution: Impersonate the user account while accessing the list item.
base.WorkflowStarting(properties);
SPUserToken token = properties.ActivationProperties.Web.AllUsers[properties.ActivationProperties.Originator].UserToken;
SPSite site = new SPSite(properties.ActivationProperties.Web.Url, token);
SPWeb web = site.OpenWeb();
SPList list = web.Lists[properties.ActivationProperties.ListId];
SPListItem item = list.GetItemById(properties.ActivationProperties.ItemId);
With the above code, item is accessed using the same user account which was used to upload the document, hence the code succeeds in getting the item.
Hope this information was helpful!
This blog is based on a support ticket I handled recently. The requirement was to let anonymous users add items to a SharePoint list/library using client side object model(JavaScript).
Here are the steps needed to implement this.
1. Enable Anonymous access at the Web Application level
Go to SharePoint Central Administration => Application Management, select the Web Application => Authentication Providers, click on the zone, and select Enable anonymous access
2. Now, navigate to the corresponding web site, Site Action => Site Permissions => Anonymous Access.
Configure what anonymous users can access at the site level
3. Break the permission inheritance on the specific list in which you want to allow anonymous users to add items.
Navigate to the list/library settings for the list in which you want to allow Anonymous users to add items:
List Settings => Permissions for this list => Stop Inheriting Permissions, click OK => Anonymous Access
Select Add Items.
4. Enable “AddItem” operation for the client object model for the Web Application. You can run the following code as a console application (equivalent powershell script also should work).
// Allows AddItem operation using anonymous access
private static voidAllowAnonAccess(){
Console.WriteLine("Enabling Anonymous access....");
SPWebApplication webApp = SPWebApplication.Lookup(new Uri(webAppUrl));
webApp.ClientCallableSettings.AnonymousRestrictedTypes.Remove(typeof(Microsoft.SharePoint.SPList), "GetItems");
webApp.ClientCallableSettings.AnonymousRestrictedTypes.Remove(typeof(Microsoft.SharePoint.SPList), "AddItem");
webApp.Update();
Console.WriteLine("Enabled Anonymous access!");
// Revokes Add/Get Item operation using anonymous access
private static voidRemoveAnonAccess(){
Console.WriteLine("Disabling Anonymous access....");
webApp.ClientCallableSettings.AnonymousRestrictedTypes.Add(typeof(Microsoft.SharePoint.SPList), "GetItems");
webApp.ClientCallableSettings.AnonymousRestrictedTypes.Add(typeof(Microsoft.SharePoint.SPList), "AddItem");
Console.WriteLine("Disabled Anonymous access!");
Please do IISRESET after running this code
You can make use of the createListItem() and retrieveListItems() method discussed in the following articles to Add/Get items using the anonymous account:
How to: Retrieve List Items Using JavaScript
http://msdn.microsoft.com/en-us/library/hh185007(v=office.14).aspx
Creating a List Item Using ECMAScript (JavaScript, JScript)
http://msdn.microsoft.com/en-us/library/hh185011(v=office.14).aspx
Note: If you are using a custom layouts page to execute the JS Script, make sure it’s accessible to the anonymous users. Inherit the custom page from UnsecuredLayoutsPageBase with AllowAnonymousAccess set to true.
Anonymous layouts page:
Item created by the anonymous user:
Sample code for this is available for download.
Happy anonymous access!!
This post is a contribution from Amy Luu, an engineer with the SharePoint Developer Support team.
You can get the following error when SharePoint communicates to an external service via HTTPS either within the same server or a different server.
Could not establish trust relationship for the SSL/TLS secure channel, or
Remote certificate is invalid according to the validation procedure, or
An operation failed because the following certificate has validation errors
Typically, the scenario will be that a custom component that resides in SharePoint 2010/2013 calls WCF service over HTTPS on the same or different server. The reason for this is that SharePoint implements its own certificate validation policy to override .NET certificate validation.
Fix is to setup a trust between SharePoint and the server requiring certificate validation.
In SharePoint Central Administration site, go to “Security” and then “Manage Trust”. Upload the certificates to SharePoint. The key is to get both the root and subordinate certificates on to SharePoint.
The steps to get the certificates from the remote server hosting the WCF service are as follows:
1. Browse from IE to the WCF service (e.g., https://remotehost/service.svc?wsdl)
2. Right click on the browser body and choose “Properties” and then “Certificates” and then “Certificate Path”.
This tells you the certificate chain that’s required by the other server in order to communicate with it properly. You can double-click on each level in the certificate chain to go to that particular certificate, then click on “Details” tab, “Copy to File” to save the certificate with the default settings.
As an example, get both VeriSign & VeriSign Class 3 Extended Validation SSL CA.
Hope this helps!
A customer reported this problem to us and it was quite a learning to know how content processing works in SharePoint 2013 with respect to crawled properties from a custom XML indexing connector. Thought this could be worth sharing!
So, here’s the problem. Follow the steps outlined in this blog post Create a custom XML indexing connector for SharePoint 2013 and perform a full crawl of the custom XML connector content source. Go to Search Administration > Search Schema > Categories. Look at newly created custom XML connector category, you should see 18 crawled properties in there.
Use the ECB menu against the custom XML connector category called “XML Connector” and click “Edit Category”. Click “Delete all unmapped crawled properties” button to delete all the crawled properties available through the custom XML connector (screenshot below). Since we have not associated any crawled property to a managed property, all crawled property will be deleted.
Perform a full/incremental crawl of the content source again. Once done, check the crawled properties available for the custom XML connector category. There will be none available That’s the problem!!!
On investigation and collaborating with the search development team, it was learnt that this behavior is by design. Here’s the technical details.
CTS (Content Transformation Service) maintains an in-memory cache of crawled properties. And on subsequent crawls, it skips the properties that’s already in the cache. This design is for performance reasons. Since extracting crawled properties and updating them in schema is an intensive operation, CTS is designed this way so that only new crawled properties are crawled on subsequent attempts thus resulting in a much faster throughput in terms of crawl speed. This design also helps in reducing roundtrips to multiple databases as the property reporter talks to both schema object model and search admin database.
So here’s how to get back the crawled properties. There are two ways and these can be used as the scenario may be at your environments/deployments.
1. Restart search host controller services.
Open SharePoint 2013 Management Shell in admin mode and issue the command:
Restart-Service spsearchhostcontroller
This will restart all of the search services.
2. The above might not be ideal on environments where all search services are running on single server since it will cause a downtime for all search services (all noderunner.exe will be killed and spawned). In this case, the specific content processing process can be killed (with a command as shown below) and it will be spawned again immediately.
PS C:\> Get-WmiObject Win32_Process -Filter "Name like '%noderunner%' and CommandLine like '%ContentProcessing%'" | %{ Stop-Process $_.ProcessId }
Hope this post was informative and helpful.
I worked on a case where the problem was that PageMethods won’t execute from within a SharePoint 2013 application page (page deployed to the _layouts folder). To replicate the problem, I had a custom master page deployed through a VS 2012 solution with the following definition within the <body/> element.
<asp:ScriptManager id="ScriptManager" runat="server" EnablePageMethods="true" EnablePartialRendering="true" EnableScriptGlobalization="false" EnableScriptLocalization="true" />
<script type="text/javascript">
function CallMe() {
alert("called from master page");
// call server side method
PageMethods.TestMethod(OnRequestComplete, OnRequestError);
function OnRequestComplete(res, userContext, methodName) {
alert(res);
function OnRequestError(error, userContext, methodName) {
if (error != null) {
alert(error.get_message());
</script>
And I had my TestMethod defined in my application page as shown below.
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web.Services;
namespace SPProj.Layouts.SPProj
public partial class ApplicationPage1 : LayoutsPageBase
protected void Page_Load(object sender, EventArgs e)
Button1.Attributes.Add("onclick", "javascript:CallMe()");
[WebMethod]
public static string TestMethod()
return "Hello";
Notice the ‘onclick’ attribute added to the server-side button control in the Page_Load event. The idea is, when this page is loaded and the button is clicked, we call the “CallMe()” function defined in the master page. And this client-side function will call the server-side TestMethod method by virtue of having PageMethods enabled. But this is what happens in SharePoint 2013.
The page loads.
Click the button.
Click OK on this alert and the second message box won’t come up. You might have already noticed the JavaScript error in IE status bar. Double-click on it and you’ll see this error.
Apparently, this is because of anonymous JavaScript functions being pushed to the page by the new web-scoped feature called “Following Content”. Here’s a snippet from IE Developer Tools. For brevity, only relevant snippet is shown.
PageMethods.set_path("applicationpage1.aspx");
PageMethods.TestMethod= function(onSuccess,onFailed,userContext) {
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
PageMethods._staticInstance.TestMethod(onSuccess,onFailed,userContext); }
// from custom action with id = "FollowingCalloutScriptBlock"
(function(){
if (typeof(_spBodyOnLoadFunctions) === 'undefined' || _spBodyOnLoadFunctions === null) {
return;
_spBodyOnLoadFunctions.push(function() {
The problem is that when PageMethods are pushed to the page, a semi-colon isn’t added to properly terminate the JavaScript block. This is actually not a SharePoint but ASP.NET issue that PageMethods are not properly block terminated. Since the following JavaScript code is anonymous function at runtime it’s considered to be in the same block and executed, which causes the object expected error.
There are multiple ways to fix it.
1. Deactivate “Following Content” feature. Not a good one, but if this feature is not being used (which is highly unlikely), then simply deactivating it resolves this error.
2. Modify the “Following Content” feature. Change the 2 functions defined in the ScriptBlock of <CustomAction/> element to be named functions instead of anonymous. Deactivate/Uninstall “Following Content” feature. Install/Activate “Following Content” feature. THIS OF COURSE, IS UNSUPPORTED.
3. Override the Render method in the application page and inject a semi-colon character. Below is the modified application page code.
protected override void Render(System.Web.UI.HtmlTextWriter writer)
System.Web.UI.ScriptManager.RegisterClientScriptBlock(this, typeof(ApplicationPage1), "semicolon", ";", true);
base.Render(writer);
Once you deploy this solution, browse to the application page and watch the scripts pushed using IE Developer Tools, you’ll see this.
;
Notice that “;” character after the PageMethods declaration just before the anonymous functions from “Following Content” feature starts. Now, when the application page is browsed.
And the button is clicked.
The first alert is displayed and when you click OK, you’ll see the second alert as well.
That resolves this issue. Hope this post was helpful.