Click here to Skip to main content
Click here to Skip to main content

eHealthCare

, 13 Nov 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
An application developed for patients , providers and hospitals use to provide a better facility for hospitals , providers and patients.

Please note

This article is an entry in our AppInnovation Contest. Articles in this sub-section are not required to be full articles so care should be taken when voting.


Platform: Windows 8 Desktop 

Name :- EHealthCare 

Category :- Tablet - HealthCare 

Coding language used :- C# .NET 4.5  


Introduction    
 

EHealthCare as the name itself says it's a electronic healthcare application. It's an application developed for patients , providers and hospitals use to provide a better facility for hospitals , providers and patients.  

Here's what it usually happens in a normal electronic health record system. 

Providers or Nurse will register the patient by filling in the patient demographics information. It can start with the patient calling the hospital or by physically attending one of the near by hospitals.  

Patients will call up and take an appointment with the doctor. 

Nurse will schedule the provider who needs to take care of the patient. 

At the given appointment date and time, the patients will be treated and the patients clinical information will be feed to the system.

Registered patients can access their clinical information like Medications, Allergies, Lab results etc. 

Millions of dollars spent in building and maintaining healthcare systems. There are numerous applications available in the market which can help patients in accessing their health records online and can communicate with their physicians. It also includes patient registration and maintenance of patients clinical information. However this application mostly focus on other aspects which are really required for providing a better service for patients apart from maintaining the patient health information. 

How are we providing a better health service for patients , providers and other users of hospitals ? 

Provide a way for patients to record their health condition and upload the audio file to the system which maintains their demographics or clinical information. 

Doctors and nurse will have access to their patients clinical information , also they can listen to their patient health condition before the patients visit the doctor. This also helps the nurse to listen to patients problems , understand their symptoms and associate the patients to the right provider for the better treatment. Also it helps the doctors to understand their patients health condition before the patients arrive them , it in turns reduces the time taken to treat individual patients. 


Technology

1. C# 4.5 WPF Desktop application developed using VS 2012
2. HealthVault SDK
3. SQL Azure
4. WCF Service
5. Microsoft Surface Toolkit for Windows Touch 


Application Features  


Patient Registration – All registered patients clinical information will be stored and maintained in HealthVault. The basic demographics information about the patient will be maintained in a secure cloud based environment.

Manage Patients Clinical Information – It includes managing the patient weight , blood pressure , allergies , diagnosis, medication, lab results etc. 

Search doctors – Patients will be given access to search for near by doctors , we will be using Geo location to search for near by providers. 

Pill information – Providers / Nurse or Patients can get more information regarding the medication prescribed by the doctor. We will be using third party free API - http://pillbox.nlm.nih.gov/ for fetching all these information. 

Skype Integrated Phone call – The application integrates Skype phone call feature , so that patients can directly call the hospital can take up an appointment. An easy to touch dial screen will be build to initiate a call. 

Food nutrition search, analysis – The application will also integrate the food and nutrition search , analysis. We will be using third party API such as ESHA Nutrition  Database API http://developer.esha.com/docs/read/api/v1/Nutrients This service provides a look-up of against a nutrient database documenting more than 13,500 foods. 

Integration to HealthVault - It's one of the most important thing that we are doing as a part of this application development. We will be maintaining the entire patients clinical information in HealthVault. There are lots of advantages by making use of HealthVault. Below I have mentioned few things.

1. Importing or Exporting of patients clinical information.
2. Patients/Providers will have direct access and can manage the clinical information with ease. 

In addition to the above ones , I have a plan to integrate Dicom viewer , where the providers can directly upload the patients medical images to the system and the patients are given an option to view the same. With the touch capabilities , one can easily pinch in zoom/out , rotate the image etc.  

Workflow Diagram 


 

How does the provider or doctor send patient information to HealthVault ? 

