This topic describes how to deploy the PACS Storage Server and Medical Web Viewer to Microsoft Azure App Services. An app service is a Platform-as-a-Service (PaaS). Deploying the medical web viewer using App Services is not as straight-forward as deploying it to a virtual machine (VM). Nor do App Services provide as much control over the machine(s) hosting the services as Virtual Machines provide. However, managing App Services is easier when done through the Azure portal. For more information, refer to https://docs.microsoft.com/en-us/azure/architecture/guide/technology-choices/compute-decision-tree.
There are two different ways to set up the components:
Option 1: Host the web services, web client, and the database on Azure. Use the web client to store the DICOM files which will be stored on the local App Service drive.
Option 2: Host the web services, web client, DICOM files, and the database on Azure. This solution is more suitable for an enterprise solution. Using the LEADTOOLS Storage Server is a good way to manage the DICOM files.
The following instructions apply to both Option 1 and Option 2. [There is one step that applies solely to Option 2. That step, an additional edit to the advanced.config file, is included as a section entitled, "Option 2 Edits", at the end of the topic.]
Perform the following steps to add a new, classic Storage account:
Run the "CSPacsDatabaseConfigDemo.exe" demo to install your database in Azure, for more information see: Creating a Microsoft Azure-hosted Database
Perform the following steps to deploy the web service to an Azure app service:
One of the pre-requisites is to install the LEADTOOLS setup, and configure the Medical Web Viewer. Files from the setup and configuration need to be copied over to the App Service's site. To do so, perform the following steps:
Copy the Service Binaries and Config/Definitions to the Azure App Service
Go to the web service folder on disk (for example, <installation>\Examples\DotNet\PACSFramework\MedicalWebViewer\Leadtools.Medical.WebViewer.WCF).
Copy the contents of this folder to the App Service’s (site/wwwroot/) using the FTP client.
Copy everything in the BIN folder except for the following files: mfc100.dll, mfc100u.dll, mfcm100.dll, mfcm100u.dll, Leadtools.Tasks.ServerProcess.exe
Note: The default platform is win32, so be sure you are copying the 32-bit binaries from the LEADTOOLS installation folder.
Note: Currently the free plan on Azure lets you deploy 32-bit web applications. To deploy 64-bit applications, from the Azure portal select the App Service and click Settings > Platform. Change the platform to 64-bits.
Create a new Folder called (App_Data) inside the (site/wwwroot/).
Copy the (PACS server folder). The default name is (L21_PACS_SCP32). It can be found on <installation>\bin\Dotnet4\Win32 if you are installing the win32.
Copy any LEADTOOLS License file to APP_Data.
From (site/wwwroot/), edit the web.config file as follows:
Remove any reference to CorsSupport, Leadtools.Wcf.CorsSupportBehaviorElement.
In appSettings, change the following values:
license
> set the value to App_Data\licensefilename.lic
key
> set the value to App_Data\xyz123abc
globalConfigPath
> set to App_Data\globalPacs.Config
storageServerServicePath
> set to App_Data\L21_PACS_SCP32\
Caching.Enabled
> set to false
Caching.Lifetime
> set to 00:00:00
For more information about using the settings in the web.config file to manage caching, refer to Managing the Medical Web Viewer Custom Cache.
From (site/wwwroot/App_Data), open the globalPacs.config file and edit the connection string for (LeadStorageServer21_32 or LeadStorageServer21_64) to be the one pointing to the Azure SQL Database you created above.
From (site/wwwroot/App_Data/L21_PACS_SCP32) edit the advanced.config file as follows:
storeAddIn
node with the following code:
<storeAddIn storageLocation="d:\home\data\L21_PACS_SCP32\Store"
hangingProtocolLocation="d:\home\data\L21_PACS_SCP32\Store\HangingProtocol"
storeFileExt="dcm" preventStoringDuplicateInstance="false" createBackupBeforeOverwrite="true"
overwriteBackupLocation="d:\home\data\L21_PACS_SCP32\Store\Overwrite"
deleteFiles="true" backupFilesOnDelete="false" deleteBackupLocation="d:\home\data\L21_PACS_SCP32\Store\Backup"
createThumbnailImage="false" DeleteAnnotationsOnImageDelete="false"
saveCStoreFailures="false" cStoreFailuresPath="d:\home\data\L21_PACS_SCP32\Store\StoreFailures"
autoTruncateData="false" useMessageQueue="true" autoCreateFolderLocations="true">
<directoryStructure createPatientFolder="true" createSeriesFolder="true"
usePatientName="false" splitPatientId="false" />
If Option 2 is being implemented, modify the <addin name=”ExternalStore”> node of the advanced.config file as well. Click here to go to the Option 2 Edits
Enable CORS. For testing, allow all (*) to connect. Enabling CORS helps when testing the web service from your machine. Be sure to remove this when finished.
Add a new Web App. Azure portal > New > Compute > App Services > Web App
Name your Web App “MedicalViewer21”
Go to your new App Service > Overview, get the FTP , and make sure you get the FTP user name as well
Use your favorite FTP client (e.g., Windows Explorer) to browse to that site location
Navigate to site/wwwroot/
Once again it is necessary to copy files from the installed LEADTOOLS setup, and the configured Medical Web Viewer. Perform the following steps:
Copy the Service Binaries and Config/Definitions. To do this, go to the web service folder on disk (e.g., (installation)\Examples\DotNet\PACSFramework\MedicalWebViewer\JS\MedicalWebViewerDemo)
Copy the contents of this folder to the App Service’s (site/wwwroot/) using the FTP client.
Search for the tag <base href and make sure the value is set to empty/blank:
<base href="" />
From (site/wwwroot/), open the web.config file and change the value of the (serviceUrl) to point to the web service deployed on Azure. You can get the web service URL from the Azure portal.
Get the URL from the Azure portal and navigate to it using an internet browser. You should be able to login and use most of the functionality of the web viewer
If you decided to deploy the (createTableAndData.sql) script to the database, the default user name/password is: admin/admin.
Download the sample SQL script to create tables and data here! (Unzip the downloaded file before using it.)
You can use the Storage Server demo to browse and manage your data if you modify its globalPacs.config and advanced.config files the same way you modified them for the App Service (for win32 these files are found in the Bin\Dotnet4\Win32 & Bin\Dotnet4\Win32\L21_PACS_SCP32). Using the Storage Server demo is optional, but can be very helpful.
Because of the nature of the platform Azure service apps use, the following functionalities do not work:
Secondary Capture
Print to PDF with Annotations burned-in (realized)
Make the following edits to the <addin name=”ExternalStore”> node of the advanced.config file only if you are implementing Option 2.
Note that in order for the BLOBS to be uploaded to Cloud Storage instead of Local Storage, StoreLocally
needs to be set to false.
Be sure to replace the following values (they are highlighted in the following code section):
<addin name="ExternalStore">
<customData>
<custom name="ExternalStoreOptions" type="Leadtools.Medical.Winforms.ExternalStore.ExternalStoreOptions, Leadtools.Medical.Winforms, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraTypeCount="7" extraType0="Leadtools.Medical.Winforms.Forwarder.Scheduling.Job, Leadtools.Medical.Winforms, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraType1="Leadtools.Medical.ExternalStore.Atmos.Addin.AtmosConfiguration, Leadtools.Medical.ExternalStore.Atmos.Addin, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraType2="Leadtools.Medical.ExternalStore.Atmos.Addin.AtmosExternalStoreAddinConfig, Leadtools.Medical.ExternalStore.Atmos.Addin, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraType3="Leadtools.Medical.ExternalStore.Azure.Addin.AzureConfiguration, Leadtools.Medical.ExternalStore.Azure.Addin, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraType4="Leadtools.Medical.ExternalStore.Azure.Addin.AzureExternalStoreAddinConfig, Leadtools.Medical.ExternalStore.Azure.Addin, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraType5="Leadtools.Medical.ExternalStore.Sample.Addin.SampleConfiguration, Leadtools.Medical.ExternalStore.Sample.Addin, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null"
extraType6="Leadtools.Medical.ExternalStore.Sample.Addin.SampleExternalStoreAddinConfig, Leadtools.Medical.ExternalStore.Sample.Addin, Version=21.0.0.1, Culture=neutral, PublicKeyToken=null">
<ExternalStoreOptions xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ExternalStoreIndex>1</ExternalStoreIndex>
<Items>
<ExternalStoreItem>
<ImageHold>0</ImageHold>
<HoldInterval>Days</HoldInterval>
<Verify>false</Verify>
<ExternalStoreAddinConfig xsi:type="AtmosExternalStoreAddinConfig">
<FriendlyName>Atmos Cloud Storage</FriendlyName>
<ConfigurationObject xsi:type="AtmosConfiguration">
<AtmosUrl>api.atmosonline.com</AtmosUrl>
<Uid>Enter UID</Uid>
<SharedSecret>Enter Shared Secret</SharedSecret>
<Port>443</Port>
<Timeout>100</Timeout>
<StorageModel>Object</StorageModel>
<StoreLocally>true</StoreLocally>
</ConfigurationObject>
<Guid>09F258DF-1BDF-46FC-9106-F9ECFEE15A59</Guid>
</ExternalStoreAddinConfig>
</ExternalStoreItem>
<ExternalStoreItem>
<ImageHold>0</ImageHold>
<HoldInterval>Days</HoldInterval>
<Verify>false</Verify>
<ExternalStoreAddinConfig xsi:type="AzureExternalStoreAddinConfig">
<FriendlyName>Azure Cloud Storage</FriendlyName>
<ConfigurationObject xsi:type="AzureConfiguration">
<StorageAccountName>storageserver</StorageAccountName>
<StorageAccountKey>NeLB3owGvuH9ziMJphMNmFmD9JB4wz9jmEneJqRy5gk+Q+dvstjBtPOfUFtbbaFQrwO2oueLdw==</StorageAccountKey>
<ContainerName>testcontainer1</ContainerName>
<UseHttps>false</UseHttps>
<StoreLocally>false</StoreLocally>
</ConfigurationObject>
<Guid>845B878D-2786-4445-99ED-9A1514093B96</Guid>
</ExternalStoreAddinConfig>
</ExternalStoreItem>
<ExternalStoreItem>
<ImageHold>0</ImageHold>
<HoldInterval>Days</HoldInterval>
<Verify>false</Verify>
<ExternalStoreAddinConfig xsi:type="SampleExternalStoreAddinConfig">
<FriendlyName>LEAD Sample External Store Addin</FriendlyName>
<ConfigurationObject xsi:type="SampleConfiguration">
<UserId>Enter User ID</UserId>
<Password>Enter Password</Password>
<Name>Enter Name</Name>
<Gender>Male</Gender>
<Age>18</Age>
<Location>F:\LEADTOOLS21\Bin\Dotnet4\x64\ExternalStoreSampleStore</Location>
<StoreLocally>true</StoreLocally>
</ConfigurationObject>
<Guid>0868AEE8-F7FA-435A-8F40-00386C339AE3</Guid>
</ExternalStoreAddinConfig>
</ExternalStoreItem>
</Items>
</ExternalStoreOptions>
</custom>
</customData>
</addin>
storeAddIn
node)