The Web Service interface of the LEADTOOLS Medical Web Viewer Framework enables programmers to quickly build centralized, high-quality, electronic image distribution and management systems. It can complement existing PACS or internal databases and allows distributed systems to securely collaborate using standard Web Service technology over the internet.
Using the framework, a developer with very limited knowledge of web hosting and web service development can easily host Web Services to allow various applications to upload and download images and binary data, manage users and access to patient records, and perform real-time queries on the server from virtually anywhere on the internet.
The plug-in capable design allows developers to easily customize the implementation to suit their own database architecture and quickly adapt it to customer-specific requirements. This design also allows developers to further customize the system by allowing implementation-specific information exchange using the provided web services (i.e. upload/download any document or binary data, add additional information during query or additional information for user management, etc.).
This is the foundation for creating a Web-based image viewer for various life-science-related systems. And, the capability of adding a plug-in dynamically facilitates multi-phase deployment when building a large system.
The WCF Service of the Medical Web Viewer Framework is composed of four endpoints. Each endpoint has its unique address (URI and transport protocol), contracts (interfaces and data types) and bindings (communication patterns).
Each endpoint is represented by a plug-in. A plug-in is an implementation of a service contract that can be dynamically added or removed from the WCF service, thereby enabling custom implementation for the plug-in by a developer. The developer can configure each endpoint address and/or bindings from the WCF service configuration file without writing any extra code.
The following system architecture diagram shows the components within the server-side of the framework as well as the workflow between the components within the framework and to the image archive and the database server outside of the framework.
The LEADTOOLS Medical Web Viewer Framework provides a default implementation for all plug-ins. Developers can easily customize any plug-in to integrate with their own system environment. This can be done by either inheriting from the default plug-ins, directly changing the provided source code of the plug-in or completely writing their own custom implementation for the plug-in by implementing the plug-in interface and configuring the WCF service to use the new customized plug-in.
The framework security model allows clients to securely communicate with the web server. The Medical Web Viewer Framework supports all security options provided by WCF services which can be configured by an administrator without writing any extra code. An administrator can use the WCF security model for message security. The model is based on the open platform secure SOAP messages. Security can be provided by using either user name and password or X.509 certificates for securing the Query, Store and DICOM retrieve plug-ins. Transport level security such as HTTPS can be used on the Manage plug-in. Security can be configured for each plug-in contract independently and with different options.
In addition to secure communication, the LEADTOOL Medical Web Viewer Framework provides and implements management model security. A user and patient record access management system can be built on top of the framework to manage the users accessing the server-side of the framework remotely and from different locations over the web. The framework provides an interface for full user management, including management of various user accounts and assigning the user to a specific roles and groups plus permissions to access patient's records according to the implementation's need.
Auditing security events is also supported by the framework and can be configured to log messages directly to the windows event log or implement any type of custom logging systems.
Please note that because the framework allows each plug-in to be represented by a separate contract (interface and address), a single system can host multiple plug-ins for the same web service. Consequently, developers can create multiple implementations to interact with different back-end systems. Developers can specify different addresses for the plug-ins, although they are hosted by the same WCF service. For example, a system developer can write two separate plug-ins for “DICOM Query": one to query a system database and another to query a different remote PACS. Such a scenario would enable client access to both systems via the framework.
LEADTOOLS developers can change the DICOM Query plug-in and DICOM store plug-in to interface with a PACS database or storage system. The following sample code demonstrates how to implement a new DICOM Query plug-in and integrate it with the WCF service.
Create a new DICOM Query plug-in class by implementing the IDICOMQuery interface:
namespace CustomPlugins
{
public class MyCustomDICOMQueryPlugin : IDICOMQuery
{
public MyCustomDICOMQueryPlugin ( string applicationName )
{
}
public List<ObjectInstanceInformation> FindObjectInstance(string studyInstanceUID,
string seriesInstanceUID,
string instanceNumber,
string SOPInstanceUID,
string extraData)
{
throw new Exception("The method or operation is not implemented.");
}
public System.Data.DataSet FindSeries(string studyInstanceUID,
string modality,
string seriesNumber,
string seriesInstanceUID,
string sortField,
bool ascending,
int maxRows,
string extraData)
{
throw new Exception("The method or operation is not implemented.");
}
public System.Data.DataSet FindStudies(string patientName,
string patientID,
string studyID,
string[] modalitiesInStudy,
string accessionNumber,
string referDrName,
string studyDateStart,
string studyDateEnd,
string studyTimeStart,
string studyTimeEnd,
string studyInstanceUID,
string sortField,
bool ascending,
int maxRows,
string extraData)
{
throw new Exception("The method or operation is not implemented.");
}
public string[] GetDicomFileName(string studyInstanceUID,
string seriesInstanceUID,
string sopInstanceUID,
string extraData)
{
throw new Exception("The method or operation is not implemented.");
}
public List<SOPInstancePreCompressedFormat> GetPrecompressedImagesFormat(string studyInstanceUID,
string seriesInstanceUID,
string sopInstanceUID,
string extraData)
{
throw new Exception("The method or operation is not implemented.");
}
public PreCompressedImageTypes PreCompressedImageExists(string sopInstanceUID,
int imageWidth,
int imageHeight,
string mimeType,
int bitsPerPixel,
int qualityFactor)
{
throw new Exception("The method or operation is not implemented.");
}
}
}
The DICOM Query plug-in interface contains an extraData string parameter for each method used by the WCF service contract. Use it to provide custom information for the user-specific plug-in implementation.
Now that the plug-in has been created, integrate it with the Medical Web Viewer WCF Service. This is performed by altering the WCF service configuration file, and if required, customizing the plug-in factory.
The plug-in factory reads the configuration settings provided in the configuration file to dynamically create the plug-in. This is performed by registering a configuration section in the configuration file, which contains the information required to create and initialize the plug-in. Only change the type of the configuration section to be created and keep the section name element with its original value.
<configSections>
<section
name="dicomServicesPluginFactorySection"
type="Leadtools.Dicom.Services.DICOMServicesConfigurationHandler, Leadtools.Dicom.Services" />
</configSections>
The current implementation provides a configuration section handler which holds the information for each plug-in type and initialization information. There is no need to change this unless you have some extra initialization information that you want to provide for your plug-in. In this case, directly update the source code or inherit from the default configuration section handler and add any extra information required for the plug-in. Then, customize the plug-in factory to handle the new configuration information for your plug-in.
With the custom plug-in that was created earlier, define the new plug-in type in the configuration file for the plug-in factory as follows:
<dicomServicesPluginFactorySection type="Leadtools.Dicom.WCF.DICOMPluginFactory">
<queryConfigurationSection
type="CustomPlugins.MyCustomDICOMQueryPlugin, MyAssemblyName"
connectionStringName="Medical_WebViewerConnectionString"
applicationName="Leadtools Medical Web Viewer" />
...
...
...
</dicomServicesPluginFactorySection>
The configuration section handler expects a connection string section name and application name elements which are required for the default DICOM Query plug-in. This sample custom plug-in only needs the application name for initialization, so fill the connection string section name with any value and customize the plug-in factory to create the DICOM Query plug-in using only the information required. The following is a class derived from the DICOMPluginfactory class which creates and initializes the custom plug-in. Note that you can also update the source code for the factory class.
namespace CustomPluginFactory
{
public class MyCustomPluginFactory : DICOMPluginFactory
{
public override IDICOMQuery GetDICOMQueryPlugIn()
{
Type queryPlugInType ;
IDICOMQuery queryPlugIn ;
queryPlugInType = Type.GetType ( ConfigHandler.QueryConfigurationSection.Type ) ;
queryPlugIn = ( IDICOMQuery ) Activator.CreateInstance ( queryPlugInType,
new object [ ] { ConfigHandler.QueryConfigurationSection.ApplicationName } ) ;
return queryPlugIn ;
}
}
}
Now the new plug-in is ready to use. To register the new factory, update the configuration section and make sure that the new assembly "MyAssemblyName.dll" is located in a place that can be found by the service runtime, such as in the WCF Service Bin folder or the GAC:
<dicomServicesPluginFactorySection type="CustomPluginFactory.MyCustomPluginFactory, MyAssemblyName">
<queryConfigurationSection
type="CustomPlugins.MyCustomDICOMQueryPlugin, MyAssemblyName"
connectionStringName="Medical_WebViewerConnectionString"
applicationName="Leadtools Medical Web Viewer" />
...
...
...
</dicomServicesPluginFactorySection>