A patient visits a lab and takes an Xray of his chest and wants to store his lab results in HealthVault account. The lab's application creates a DOPU (drop-off and pick-up) package in HealthVault containing the patient's results (In this scenario it's Xray images). The following parameters are required for the successful submission of DOPU package. 

DOPU Application ID 

HealthVault Url , say https://platform.healthvault-ppe.com/platform/wildcat.ashx

Pickup Url - https://account.healthvault-ppe.com/patientwelcome.aspx

Patient name - Name of the patient for which the providers wishes to send clinical information.

The secret answer is used to encrypt the DOPU package and to later verify the identity of the user.

HealthVault returns an identity code for the DOPU package. The application then sends the user an email containing the identity code and a link to HealthVault. Alternatively, the lab could give the patient a print-out with the information. The patient goes to the URL and enters the identity code. The patient will have to create new account is not exists. 

The patient is prompted for the answer to the secret question, if the patient enters it correctly, this validates the identity of a person who needs to receive or import the package.

The patient then selects the HealthVault record in which the lab results should be stored.

The data from the DOPU package is saved in patient's HealthVault account. 

 

How does our desktop application will talk to HealthVault ?  

We will be using Software on Device Application (SODA) model to connect our application to HealthVault and fetch the patient clinical information. 

Software on Device Authentication (SODA) applications are client applications that run on a desktop or mobile device.  Every time a user installs a SODA application, the user must authorize that installation of the application to access their HealthVault record.  For instance, if the user is running the same application on both their laptop and desktop, they will need to authorize both installations to access their HealthVault record.

SODA applications are offline applications, and the user is sent to HealthVault only once to authorize the application instance.  After the user has authorized the application instance, they then return to the application.  

How does the patient medical images like XRay etc are handled ? 

Patient medical images will be uploaded using DOPU (drop-off and pick-up). Our application will read all the medical images are show it in a screen so that patients can select one and view images and additional information. 

We will make use of opensource Dicom library i.e fo-dicom (Fellow Oak DICOM for .NET) to read the Dicom images.

Below is the screenshot of the analysis of the sample medical image





Below is the screenshot of how the medical image study in HealtVault. Note - The below medical image which is being uploaded to my Healthvault account , is just for demonstration purpose.


Windows 8 Sensors Usage

1. We will be using GeoLocator to get the location latitude and longitude information and search near by doctors. 

2.
SimpleOrientation sensor to determine the device orientation and render the Dicom images.  

3.
 Touch we will use it extensively for pinch in zoom in/out for Dicom images and also show up the application UI in such a way that it should be easy enough for patients to use controls , navigate etc.   

Background   

Healthcare background knowledge is required to understand the terminologies and concepts of healthcare system. In addition to that to understand the code , one has to have an experience in building desktop applications in WPF technology. 

Using the code

We will see few code snippets of the actual system which is in progress.  Below is the code snippet where the patient selects an audio file (*.wav format) to play and upload.

1. Create an instance of OpenFileDialog
2. Set the required filtering 
3. Show dialog which allows the uses to browse and select an audio file.
4. Once the file is selected, try opening the file. Throw exception if there is an issue in reading the file , some times the file content may be corrupted too. 

private void SelectInputFile()
{
    var ofd = new OpenFileDialog();
    ofd.Filter = "Audio files|*.wav;";
    if (ofd.ShowDialog() == true)
    {
         if (TryOpenInputFile(ofd.FileName))
         {
              InputFile = ofd.FileName;
              IsPlayButtonEnabled = true;
              IsUploadButtonEnabled = true;
         }
         else
         {
              IsPlayButtonEnabled = true;
              IsUploadButtonEnabled = true;
         }
    }
} 

private bool TryOpenInputFile(string file)
{
     bool isValid = false;
     try
     {
         using (var reader = new MediaFoundationReader(file))
         {
             InputFormat = reader.WaveFormat.ToString();
             inputWaveFormat = reader.WaveFormat;
             isValid = true;
         }
     }
     catch (Exception e)
     {
         MessageBox.Show(String.Format("Not a supported input file ({0})", e.Message));
     }
     return isValid;
}

public string InputFile
{
     get { return inputFile; }
     set
     {
         if (inputFile != value)
         {
            inputFile = value;
            OnPropertyChanged("InputFile");
         }
     }
}

public string InputFormat
{
    get { return inputFormat; }
    set
    {
         if (inputFormat != value)
         {
             inputFormat = value;
             OnPropertyChanged("InputFormat");
         }
    }
}
 

Below is the code snippet for audio file upload. 

1. Make use File class to read all the bytes of the input file. 
2. Create an instance of PatientEntity , a data context which handles the CRUD operation. 
3. Create an instance of PatientAudio , set the properties and then make a call to SaveChanges.

private void Upload(int patientId)
{
    var byteArray = File.ReadAllBytes(InputFile);
    try
    {	
         using (var dataContext = new PatientEntities())
         {
             dataContext.PatientAudios.Add(new PatientAudio
             {
                 DateTime = DateTime.Now,
                 PatientId = patientId,
                 FileName = inputFile.Substring(inputFile.LastIndexOf("\\")+1, (inputFile.Length - inputFile.LastIndexOf("\\") -1)),
                 Audio = byteArray
             });
             dataContext.SaveChanges();
         }
         MessageBox.Show("Uploaded Successfully!");
         LoadAudioFilesFromDB();
      }
      catch (Exception ex)
      {
         MessageBox.Show(string.Format("Problem in uploading: {0}", ex.InnerException.Message));
      }
} 

Load audio files from database. Below is the code snippet shows how we are loading the audio files from Patient database. 

private void LoadAudioFilesFromDB(int patientId)
{
   try
   {
        using (var dataContext = new PatientEntities())
        {
             var patientAudios = (from audio in dataContext.PatientAudios
                                         where audio.PatientId == patientId
                                         select audio).ToList();
             foreach (var audio in patientAudios)
             {
                  PatientAudioFilesCollection.Add(new PatientAudioViewModel
                  {
                      DateTime = audio.DateTime,
                      FileName = audio.FileName,
                      AudioId = audio.AudioId 
                  });
             }
         }
    }
    catch (Exception ex)
    {
         MessageBox.Show(string.Format("Problem in loading audio files: {0}", ex.Message));
    }           
}

public ObservableCollection<PatientAudioViewModel> PatientAudioFilesCollection
{
     get { return patientAudioFilesCollection; }
     set
     {
          if (patientAudioFilesCollection != value)
          {
              patientAudioFilesCollection = value;
              OnPropertyChanged("PatientAudioFilesCollection");
          }
     }
} 

Below is the code snippet shows how we are playing an audio from a stream

1. Read all bytes from a input file path. Ideally the code can also be re-used to get the byte array from DB.
2. Create a MemoryStream based on the byte array which is read in step 1.
3. Create an instance of SoundPlayer , passing in the Stream as constructor argument.
4. Make a call to Play method of SoundPlayer to play the audio.  

private void Play()
{
    var byteArray = File.ReadAllBytes(InputFile);
    var stream = new MemoryStream(byteArray);
    var soundPlayer = new SoundPlayer(stream);
    soundPlayer.Play();
} 

Below is the screenshot which shows the usability of the Audio file Load, Upload and Play. As of now it's a demo project , I still need to integrate the Audio Record option. This one will be integrated in our WPF application to allow the patients to record their audio conversation about their health conditions. 

HealthVault Connectivity from Desktop Application

We will some of the basics about how our application can connect to HealthVault and access clinical information. The patient has to provision our application by authorizing with himself with HealthVault and this should be one time process. After the successful provisioning , the patient can access his/her clinical information.Below is the code snippet for provisioning   

public void ProvisionApplication()
{
            // generate a GUID that will be used for the application creation.
            _applicationId = Guid.NewGuid();
            HealthClientApplication client = HealthClientApplication.Create(_applicationId, _masterApplicationId);
            client.StartApplicationCreationProcess();
            // launch dialog box to wait
            MessageBox.Show("Please click on OK button After completing application setup");
            // check if the app is provisioned now
            HealthServiceInstance instance = FindProvisionedServiceInstance();
            if (instance == null)
            {
                MessageBox.Show("The application setup in your browser did not complete.");
                return;
            }
            _serviceInstance = instance;
            _healthClientApplication = client;
            // the app was provisioned
            _healthClientApplication = HealthClientApplication.Create(
                _applicationId,
                _masterApplicationId,
                _serviceInstance);
            // Get list of authorized people
            ApplicationConnection connection = HealthClientApplication.ApplicationConnection;
            List<personinfo> authorizedPeople = new List<personinfo>(connection.GetAuthorizedPeople());
            if (authorizedPeople.Count == 0)
            {
                MessageBox.Show("No records were authorized.  Application setup process did not complete.");
                return;
            }

            PersonInfo personInfo = authorizedPeople[0];
            
            _personId = personInfo.PersonId;
            _recordId = personInfo.SelectedRecord.Id;
            provisioned = true;
            SaveUserSettings();
            MessageBox.Show("Application + " + _applicationId + " is now provisioned");
        } 
</personinfo></personinfo>

Code snippet to get weight information from HealthVault. 

1. Create an HealthClientAuthorizedConnection instance and make a call to get the authorized connection by passing in the PersonId.

2. Create an instance of HealthRecordAccessor with the connection object and RecordId so that we can make use of this to get the HealthRecordSearcher instance.

3. By applying suitable filters , in this case we wish to get the Weight information of the patient, We will be creating a HealthRecordFilter instance with the weight type. 

4. Use the HealthRecordSearcher instance , set the Filters property with the filter instance to get the matching records.

public HealthRecordItemCollection GetWeight()
{
      if (!provisioned)
      {
           MessageBox.Show("Please provision application first");
           return null;
      }
      HealthClientAuthorizedConnection connection =
      HealthClientApplication.CreateAuthorizedConnection(PersonId);
      HealthRecordAccessor accessor = new HealthRecordAccessor(connection, RecordId);
      HealthRecordSearcher searcher = accessor.CreateSearcher();
      HealthRecordFilter filter = new HealthRecordFilter(Weight.TypeId);
      searcher.Filters.Add(filter);
      HealthRecordItemCollection items = searcher.GetMatchingItems()[0];
      return items;
} 

Code snippet to set weight in HealthVault

public void SetWeightOnHealthVault(double weightValue)
{
     if (!provisioned)
     {
          MessageBox.Show("Please provision application first");
          return;
     }
     HealthClientAuthorizedConnection connection =
     HealthClientApplication.CreateAuthorizedConnection(PersonId);
     HealthRecordAccessor accessor = new HealthRecordAccessor(connection, RecordId);
     Weight weight = new Weight();
     weight.Value = new WeightValue(weightValue);
     accessor.NewItem(weight);
} 

Application Prototype Screenshots


Below are the application prototype screenshots.  

Application Main Screen

 

Allergies Screen

 
Medications Screen

 

Pill information screen

 

Application Implementation

There are mainly two applications one for providers or doctors and the other one for patients. Provider will have all access to their patients.  There was a slight change made tois  the application to not to have the HealthVault dependency but instead came up the entire database model required to hold the patient and providers information. The reason being I lately realized that HealthVault access is not supported for all countries and there will be a tight dependency if we rely on HealthVault. 

Here's what the patient does , she/he will register himself and log in to the application for managing his/her clinical information and performing some other interesting and useful stuffs. The application is designed in such a way that it should be easy enough to operate with a simple touch enabled controls and screens for helping he patients and providers to navigate easily and manage patient clinical information. 

The application is designed by mix and matching the Desktop and Web. The contents will be rendered on the screen by using a web browser control. MVC4 Application is designed with actions taking care of functionality. It will be easy for screen redesign , 

Here's the screenshot of the Patient app main screen.  

Here's the patient registration screen, the patients have to register themselves to access and manage their clinical information. It's a simple registration page which captures basic patient demographics information. 




Here's the code snippet for validating the patient log on. The application makes use of opensource Windows 8 style Log on control  - http://wpfsmartlibrary.codeplex.com/wikipage?title=SmartLoginOverlay

private bool validateUser(string username, string password)
{
            var patientDataRepository = new PatientDataRepository();
            password = EncryptDecrypt.EncryptData(password);
            var patient = patientDataRepository.GetPatientByUserNamePassword(username, password);
            if (patient != null)
            {
                if (patient.UserName.Equals(username) && patient.Password.Equals(password))
                {
                    EHealthCareDesktopApp.Properties.Settings.Default.PatientID = patient.PatientId;
                    EHealthCareDesktopApp.Properties.Settings.Default.PatientName = patient.FirstName + "  " + patient.LastName;
                    EHealthCareDesktopApp.Properties.Settings.Default.UniqueIdentifier = patient.UniqueIdentifier;
                    EHealthCareDesktopApp.Properties.Settings.Default.Save();
                    return true;
                }
            }
            return false;
} 

The above code uses certificate. Below is the code snippet for encrypting the password. 

 public static string ReadCert()
 {
            // Load the certificate into an X509Certificate object.
            string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\EHealthCare.cer";
            X509Certificate cert = X509Certificate.CreateFromCertFile(path);
            // return certificate raw data string
            return cert.GetRawCertDataString();
}
        
public static string EncryptData(string Message)
{
            byte[] Results;
            string passphrase = ReadCert();
           
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();
            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(passphrase));
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();
            TDESAlgorithm.Key = TDESKey;
            TDESAlgorithm.Mode = CipherMode.ECB;
            TDESAlgorithm.Padding = PaddingMode.PKCS7;
            byte[] DataToEncrypt = UTF8.GetBytes(Message);
            try
            {
                ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
            }
            finally
            {
                TDESAlgorithm.Clear();
                HashProvider.Clear();
            }
            return Convert.ToBase64String(Results);
} 


