Category: Office Web Application Server (WAC)

Office Web Applications 2013: Errors pre-viewing all Office Documents

In process of building Disaster Recovery Solution for SharePoint 2013 we installed a DR SharePoint Farm (SP2013) and DR Office Web Application Servers Farm (WAC2013). In process of testing integration between SP2013 DR farm and WAC2013 DR Farm we received errors for all Office Web Apps services.

Word Web Apps error:  “Sorry, there was a problem and we can’t open this document.  If this happens again, try opening the document in Microsoft Word.”

OfficeWebAppsWordErrorProblemOpeningDocument

Excel Web Apps Error: “Excel Web App – Sorry, we’re having a problem showing this workbook”

OfficeWebAppsExcelErrorProblemOpeningDocument

Sifting ULS Log entry: “HttpRequestAsync (WOPICheckFile,WACSERVER), request failure [HttpResponseCode:Unauthorized, HttpResponseCodeDescription:Unauthorized, url:http://SP2013/sites/Workflows/_vti_bin/wopi.ashx/files/a457e9117c8d466faa75bcb4cf26149c?access_token=REDACTED_1056&access_token_ttl=1470880994483%5D”, followed by “Request http://SP2013/sites/Workflows/_vti_bin/wopi.ashx/files/a457e9117c8d466faa75bcb4cf26149c failed with 401 error but we will not retry. [file source: WACSERVER]”.

SharePoint2013_OfficeWebApps2013_DisasterRecovery_HighLevel

Disaster Recovery architecture diagram for SharePoint 2013 and Office Web Apps 2013

In our case we were accessing DR SP2013 farm and DR WAC2013 farm through local traffic managers load balancers (LLB) and the Primary Farms through Geographical load balancers (GLB). Both farms are configured to have both GLB and LLB URLs as alternative access mappings (AAM) with GLB URL set as a default.

The way Office Web Apps integration with SharePoint works is that when SharePoint create a request to Office Web Apps Server Farm it uses the Default AMM URL as a base for a link to the document that is being previewed. In our case it was using URL of GLB,  and as result was trying to access the primary farm to generate document preview. The 401 error was due to the fact that the user did not have authentication token to the primary farm.

Solution: the following steps need to be performed in DR SP 2013 and WAC 2013 farms for the time of integration testing the DR farm:

1.  SP2013DR farm have to be reconfigured to use the URL of LLB of the DR SharePoint farm as default AAM;

2. WAPI bindings on the DR SP 2013 farm needs to be reconfigured to use the URL of the LLB of the WAC2013DR Farm;

Remove-SPWOPIBinding -All:$true -confirm:$false
Get-SPWOPISuppressionSetting | Remove-SPWOPISuppressionSetting -confirm:$false
New-SPWOPIBinding -ServerName 'WAC2013DR' -confirm:$false
Set-SPWOPIZone –zone 'internal-https' -confirm:$false

3. DR Office Web Application Farm needs to be configured to use DR WAC 2013 farm URL of LLB as -InternalURL parameter;

Set-OfficeWebAppsFarm -InternalURL 'https://WAC2013DR' 

Those steps will need to be reversed to get farm ready for the Disaster Recovery situation.

 

That was another page in the Chronicles of SharePoint Bits, Happy scripting!

Office Web Applications 2013: 404 (File or Directory not found) error in documents Preview

Same times after opening Excel the document in the browser or narrowing search result using Refinement Panel document preview using Office Web App (WAC) will generate 404 error

 OfficeWebAppsServer2013_404Error

Problem: SP2013 keeps track of the navigation history using query string and passes it to Office Web Application Server to preserve it. If query string exceeds the IIS or Web Application limits the URL gets trimmed out and user get an 404 – File or directory not found error.

Solution: Increase default IIS and Web Application maximum query and URL string as described in the TechNet blog:

http://blogs.technet.com/b/office_web_apps_server_2013_support_blog/archive/2015/02/13/office-web-apps-2013-throws-a-404-error-on-mobile-devices.aspx

You will have to modify IIS and Office Web Apps application configuration as following:

c:\windows\system32\inetsrv\config\applicationHost.config

<requestFiltering>

<requestLimits maxAllowedContentLength=”262144000″ maxUrl=”40960” maxQueryString=”16048” />

</requestFiltering>

Ref: https://msdn.microsoft.com/en-us/library/vstudio/e1f13641(v=vs.100).aspx

 

D:\APPS\Microsoft Office Web Apps\RootWebSite\Web.Config:

<system.web>

<httpRuntime maxRequestLength=”256000″ maxUrlLength=”40960” maxQueryStringLength=”16048” />

</system.web>

maxQueryStringLength (Optional Int32 attribute) The maximum length of the query string, in number of characters. The default is 2048.

The value of the MaxQueryStringLength property can be any integer, zero or larger. If the length of a query string exceeds the size limit, ASP.NET returns an HTTP 400 (Bad Request) status code.

Note: Extremely small values can make a Web site unusable.

There is also an IIS setting that controls query string length. See the maxQueryString attribute in Request Limits <requestLimits>.

maxUrlLength (Optional Int32 attribute) The maximum length of the URL, in number of characters. The default is 260.

The value of the MaxUrlLength property can be any integer, zero or larger.

If the length of the request URL (which is the value of the Path property) exceeds the configured size limit, ASP.NET returns an HTTP 400 (Bad Request) status code.

Note: Extremely small values can make a Web site unusable.

maxRequestLength (Optional Int32 attribute) Specifies the limit for the input stream buffering threshold, in KB. This limit can be used to prevent denial of service attacks that are caused, for example, by users posting large files to the server. The default is 4096 KB.

If the threshold is exceeded, a ConfigurationErrorsException exception is thrown.

Ref: http://www.iis.net/configreference/system.webserver/security/requestfiltering/requestlimits

 

That was another page in the Chronicles of SharePoint Bits, no new scripts today!

Checking Office Web Application Server farm version and SSL Certificate

In complex environment when load balancing solution implemented for Office Web Apps Server on two or more servers it is important to have the same version of Office Web App Server to be installed on all the servers in the Office Web App farm. Plus you have to make sure the SSL certificate have not expired on any of the servers.
The following command can be used to retrieve Office Web Application Server version number:
(Invoke-WebRequest https://wac.contoso.com/m/met/participant.svc/jsonAnonymous/BroadcastPing).Headers[“X-OfficeVersion”].
You will have to verify that response header from every server in the farm have the same X-OfficeVersion value. While checking the response header you can check the certificate for expiration as well.
The code below checks certificate expiration date and X-OfficeVersion value in Response Header from the load balancer plus from every server in the Farm. The function that checks the Certificate was adapted from PowerShell to get remote website’s SSL certificate expiration blog.

####################################################################################################
#
#  Author.......: David Shvartsman
#  Date.........: 07/20/2016
#  Description..: Checking Office Web Application Server farm version and SSL Certificate
#
####################################################################################################
if ((Get-PSSnapin 'Microsoft.SharePoint.PowerShell'; -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin 'Microsoft.SharePoint.PowerShell'
}
function checkWAC($url, $WACEnvironment) {
    #disabling the cert validation check. This is what makes this whole thing work with invalid certs...
    [Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    $WACerror = 'Green'
    $WACVer= 'not accessible'
    $minimumCertAgeDays = 60
    $timeoutMilliseconds = 10000
    $expiration = $null
    $certExpiresIn = $null
    $req = [Net.HttpWebRequest]::Create($url)
    $req.Timeout = $timeoutMilliseconds
    try {
        $response = $req.GetResponse()
        $WACVer = $req.GetResponse().Headers['X-OfficeVersion'] #|Out-Null
        $response.Close()
    [datetime]$expiration = $req.ServicePoint.Certificate.GetExpirationDateString()
    [int]$certExpiresIn = ($expiration - $(get-date)).Days
    $certName = $req.ServicePoint.Certificate.GetName()
    $certPublicKeyString = $req.ServicePoint.Certificate.GetPublicKeyString()
    $certSerialNumber = $req.ServicePoint.Certificate.GetSerialNumberString()
    $certThumbprint = $req.ServicePoint.Certificate.GetCertHashString()
    $certEffectiveDate = $req.ServicePoint.Certificate.GetEffectiveDateString()
    $certIssuer = $req.ServicePoint.Certificate.GetIssuerName()
    if ($certExpiresIn -gt $minimumCertAgeDays)
        {$cert = 'Cert expires in $certExpiresIn days [on $expiration]'}
    else
        {$cert = 'Cert expires in $certExpiresIn days [on $expiration] Threshold is $minimumCertAgeDays days. Check details:`n`nCert name: $certName`nCert public key: $certPublicKeyString`nCert serial number: $certSerialNumber`nCert thumbprint: $certThumbprint`nCert effective date: $certEffectiveDate`nCert issuer: $certIssuer'}
    }
    catch {
        #Write-Host Exception while checking URL $url`: $_ -f Red
        $WACerror = 'Red'
    }

    $req = $null
    rv req
    rv expiration
    rv certExpiresIn
    Write-host 'Office Web Apps Server [$($WACSPserver)] version in $($WACEnvironment): $($WACVer), $($cert)' -ForegroundColor $WACerror
    $WACVer
}

CLS
Write-Host 'The Office Web App 2013 (WAC) version information can be found here: http://www.toddklindt.com/blog/Lists/Posts/Post.aspx?ID=346#OWA'
Write-Host ''
$WACerror = $false
#Checking Load Balancer URL https://wac.contoso.com
$WAC1 = checkWAC 'https://wac.contoso.com/m/met/participant.svc/jsonAnonymous/BroadcastPing'     'LOAD Balancer'
#Checking Individual Server URL https://wacserver1.contoso.com
$WAC2 = checkWAC 'https://wacserver1.contoso.com/m/met/participant.svc/jsonAnonymous/BroadcastPing'   'wacserver1'
if ($WAC1 -ne $WAC2) {$WACerror = $true}
$WAC1 = $WAC2
#Checking Individual Server URL https://wacserver2.contoso.com
$WAC2 = checkWAC 'https://wacserver2.contoso.com/m/met/participant.svc/jsonAnonymous/BroadcastPing'   'wacserver2'
if ($WAC1 -ne $WAC2) {$WACerror = $true}
$WAC1 = $WAC2
#Checking Individual Server URL https://wacserver3.contoso.com
$WAC2 = checkWAC 'https://wacserver3.contoso.com/m/met/participant.svc/jsonAnonymous/BroadcastPing'   'wacserver3'
if ($WAC1 -ne $WAC2) {$WACerror = $true}
if ($WACerror) {Write-Host 'WAC servers version are not the same' -ForegroundColor red}
Write-Host ''

The list of all Office Web App 2013 Server (WAC) versions information can be found on Todd Klindt blog: http://www.toddklindt.com/blog/Lists/Posts/Post.aspx?ID=346#OWA

That was another page in the Chronicles of SharePoint Bits, happy scripting!