Step 1: Configure the HTML5 Medical Viewer to work with the shipping database schema
This should already be configured, as it is part of the Configure the LEAD Storage Server with the shipping database schema step in the Changing the LEAD Medical Storage Server to Use a Different Database Schema tutorial.
If you have not already done this, you must restore the globalPacs.config file to reference the shipping database:
Start Windows Explorer, and go to the {LEAD Installation BIN} folder.
Rename the globalPacs.config to globalPacs_custom.config.
Make a copy of globalPacs_original.config, and rename the copy globalPacs.config.
Run LeadtoolsServicesHostManager_Original.exe. It performs the following tasks:
Run WebViewerConfiguration_Original.exe.
At this point, you should verify that the Medical Web Viewer Demo runs correctly using the shipping database.
Step 2: Modify GlobalPacs.config to use the tutorial custom database
This should already be configured if you have finished the Changing the LEAD Medical Storage Server to Use a Different Database Schema tutorial.
If you have not already done this, follow Step 4: Modify GlobalPacs.config to use the New Database of the Changing the LEAD Medical Storage Server to Use a Different Database Schema tutorial.
Open a browser (for example, Internet Explorer) and enter the following URL:
Step 3: Modify the web.config to use the storage catalog and the DataSet Schema
Open the Medical Web Services web.config configuration file in any editor (i.e. Visual Studio)
The default location for the Medical Web Services web.config file is here:
C:\LEADTOOLS 19\Examples\PACSFramework\MedicalWebViewer\Leadtools.Medical.WebViewer.WCF\web.config
Make the following additions (additions shown highlighted), and save your changes.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="xmlStorageCatalogSettings" type="Leadtools.Medical.Storage.DataAccessLayer.XmlStorageCatalogSettings, Leadtools.Medical.Storage.DataAccessLayer" />
</configSections>
<xmlStorageCatalogSettings catalogPath="C:\LEADTOOLS 19\Bin\Dotnet4\Win32\MyCatalog.xml"/>
<system.web>
<compilation debug="true" />
<authentication mode="None"/>
<httpRuntime maxRequestLength="2097151" />
<hostingEnvironment shadowCopyBinAssemblies="false"/>
<pages compilationMode="Never"/>
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="Leadtools.Medical.WebViewer.Wcf.StoreService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IStoreService" behaviorConfiguration="WebViewerServiceBehavior" bindingConfiguration="HandleLargeData">
</endpoint>
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.ObjectQueryService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IObjectQueryService" behaviorConfiguration="WebViewerServiceBehavior">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.ObjectRetrieveService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IObjectRetrieveService" behaviorConfiguration="WebViewerServiceBehavior">
</endpoint>
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.PacsQueryService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IPACSQueryService" behaviorConfiguration="WebViewerServiceBehavior">
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.PACSRetrieveService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IPACSRetrieveService" behaviorConfiguration="WebViewerServiceBehavior">
</endpoint>
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.AuthenticationService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IAuthenticationService" behaviorConfiguration="WebViewerServiceBehavior">
</endpoint>
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.PatientAccessRightsService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IPatientAccessRightsService" behaviorConfiguration="WebViewerServiceBehavior">
</endpoint>
</service>
<service name="Leadtools.Medical.WebViewer.Wcf.AnnotationsService" behaviorConfiguration="WebViewerServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="Leadtools.Medical.WebViewer.ServiceContracts.IAnnotationsService" behaviorConfiguration="WebViewerServiceBehavior" bindingConfiguration="HandleLargeData">
</endpoint>
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="jsonWebHttp" type="Leadtools.Dicom.Services.ErrorHandler.JsonErrorWebHttpBehaviorElement, Leadtools.Medical.WebViewer.WCF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<bindings>
<webHttpBinding>
<binding name="HandleLargeData" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="WebViewerServiceBehavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True" />
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebViewerServiceBehavior">
<webHttp />
<jsonWebHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<connectionStrings>
</connectionStrings>
<appSettings>
<add key="license" />
<add key="key" />
<add key="ClientAe" value="L19_CLIENT32" />
<add key="ClientIP" value="192.168.0.181" />
<add key="ClientPort" value="1000" />
<add key="ServerAe" value="L19_PACS_SCP32" />
<add key="ServerIP" value="192.168.0.181" />
<add key="ServerPort" value="504" />
<add key="globalConfigPath" value="C:\LEADTOOLS 19\Bin\Dotnet4\Win32\GlobalPacs.config" />
<add key="storageServerServicePath" value="c:\LEADTOOLS 19\bin\dotnet4\win32\L19_PACS_SCP32\" />
<add key="DataSetSchema" value="C:\LEADTOOLS 19\Bin\Dotnet4\Win32\MyDataSet.xsd"/>
</appSettings>
</configuration>
For detailed information on the storage catalog see the Storage Catalog topic in the Changing the LEAD Medical Storage Server to Use a Different Database Schema tutorial.
For detailed information on the DataSet schema, see the Creating the Strongly Typed DataSet Class and the XML Schema topic in the Changing the LEAD Medical Storage Server to Use a Different Database Schema.
Step 4: Modify the Leadtools.Medical.WebViewer.WCF Assembly
Note that any code modifications that you make as part of this tutorial have already been included in the shipping version of the source code, wrapped in directives, as shown below:
#if TUTORIAL_CUSTOM_DATABASE
// Begin of Tutorial Source Code Modifications
// ...
// ...
// End of Tutorial Source Code Modifications
#endif
Modify Utils.cs.
The default location is C:\LEADTOOLS 19\Examples\PACSFramework\MedicalWebViewer\Leadtools.Medical.WebViewer.WCF\Helper\Utils.cs
Add the following using statements to the top of Utils.cs
using My.Medical.Storage.DataAccessLayer;
using My.Medical.Storage.DataAccessLayer.Entities;
public static void RegisterInterfaces()
{
if (!DataAccessServiceLocator.IsRegistered<IPatientInfo>())
{
DataAccessServiceLocator.Register<IPatientInfo>(new MyPatientInfo());
}
if (!DataAccessServiceLocator.IsRegistered<IStudyInfo>())
{
DataAccessServiceLocator.Register<IStudyInfo>(new MyStudyInfo());
}
if (!DataAccessServiceLocator.IsRegistered<ISeriesInfo>())
{
DataAccessServiceLocator.Register<ISeriesInfo>(new MySeriesInfo());
}
if (!DataAccessServiceLocator.IsRegistered<IInstanceInfo>())
{
DataAccessServiceLocator.Register<IInstanceInfo>(new MyInstanceInfo());
}
if (!DataAccessServices.IsDataAccessServiceRegistered<IStorageDataAccessAgent>())
{
System.Configuration.Configuration configuration = ServiceUtils.GetGlobalPacsConfig();
IStorageDataAccessAgent storageDataAccess = DataAccessFactory.GetInstance(new MyStorageDataAccessConfigurationView(configuration, ServiceUtils.ProductNameStorageServer, null)).CreateDataAccessAgent<IStorageDataAccessAgent>();
DataAccessServices.RegisterDataAccessService<IStorageDataAccessAgent>(storageDataAccess);
}
RegisteredEntities.AddItem(RegisteredEntities.PatientEntityName, typeof(MyPatient));
RegisteredEntities.AddItem(RegisteredEntities.StudyEntityName, typeof(MyStudy));
RegisteredEntities.AddItem(RegisteredEntities.SeriesEntityName, typeof(MySeries));
RegisteredEntities.AddItem(RegisteredEntities.InstanceEntityName, typeof(MyInstance));
}
Build the project to generate the new Leadtools.Medical.WebViewer.WCF assembly.
Step 5: Modify the Leadtools.Medical.WebViewer.Addins Assembly
Start Visual Studio.
Open the Leadtools.Medical.WebViewer.Addins project.
In Solution Explorer, right-click the References folder, and add a reference to your My.Medical.Storage.DataAccessLayer.dll. You created this assembly in the Create the Custom Storage Data Access Layer, and Configuration Assemblies step in the Changing the LEAD Medical Storage Server to Use a Different Database Schema tutorial.
Modify AddInsUtils.cs
The default location is C:\LEADTOOLS 19\Examples\PACSFramework\MedicalWebViewer\Leadtools.Medical.WebViewer.Addins\Common\AddInsUtils.cs.
Add the following using statement to the top of AddInsUtils.cs:
using My.Medical.Storage.DataAccessLayer.Entities;
Modify the FillMatchingParameters() method so that it does the following (for more information, see the FillMatchingParameters Method topic).
public static void FillMatchingParameters(QueryOptions query, MatchingParameterList matchingList)
{
// if we have patient options then create a DB Patient object for matching and copy the values
if (
(query.PatientsOptions != null) &&
(!string.IsNullOrEmpty(query.PatientsOptions.PatientID) ||
!string.IsNullOrEmpty(query.PatientsOptions.PatientName))
)
{
MyPatient patient = new MyPatient();
patient.PatientIdentification =
(!string.IsNullOrEmpty(query.PatientsOptions.PatientID)) ? query.PatientsOptions.PatientID : null;
if (!string.IsNullOrEmpty(query.PatientsOptions.PatientName))
{
patient.PatientName = query.PatientsOptions.PatientName;
}
matchingList.Add(patient);
}
// if we have study options then create a DB study object for matching and copy the values
if ((query.StudiesOptions != null) && (
!string.IsNullOrEmpty(query.StudiesOptions.AccessionNumber) ||
!string.IsNullOrEmpty(query.StudiesOptions.ReferDoctorName) ||
!string.IsNullOrEmpty(query.StudiesOptions.StudyDateStart) ||
!string.IsNullOrEmpty(query.StudiesOptions.StudyDateEnd) ||
!string.IsNullOrEmpty(query.StudiesOptions.StudyID) ||
!string.IsNullOrEmpty(query.StudiesOptions.StudyInstanceUID) ||
(query.StudiesOptions.ModalitiesInStudy != null &&
query.StudiesOptions.ModalitiesInStudy.Length > 0)))
{
MyStudy study = new MyStudy();
study.StudyAccessionNumber =
(!string.IsNullOrEmpty(query.StudiesOptions.AccessionNumber)) ? query.StudiesOptions.AccessionNumber : null;
study.StudyStudyId =
(!string.IsNullOrEmpty(query.StudiesOptions.StudyID)) ? query.StudiesOptions.StudyID : null;
study.StudyStudyInstanceUID =
(!string.IsNullOrEmpty(query.StudiesOptions.StudyInstanceUID)) ? query.StudiesOptions.StudyInstanceUID : null;
if (!string.IsNullOrEmpty(query.StudiesOptions.ReferDoctorName))
{
study.StudyReferringPhysiciansName = query.StudiesOptions.ReferDoctorName;
}
if (!string.IsNullOrEmpty(query.StudiesOptions.StudyDateStart) || !string.IsNullOrEmpty(query.StudiesOptions.StudyDateEnd))
{
study.StudyStudyDate = new DateRange();
AddInsUtils.FillDateRangeInfo(query.StudiesOptions.StudyDateStart, query.StudiesOptions.StudyDateEnd, study.StudyStudyDate);
}
matchingList.Add(study);
if (query.StudiesOptions.ModalitiesInStudy != null && query.StudiesOptions.ModalitiesInStudy.Length > 0)
{
MySeries series = new MySeries();
series.SeriesModality = string.Join("\\", query.StudiesOptions.ModalitiesInStudy);
matchingList.Add(series);
}
}
// Series query options
if ((query.SeriesOptions != null) && (
!string.IsNullOrEmpty(query.SeriesOptions.SeriesInstanceUID) ||
!string.IsNullOrEmpty(query.SeriesOptions.SeriesNumber) ||
(null != query.SeriesOptions.Modality)))
{
MySeries series = new MySeries();
series.SeriesSeriesInstanceUID =
(!string.IsNullOrEmpty(query.SeriesOptions.SeriesInstanceUID)) ? query.SeriesOptions.SeriesInstanceUID : null;
series.SeriesSeriesNumber =
(!string.IsNullOrEmpty(query.SeriesOptions.SeriesNumber)) ? query.SeriesOptions.SeriesNumber : null;
if (!string.IsNullOrEmpty(query.SeriesOptions.Modality))
{
series.SeriesModality = query.SeriesOptions.Modality;
}
matchingList.Add(series);
}
// Instance query options
if ((null != query.InstancesOptions) && (
!string.IsNullOrEmpty(query.InstancesOptions.InstanceNumber) ||
!string.IsNullOrEmpty(query.InstancesOptions.SOPInstanceUID)))
{
MyInstance instance = new MyInstance();
instance.SOPInstanceUID =
(!string.IsNullOrEmpty(query.InstancesOptions.SOPInstanceUID)) ? query.InstancesOptions.SOPInstanceUID : null;
string sImageNumber =
(!string.IsNullOrEmpty(query.InstancesOptions.InstanceNumber)) ? query.InstancesOptions.InstanceNumber : null;
int nImageNumber = 0;
if (int.TryParse(sImageNumber, out nImageNumber))
{
instance.ImageImageNumber = nImageNumber;
}
matchingList.Add(instance);
}
}
Modify DatabaseQueryAddin.cs
The default location is C:\LEADTOOLS 19\Examples\PACSFramework\MedicalWebViewer\Leadtools.Medical.WebViewer.Addins\DatabaseQueryAddin\DatabaseQueryAddin.cs
The tutorial database schema does not store presentation state information, so for the tutorial modify the FindPresentationState() method to always return an empty list.
public PresentationStateData[] FindPresentationState (string userName, string referencedSeries, string userData)
{
return new PresentationStateData[0];
}
Modify StoreAddin.cs
The default location is C:\LEADTOOLS 19\Examples\PACSFramework\MedicalWebViewer\Leadtools.Medical.WebViewer.Addins\StoreAddin\StoreAddin.cs
using My.Medical.Storage.DataAccessLayer.Entities;
While the tutorial database schema does not store presentation state information, it does store and delete presentation state instances. For the tutorial, the FindPresentationInstance method fills the properties of custom classes MySeries and MyInstance with the presentation state modality "PR", and adds these classes to a MatchingParameterList so that the stored presentation state instances can be deleted from the custom database.
Modify the FindPresentationInstanced() method so that it uses the custom ICatalogEntity classes (MySeries and MyInstance). The changes are highlighted in yellow.
private DataSet FindPresentationInstance(string sopInstanceUID, out MatchingParameterCollection matchingCollection)
{
matchingCollection = new MatchingParameterCollection ( ) ;
MatchingParameterList matchingList = new MatchingParameterList ( ) ;
MySeries seriesEntity = new MySeries();
MyInstance instanceEntity = new MyInstance ( sopInstanceUID ) ;
seriesEntity.SeriesModality = "PR" ;
matchingList.Add ( instanceEntity ) ;
matchingList.Add ( seriesEntity ) ;
matchingCollection.Add ( matchingList ) ;
return _storageAgent.QueryCompositeInstances ( matchingCollection ) ;
}
Step 6: Copy the modified assemblies to the Medical Viewer Service Bin folder
Close any browsers running an instance of the Medical Viewer.
Find the location of the medical web viewer services Bin folder by performing the following steps:
Start the Internet Information Services (IIS) Manager.
In the connections pane, open the tree view until you find the MedicalViewerService site.
Right-click the Bin folder, and select Explore - this opens the Bin folder of the Medical Viewer Service, as shown in the following figure:
The default bin location for the medical web viewer services can be found at the following location:
C:\\LEADTOOLS 19\\Examples\\PACSFramework\\MedicalWebViewer\\Leadtools.Medical.WebViewer.WCF\\Bin
Copy Leadtools.Medical.WebViewer.Addins.dll and Leadtools.Medical.WebViewer.WCF.dll to the Medical Viewer Service Bin folder.
If you cannot overwrite the existing versions of these assemblies, perform the following steps:
Open a cmd box.
At the prompt, enter the iisreset command, and press Return.
Try again to copy Leadtools.Medical.WebViewer.Addins.dll and Leadtools.Medical.WebViewer.WCF.dll to the Medical Viewer Service Bin folder.
Copy the My.Medical.Storage.DataAccessLayer.dll assembly to the Medical Viewer Service Bin folder.
Step 7: Verify the HTML5 Medical Web Viewer Demo is using the Custom Database
Open a browser (for example, Internet Explorer) and enter the following URL:
http://localhost/MedicalViewer/members/WebViewer.aspx
Log in with the Username and Password credentials that were defined during database configuration.
Click the Search button to display the existing studies in the custom database.
Click one of the studies to display the existing series in the custom database.
Click one of the series to display the images of the series.