We will see how the patient can manage his/her weight. There's a provision for setting the weight goal too. The patients can key in their weight and weight goal over the period of time and can see their weight information pictorially represented in a graph and the information in also show in the grid. Here's the application screenshot.


 

Here's the code snippet for refresh the web browser control with the weight information. 

 private void WindowLoaded(object sender, RoutedEventArgs e)
 {
     dialogWindow = new DialogWindow();
     dialogWindow.Message = "Please Wait!";
     dialogWindow.Show();
     RefreshWebBrowserControl();
 }

 private void RefreshWebBrowserControl()
 {        
     string queryStringParm = string.Format("uniqueGuid={0}&patientId={1}", EHealthCareDesktopApp.Properties.Settings.Default.UniqueIdentifier,
     EHealthCareDesktopApp.Properties.Settings.Default.PatientID);
     webBrowserControl.LoadCompleted += webBrowserControl_LoadCompleted;
     webBrowserControl.Navigate(string.Format("http://ehealthcare.azurewebsites.net/home/weight?{0}", queryStringParm));
 }

void webBrowserControl_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
     dialogWindow.Close();
}
        
private void AddWeightClick(object sender, RoutedEventArgs e)
{
     var manageWeight = new ManageWeight();
     manageWeight.WeightAddedEvent += manageWeight_WeightAddedEvent;
     manageWeight.ShowDialog();
}

