Saturday, October 8, 2016

How to approve SharePoint Tasks from mobile devices?

Many have tried and offered options and workarounds which somewhat work. There are options like the "Lazy Approval" or paid apps. I am going to offer you my take on this issue.

THE PROBLEM 
You have on premise SharePoint 2013 farm and you are utilizing InfoPath forms for many different purposes. Some of these forms require approval and trigger an approval workflow which kicks out an email to end users. This is no problem on desktops and laptops with Outlook while in office or connected via VPN. The problem is with end users who are often on the go and would like to review and approve forms on their mobile devices such as IPhones/IPads and Androids. 

Side Problems: 
  • We need to convert specific links to FQDN links to ensure its accessible from the outside.
  • We need to force InfoPath forms to open in browser.
  • We need to force SharePoint to open in PC View.
THE SOLUTION
Prior to proceeding, I have created a simple Approval Workflow in SharePoint 2010 workflow format and specified my approves. In case of some InfoPath forms, approves are added on the fly when filling out a form,

InfoPath Forms Library Site Location: http://demo/subsite
  1. Edit the Approval Workflow in SharePoint Designer 2013
  2. Click on Change the behavior of a single task
  3. Click on Local Variables and create two variables.
    1. fqdnURL with type of String
    2. InfoPathMobileFQDN with type of String.
  4. Under When a Task is Pending window.
    1. Click on Action button in the ribbon.
      1. Select Extract Substring from Index of String. Had to do this in order to get part of the task URL that is needed later in the workflow to change the link to FQDN.
      2. Click on string and set it to Current Task:Form_URN
      3. It will output to Variable: substring2
    2. Click on Action button in the ribbon.
      1. Select Set Workflow Variable.
      2. Click on workflow variable and set it to Variable:fqdnURL.
      3. Click on value and set it to the site fully qualified domain name url, in my case its http://demo.whateverdomain.com/subsite
    3.  Click on Action button in the ribbon.
      1. Select Set Workflow Variable.
      2. Click on workflow variable and set it to Variable:InfoPathMobileFQDN.
      3. Click on value and set it to the site fully qualified domain name url used to open InfoPath form in browser, in my case its: "http://demo.whateverdomain.com/subsite/_layouts/15/FormServer.aspx?XmlLocation=/subite/[%TaskProcess:Item_URL%]&ClientInstalled=false&DefaultItemOpen=1"
      4. In red above please insert your own information.
      5. Should look like the following:
      6. Click on ...then Email task notification to Current Task: Assigned_To, number 4 in the above image.
      7. Highlight and edit link after the Review word in line #1, and set it to:
        1. Text to display: [%Task Process:Item_Title%]
        2. Address: set it to variable InfoPathMobileFQDN.
      8. Add If you don't see Open this task button, please click here text to the like line #3.
      9. Highlight the If you don't see Open this task button, please click here text and click on Edit HyperlLink button and set it to:
        1. Text to display: please click here
        2. Address: [%Variable: fqdnURL%]/[%Variable: substring2%]&OpenIn=Browser&Mobile=0
      10. Should look like the following:
      11. The added link in the line #3 in the screenshot above is to accommodate Non-Outlook users such as when checking webmail or using mobile devices. 
      12. Click OK and save and publish your workflow.
      13. Start a workflow with yourself and try it out on your mobile device.
NOTE: Please note that you will need to do this on few other places within this particular workflow and if you have more then one approval workflow, you will need to do this on every single one of them. There are also considerations such as if you are using UAG or some other method to publish your on premise SharePoint so that its accessible to the outside world.

This is a very first try and I plan to tweak it here and there using variables to reduce amount of typing the URLs and so on. Long story short, Approval workflows can be accessed and approved via mobile devices with few modifications mentioned above. I hope this helps someone.

Keep in mind,  you are using the above on your own risk. 

Tuesday, November 10, 2015

Excel 2013 documents opening slow in SharePoint 2013