void manageWeight_WeightAddedEvent(string message)
{
    if (message.Equals("Success"))
         RefreshWebBrowserControl();
    else
    {
       MessageBox.Show(message);
    }
}   


We will see how patients can manage their blood pressure information.  The screenshot for the same is as below


 

Here's the code snippet for the MVC Controller action.

/// <summary>
/// BloodPressure Action
/// </summary>
/// <param name="uniqueGuid">Unique GUID</param>
/// <param name="patientId">Patient ID</param>
/// <returns></returns>
public ActionResult BloodPressure(string uniqueGuid, int patientId)
{
      BloodPressureDataViewModel bloodPressureViewModel = new BloodPressureDataViewModel();
      try
      {
           bloodPressureViewModel = new BloodPressureDataHelper(uniqueGuid, patientId).GetViewModel();
           ViewBag.Error = "";
      }
      catch (Exception ex)
      {
           ViewBag.Error = ex.Message;
      }
      return View(bloodPressureViewModel);
} 

The application makes use of Chart.js for plotting the graph. Here's the code snippet for showing the chart for the BloodPressure View.

 @if(Model.BloodPressureDataEntity.Count > 0)
    {
    <text>
        var SystolicChartData = {
            labels: @Html.Raw(@Model.BloodPressureDataChart.Labels),
            datasets: [
                    {
                        fillColor : "#f28d66",
                        strokeColor : "rgba(119,183,49,.5)",
                        data: @Model.BloodPressureDataChart.SystolicData 
                    }
                    ,{
                        fillColor : "#0d990b",
                        strokeColor : "rgba(151,187,205,1)",
                        data : @Model.BloodPressureDataChart.DiastolicData
                    }
            ]         
        }
        //Get the canvas & context
        var systoicGraph = $('#graph_systolic');
        var ct = systoicGraph.get(0).getContext('2d');
        var container = $(systoicGraph).parent();
        load();
        function load() {
            var myBar = new Chart( $('#graph_systolic').get(0).getContext("2d") ).Bar( SystolicChartData, stepsOpts );
        }
    </text> 

We will see how the patient medication will be managed. Below is the screenshot for the same.


Here's the code snippet for the medication data repository. The data access layer of the app is build with Repository pattern, single repository for each model for handling the CRUD operation. 

public class MedicationDataRepository
{
        Guid uniqueGuid;
        StringBuilder validationErrors;
        public MedicationDataRepository(Guid uniqueGuid)
        {
            this.uniqueGuid = uniqueGuid;
            validationErrors = new StringBuilder();
        }
        public List<MedicationStregth> GetAllMedicationStrengths()
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.MedicationStregths.ToList();
            }
        }
        public List<MedicationDose> GetAllMedicationDoses()
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.MedicationDoses.ToList();
            }
        }
        public List<MedicationTaken> GetAllMedicationTakens()
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.MedicationTakens.ToList();
            }
        }
        public List<Medication> GetAllMedicationData(int patientID)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.Medications.Where(i => i.PatientId == patientID).OrderBy(e => e.StartDate).ToList();
            }
        }
        public void SaveMedication(Medication medication)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                try
                {
                    medication.UniqueIdentifier = this.uniqueGuid;
                    dataContext.Medications.Add(medication);
                    dataContext.SaveChanges();
                }
                catch (DbEntityValidationException ex)
                {
                    throw new Exception(ex.EntityValidationErrors.GetValidationErrors());
                }
            }  
        }
        public Medication GetMedicationById(int patientID, int medicationId)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.Medications.Where(i => i.Id == medicationId && i.PatientId == patientID &&
                    i.UniqueIdentifier == uniqueGuid).FirstOrDefault();
            }
        }
} 


Code snippet for medication action is as follows. 

/// <summary>
/// Medication Action
/// </summary>
/// <param name="uniqueGuid">Unique GUID</param>
/// <param name="patientId">Patient ID</param>
/// <returns></returns>
public ActionResult Medication(string uniqueGuid, int patientId)
{
       List<MedicationViewModel> medicationsList = new List<MedicationViewModel>();
       try
       {
           var medicationDataHelper = new MedicationDataHelper(uniqueGuid, patientId);
           medicationsList = medicationDataHelper.GetViewModel();
       }
       catch (Exception ex)
       {
           ViewBag.Error = ex.Message;
       }
       return View(medicationsList);
} 

We shall see how the patients can capture or manage their notes or some helpful text as notes. Here's the screenshot for the same.  The actual credit for the notes control (which internally makes use of the WPF InkCanvas) goes to "Sacha Barber" as I have reused his implementation. Here's the reference - http://www.codeproject.com/Articles/19102/Adventures-into-Ink-API-using-WPF

 

Here's the code snippet for the patient notes data repository. 

public class PatientNotesRepository
{
        Guid uniqueGuid;
        public PatientNotesRepository(Guid uniqueGuid)
        {
            this.uniqueGuid = uniqueGuid;
        }

        public PatientNote GetPatientNoteById(int patientID, int patientNoteId)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.PatientNotes.Where(i => i.Id == patientNoteId && i.PatientId == patientID &&
                    i.UniqueIdentifier == uniqueGuid).FirstOrDefault();
            }
        }

        public List<PatientNote> GetAllNotes(int patientID)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.PatientNotes.Where(i => i.PatientId == patientID && i.UniqueIdentifier == uniqueGuid).ToList();
            }
        }

        public void SavePatientNotes(PatientNote patientNotes)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                dataContext.PatientNotes.Add(patientNotes);
                dataContext.SaveChanges();
            }
        }

        public void DeletePatientNotes(int patientID, int patientNoteId)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                var patientNoteToDelete = GetPatientNoteById(patientID, patientNoteId);
                dataContext.PatientNotes.Attach(patientNoteToDelete);
                dataContext.PatientNotes.Remove(patientNoteToDelete);
                dataContext.SaveChanges();
            }            
        }

        public void UpdatePatientNotes(int patientNoteId, PatientNote patientNote)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                var patientNoteToUpdate = GetPatientNoteById(patientNote.PatientId, patientNoteId);
                if (patientNoteToUpdate != null)
                {
                    patientNoteToUpdate.Notes = patientNote.Notes;
                    patientNoteToUpdate.Date = patientNote.Date;
                    patientNoteToUpdate.Subject = patientNote.Subject;
                    dataContext.PatientNotes.Attach(patientNoteToUpdate);
                    dataContext.Entry(patientNoteToUpdate).State = EntityState.Modified;
                    dataContext.SaveChanges();
                }
            }
        }
 } 