Using Office 2013 (15.0.4701.1001), often excel documents would hang for 20-30 seconds. Microsoft suggested the following key be added to the end user registry:
  1. Open regedit.exe
    Navigate to following key:
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\15.0\Common\Internet]
  1. Click Edit Menu -> New -> DWORD with name of "FSSHTTPOff" (without quotes)
  2. Click on "FSSHTTPOff" and enter value of 1
  3. Close any Office Applications and browser sessions
Please use at your own risk.

Wednesday, May 20, 2015

SharePoint 2013 List throws the "Value does not fall within the expected range." error when trying to submit a new item.

Recently, we had an issue with one of our custom lists. This list had a form customized with InfoPath 2013. Out of nowhere, one day we could not submit any new items and would get the following error message.


"Value does not fall within the expected range."
After checking ULS logs, we found the following:



System.ArgumentException: Value does not fall within the expected range., StackTrace:
at Microsoft.SharePoint.SPListItem.AddOrUpdateItem(Boolean bAdd, Boolean bSystem, Boolean bPreserveItemVersion, Boolean bNoVersion, Boolean bMigration, Boolean bPublish, Boolean bCheckOut, Boolean bCheckin, Guid newGuidOnAdd, Int32& ulID, Object& objAttachmentNames, Object& objAttachmentContents, Boolean suppressAfterEvents, String filename, Boolean bPreserveItemUIVersion)
at Microsoft.SharePoint.SPListItem.UpdateInternal(Boolean bSystem, Boolean bPreserveItemVersion, Guid newGuidOnAdd, Boolean bMigration, Boolean bPublish, Boolean bNoVersion, Boolean bCheckOut, Boolean bCheckin, Boolean suppressAfterEvents, String filename, Boolean bPreserveItemUIVersion)
at Microsoft.SharePoint.SPListItem.Update()
at Microsoft.SharePoint.SPListItem.ValidateUpdateListItem_Client(List`1 formValues, Boolean bNewDocumentUpdate)
at Microsoft.SharePoint.ServerStub.SPListItemServerStub.InvokeMethod(Object target, String methodName, XmlNodeList xmlargs, ProxyContext proxyContext, Boolean& isVoid)
at Microsoft.SharePoint.Client.ServerStub.InvokeMethodWithMonitoredScope(Object target, String methodName, XmlNodeList args, ProxyContext proxyContext, Boolean& isVoid)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.InvokeMethod(Object obj, String methodName, XmlNodeList xmlargs, Boolean& isVoid)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessMethod(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessOne(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessStatements(XmlNode xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessExceptionHandlingScope(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessOne(XmlElement xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.ProcessStatements(XmlNode xe)
at Microsoft.SharePoint.Client.ClientMethodsProcessor.Process()
at Microsoft.SharePoint.Client.ClientRequestServiceImpl.ProcessQuery(Stream inputStream, IList`1 pendingDisposableContainer)
at Microsoft.SharePoint.Client.ClientRequestService.ProcessQuery(Stream inputStream)
at SyncInvokeProcessQuery(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
at System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext)
at System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump(IAsyncResult result)
at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(Item item, Boolean canDispatchOnThisThread)
at System.Runtime.InputQueue`1.EnqueueAndDispatch(T item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.SingletonChannelAcceptor`3.Enqueue(QueueItemType item, Action dequeuedCallback, Boolean canDispatchOnThisThread)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.CompleteParseAndEnqueue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EnqueueMessageAsyncResult.HandleParseIncomingMessage(IAsyncResult result)
at System.Runtime.AsyncResult.SyncContinue(IAsyncResult result)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.BeginProcessInboundRequest(ReplyChannelAcceptor replyChannelAcceptor, Action dequeuedCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Channels.HttpChannelListener`1.HttpContextReceivedAsyncResult`1.ProcessHttpContextAsync()
at System.ServiceModel.Channels.HttpChannelListener`1.BeginHttpContextReceived(HttpRequestContext context, Action acceptorCallback, AsyncCallback callback, Object state)
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequest(Object state)
at System.ServiceModel.AspNetPartialTrustHelpers.PartialTrustInvoke(ContextCallback callback, Object state)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.OnBeginRequestWithFlow(Object state)
at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)


We figured it was a corrupted column but since this list has about 80 columns of different types we could not quite put a finger on which one was corrupted. After exhausting google search and million articles that led to mostly custom code, development, and people/groups column issues we submitted a ticket with Microsoft. However, Microsoft could not figure it out but agreed that its a corrupted column.

Our next step was to export the list and import it into another site and start deleting columns one by one until we find the one that is corrupted. After much trial and error we found that the issue was with a dropdown (choice column). If we deleted that particular choice column, we could submit new items with no problems.

So deleting this column in production list would be a big problem, hence deleting was not an option or at least not yet. Next, we realized that this column was indexed so we deleted its index and tried to submit new item...and it worked!!!

So it appears that its index was corrupted somehow, so simply deleting its index resolved the issue.





Tuesday, February 3, 2015

SharePoint 2013 Alerts not working...again

There is plenty of resources online about this issue and none suggest doing this first and they really should.

So if you had SharePoint 2013 alerts configured and working and is just stopped working one day with the following symptoms:

  • If you register for alerts in a particular list, you get a notification that "You have successfully created an alert for..."
  • If you modify any item in the same list as above, no alerts come thru.

You will need to make sure that each SharePoint server ip address (web front, application) in the farm is added as an allowed SMTP sender in Exchange.

Explanation: Any SharePoint server in the farm can be in charge of sending an alert and usually one is in charge of a particular site collection. If you restart Timer Service, it might move that responsibility to another SharePoint server whose IP is not listed as an allowed SMTP sender in Exchange, and as an end result, it might not send alerts.

Hoping this helps someone

Wednesday, November 6, 2013

Publishing Office Web Apps 2013 in UAG 2010

If you are setting up Office Web Apps 2013 along with SharePoint 2013 and need to publish both in UAG 2010 for external users you should read the following article:

http://technet.microsoft.com/en-us/library/jj204665.aspx

Pay close attention to line 8 as it made a difference for us.

Tuesday, October 1, 2013

The permissions granted to user ‘domain\username’ are insufficient for performing this operation.

If you are setting up SharePoint 2013 and SQL 2012 with SharePoint Integration Mode please read on. You might be under impression you did everything properly but you get the following error when trying to deploy a report using BIDS or trying to edit a data source:

"The permissions granted to user ‘domain\username’ are insufficient for performing this operation. —> Microsoft.ReportingServices.Diagnostics.Utilities.AccessDeniedException: The permissions granted to user ‘domain\username’ are insufficient for performing this operation."

To solve this problem you have to grant your SQL Reporting Service Application Pool Account (whatever is running your SQL Service Application, see Central Admin -> Manage Service Application -> SQL Server Reporting Services) Full Control to the web application that report is being deployed to in your particular case.

Or you could just use the powershell command below:

$webApp = Get-SPWebApplication –Identity http://yoursharepointapp
$webApp.GrantAccessToProcessIdentity(“domain\SSRSAccount”)


Source: http://paulliebrand.com/

Thursday, September 26, 2013

Attaching SharePoint 2010 content database (Windows/SQL 2008 R2) database to SharePoint 2013 (Windows/SQL 2012)

If you are migrating from SharePoint 2010 to SharePoint 2013 and trying to attach a SharePoint 2010 content database that used to reside in SQL 2008 R2 to SQL 2012 you should know the following.

During the upgrade process of attached database you might get an error message similar to this:

"WARNING The [SharePoint - 25000] web application is configured with claims authentication mode however the content database you are trying to attach is intended to be used against a windows classic authentication mode."

The reason you are getting error message above is because all new Web Applications in SharePoint 2013 are by default created in Claims Authentication Mode.

To get around this, create the new Web Application in SharePoint 2013 using PowerShell command with Windows Classic Authentication Mode:

New-SPWebApplication -Name "Contoso Internet Site" -ApplicationPool "ContosoAppPool" -AuthenticationMethod "Kerberos" -ApplicationPoolAccount (Get-SPManagedAccount "CONTOSO\jdoe") -Port 80 -URL "https://www.contoso.com"

Microsoft: http://technet.microsoft.com/en-us/library/gg276326.aspx

Please be aware that this authentication mode is no longer supported. At this point you can run the upgrade once more and move on.

If you use anything written here, you do it on your own risk!