We will see how the patients can search for specific drug and know more information about the same. Here's the screenshot for the same. One can search drug by code or by name.



Below is the code snippet for the Drug Controller. We are making use of Aetna CarePass API for fetching the drug information. 

public class DrugController : Controller
{
        public ActionResult DrugSearchByName(string id)
        {
            try
            {
                string HealthDataInitiativeApiKey = ConfigurationManager.AppSettings["HealthDataInitiativeApiKey"].ToString();
                string url = string.Format("https://api.carepass.com/hhs-directory-api/drugs/search?name={0}&apikey={1}", id, HealthDataInitiativeApiKey);
                var webRequestClient = new WebRequestHelper();
                ViewBag.DrugResult = webRequestClient.GetJsonResponse(url);
            }
            catch
            {
                ViewBag.DrugResult = "";
            }
            return View();
        }

        public ActionResult DrugSearchByNDC(string id)
        {
            try
            {
                string HealthDataInitiativeApiKey = ConfigurationManager.AppSettings["HealthDataInitiativeApiKey"].ToString();
                string url = string.Format("https://api.carepass.com/hhs-directory-api/drugs/{0}?apikey={1}", id, HealthDataInitiativeApiKey);
                var webRequestClient = new WebRequestHelper();
                ViewBag.DrugResult = webRequestClient.GetJsonResponse(url);
            }
            catch
            {
                ViewBag.DrugResult = "";
            }
            return View();
        }

        public ActionResult DrugSearchByNDA(string id)
        {
            try
            {
                string HealthDataInitiativeApiKey = ConfigurationManager.AppSettings["HealthDataInitiativeApiKey"].ToString();
                string url = string.Format("https://api.carepass.com/hhs-directory-api/applications/{0}?apikey={1}", id, HealthDataInitiativeApiKey);
                var webRequestClient = new WebRequestHelper();
                ViewBag.DrugResult = webRequestClient.GetJsonResponse(url);
            }
            catch
            {
                ViewBag.DrugResult = "";
            }
            return View();
        }
} 


We will see how the patients can search near by doctors. Note - We are making use of third party API for retrieving the healthcare provider information i.e The Factual HealthCare Provider API. Below is the screenshot of how the application UI looks like. 

For Geo location we are making use of GeoPosition class which is a part of the .NET framework Windows Sensor feature.

 

Here's the  code snippet for the Health Care Provider Controller. It makes use of HealthCareProviderRepository to query and fetch the list of matching providers. 

public class HealthCareProviderController : Controller
{
        [HttpGet]
        public ActionResult GetAllProviders(HealthCareProvider.Models.ProviderFilter filter)
        {
            var providers = GetFilteredProviders(filter);
            return PartialView("ProvidersWebGrid", providers);
        }

        private List<Provider> GetFilteredProviders(HealthCareProvider.Models.ProviderFilter filter)
        {
            var repository = new HealthCareProvider.Models.HealthCareProviderRepository();
            var providers = new List<Provider>();
            var data = repository.GetHealthCareProviderData(filter);
            JObject json = JObject.Parse(data);
            var jss = new JavaScriptSerializer();
            dynamic dynamicData = jss.Deserialize<dynamic>(json["response"]["data"].ToString());
            for (int i = 0; i < dynamicData.Length; i++)
            {
                var item = (dynamicData[i] as System.Collections.Generic.Dictionary<string, object>);
                var provider = new Provider();
                if (item.ContainsKey("name"))
                {
                    provider.Name = item["name"].ToString();
                }
                if (item.ContainsKey("locality"))
                {
                    provider.Locality = item["locality"].ToString();
                }
                if (item.ContainsKey("latitude"))
                {
                    provider.Latitude = item["latitude"].ToString();
                }
                if (item.ContainsKey("longitude"))
                {
                    provider.Longitude = item["longitude"].ToString();
                }
                if (item.ContainsKey("npi_id"))
                {
                    provider.Npi = item["npi_id"].ToString();
                }
                if (item.ContainsKey("address"))
                {
                    provider.Address = item["address"].ToString();
                }
                if (item.ContainsKey("region"))
                {
                    provider.Region = item["region"].ToString();
                }
                providers.Add(provider);
            }
            return providers;
        }
} 


We will see how the patients can find or search near by Pharmacies with in their vicinity. While I was working on this solution, finding for a suitable solution on how to get these information , I got to know a website through which we can easily get the required information. I thought let there be some fun and it was really worth-full to have such features in our application. Here's the website url - http://pharmacy.unarxcard.com/ . Below is screenshot for the same.

 

We will see how the patients can get additional information or know more about the pills that are prescribed by their physicians. Below is the screenshot for the same. Note - We are making use of US Government based PillBox Service for the same. 



Here's the code snippet for fetching the pill information based on the matching filtering criteria's.

public class PillIdentifierController : Controller
{
        public ActionResult Index(string shape, string color, string ingredient)
        {
            List<PillInfoEntity> pillInfoEntities = new List<PillInfoEntity>();
            string url = string.Format("http://pillbox.nlm.nih.gov/PHP/pillboxAPIService.php?key=12345&shape={0}&color={1}&ingredient={2}",
                                        shape, color, ingredient);
            try
            {
                XDocument xmlDocument = XDocument.Load(url);
                pillInfoEntities = (from item in xmlDocument.Descendants("pill")
                                 select new PillInfoEntity
                                 {
                                     Author = item.Element("AUTHOR").Value,
                                     Color = item.Element("SPLCOLOR").Value,
                                     HasImage = item.Element("HAS_IMAGE").Value,
                                     Imprint = item.Element("SPLIMPRINT").Value,
                                     Ingredients = item.Element("INGREDIENTS").Value,
                                     NDC9 = item.Element("NDC9").Value,
                                     ProductCode = item.Element("PRODUCT_CODE").Value,
                                     RxCUI = item.Element("RXCUI").Value,
                                     RxString = item.Element("RXSTRING").Value,
                                     RxTTY = item.Element("RXTTY").Value,
                                     Score = item.Element("SPLSCORE").Value,
                                     Shape = item.Element("SPLSHAPE").Value,
                                     Size = item.Element("SPLSIZE").Value,
                                     ImageUrl = string.Format("http://pillbox.nlm.nih.gov/assets/small/{0}.jpg", item.Element("image_id").Value)
                                 }).ToList();
            }
            catch
            {
            }
            return View(pillInfoEntities);
        }
} 


We will see how the patients can make appointments and upload or associate audio information. Below is the screenshot for the same.

 
Below is the code snippet for the Appointment data repository.

public class AppointmentDataRepository
{ 
        Guid uniqueGuid;

        public AppointmentDataRepository()
        {
        }

        public AppointmentDataRepository(Guid uniqueGuid)
        {
            this.uniqueGuid = uniqueGuid;
        }

        public Guid GetPatientUniqueIdentifier(int patientId)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                var appointment = dataContext.Appointments.FirstOrDefault(a => a.PatientId == patientId);
                return appointment == null ? Guid.Empty : appointment.UniqueIdentifier;
            }
        }

        public List<Specialty> GetAllSpecialties()
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.Specialties.ToList();
            }
        }

        public string GetSpecialtiyName(int specialtyId)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                var specialty = dataContext.Specialties.FirstOrDefault(s => s.Id == specialtyId);
                return specialty == null ? "" : specialty.SpecialityName;
            }
        }

        public Appointment GetAppointmentById(int patientID, int appointmentId)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return dataContext.Appointments.Where(i => i.Id == appointmentId && i.PatientId == patientID &&
                    i.UniqueIdentifier == uniqueGuid).FirstOrDefault();
            }
        }

        public List<Appointment> GetAllAppointmentData(int patientID)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                return (from appointment in dataContext.Appointments
                        where appointment.PatientId == patientID && appointment.UniqueIdentifier == uniqueGuid
                        orderby appointment.StartDate descending
                        select appointment).ToList();
            }
        }

        public void SaveAppointment(Appointment appointment)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                try
                {
                    appointment.UniqueIdentifier = uniqueGuid;
                    dataContext.Appointments.Add(appointment);
                    dataContext.SaveChanges();
                }
                catch (DbEntityValidationException ex)
                {
                    throw new Exception(ex.EntityValidationErrors.GetValidationErrors());
                }
            }
        }

        public void UpdateAppointmentStatus(int appointmentId, int patientID, string status)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                try
                {
                    var appoinmentToUpdate = GetAppointmentById(patientID, appointmentId);
                    if (appoinmentToUpdate != null)
                    {
                        appoinmentToUpdate.Status = status;
                        dataContext.Entry(appoinmentToUpdate).State = EntityState.Modified;
                        dataContext.SaveChanges();
                    }
                }
                catch (DbEntityValidationException ex)
                {
                    throw new Exception(ex.EntityValidationErrors.GetValidationErrors());
                }
            }
        }

        public void UpdateAppointment(int appointmentId, Appointment appointment)
        {
            using (var dataContext = new eHealthCareEntities())
            {
                try
                {
                    var appoinmentToUpdate = GetAppointmentById(appointment.PatientId, appointmentId);
                    if (appoinmentToUpdate != null)
                    {
                        appoinmentToUpdate.ProviderId = appointment.ProviderId;
                        appoinmentToUpdate.Purpose = appointment.Purpose;
                        appoinmentToUpdate.SpecialtyId = appointment.SpecialtyId;
                        appoinmentToUpdate.StartDate = appointment.StartDate;
                        appoinmentToUpdate.Type = appointment.Type;
                        appoinmentToUpdate.EndDate = appointment.EndDate;
                        dataContext.Entry(appoinmentToUpdate).State = EntityState.Modified;
                        dataContext.SaveChanges();
                    }
                }
                catch (DbEntityValidationException ex)
                {
                    throw new Exception(ex.EntityValidationErrors.GetValidationErrors());
                }
            }
 } 

Points of Interest   

It's always very much excited to code something new which includes the usage of Windows Sensors. For now it's all the concepts that you can see in this article with few bits and pieces of code. 

History 

Version 1.0 - Created article and explained the plan at high level. A big picture to understand what exactly we will be doing in the application. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ranjan.D
Web Developer
United States United States
Profile
 
Around 10 years of professional software development experience in analysis, design, development, testing and implementation of enterprise web applications for healthcare domain with good exposure to object-oriented design, software architectures, design patterns, test-driven development and agile practices.
 
In Brief
 
Analyse and create High Level , Detailed Design documents.
Use UML Modelling and create Use Cases , Class Diagram , Component Model , Deployment Diagram, Sequence Diagram in HLD.
 
Area of Working : Dedicated to Microsoft .NET Technologies
Experience with : C# , J2EE , J2ME, Windows Phone 8, Windows Store App
Proficient in: C# , XML , XHTML, XML, HTML5, Javascript, Jquery, CSS, SQL, LINQ, EF
 
Software Development
 
Database: Microsoft SQL Server, FoxPro
Development Frameworks: Microsoft .NET 1.1, 2.0, 3.5, 4.5
UI: Windows Forms, Windows Presentation Foundation, ASP.NET Web Forms and ASP.NET MVC3, MVC4
Coding: WinForm , Web Development, Windows Phone, WinRT Programming, WCF, WebAPI
 
Healthcare Domain Experience
 
CCD, CCR, QRDA, HIE, HL7 V3, Healthcare Interoperability
 
Others:
 
TTD, BDD
 
Education
 
B.E (Computer Science)
 
CodeProject Contest So Far:
 
1. Windows Azure Developer Contest - HealthReunion - A Windows Azure based healthcare product , link - http://www.codeproject.com/Articles/582535/HealthReunion-A-Windows-Azure-based-healthcare-pro
 
2. DnB Developer Contest - DNB Business Lookup and Analytics , link - http://www.codeproject.com/Articles/618344/DNB-Business-Lookup-and-Analytics
 
3. Intel Ultrabook Contest - Journey from development, code signing to publishing my App to Intel AppUp , link - http://www.codeproject.com/Articles/517482/Journey-from-development-code-signing-to-publishin
 
4. Intel App Innovation Contest 2013 - eHealthCare - http://www.codeproject.com/Articles/635815/eHealthCare
 
5. Grand Prize Winner of CodeProject HTML5 &CSS3 Article Contest 2014
 
6. Grand Prize Winner of CodeProject Android Article Contest 2014

Comments and Discussions

 
Questionhow open this project with visual studio PinmemberMember 1131968821-Dec-14 0:55 
AnswerRe: how open this project with visual studio PinmvpRanjan.D21-Dec-14 4:46 
QuestionQuestion PinmemberMember 1131968820-Dec-14 21:35 
AnswerRe: Question PinmvpRanjan.D21-Dec-14 5:34 
Questionmissed lib Pinmembermo7med0921-Nov-14 23:56 
Questionquestion Pinmembermo7med0921-Nov-14 23:06 
AnswerRe: question PinmvpRanjan.D21-Dec-14 5:36 
Questionhelp please [modified] Pinmemberalsaher208820-Nov-14 13:21 
GeneralMy vote of 5 PinmemberBruno Sprecher15-Nov-14 2:37 
QuestionI was hoping you may be able to answer a question that is a little off topic PinmemberMember 213088913-Oct-14 10:49 
AnswerRe: I was hoping you may be able to answer a question that is a little off topic PinmvpRanjan.D13-Oct-14 17:05 
QuestionNICE PROJECT PinmemberMember 109869621-Sep-14 8:18 
AnswerRe: NICE PROJECT PinmvpRanjan.D1-Sep-14 8:37 
Questionabout your article eHealthCare PinmemberMember 1098696228-Aug-14 1:31 
AnswerRe: about your article eHealthCare PinmvpRanjan.D28-Aug-14 1:44 
QuestionSource code? PinmemberMartinKurek13-Nov-13 12:31 
AnswerRe: Source code? PinprofessionalRanjan.D13-Nov-13 12:36 
AnswerRe: Source code? [modified] PinprofessionalRanjan.D13-Nov-13 16:00 
GeneralMy vote of 5 PinprofessionalKshitij Marwah 131-Aug-13 22:41 
GeneralRe: My vote of 5 PinprofessionalRanjan.D8-Sep-13 14:44 
AdminThanks! PinstaffKevin Priddle16-Aug-13 11:09 
QuestionQuestion PinmemberJason Gleim13-Aug-13 9:10 
AnswerRe: Question [modified] PinprofessionalRanjan.D13-Aug-13 10:19 
GeneralMy vote of 5 PingroupGrasshopper.iics13-Aug-13 3:34 
GeneralMy vote of 5 Pinmemberrjgadag13-Aug-13 2:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 13 Nov 2013
Article Copyright 2013 by Ranjan.D
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid