diff --git a/Modules/Core/include/mitkMimeType.h b/Modules/Core/include/mitkMimeType.h
index be5dad77fb..785409c9ea 100644
--- a/Modules/Core/include/mitkMimeType.h
+++ b/Modules/Core/include/mitkMimeType.h
@@ -1,102 +1,102 @@
 /*===================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center,
 Division of Medical and Biological Informatics.
 All rights reserved.
 
 This software is distributed WITHOUT ANY WARRANTY; without
 even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.
 
 See LICENSE.txt or http://www.mitk.org for details.
 
 ===================================================================*/
 
 #ifndef MITKMIMETYPE_H
 #define MITKMIMETYPE_H
 
 #include <MitkCoreExports.h>
 
 #include <usSharedData.h>
 
 #include <vector>
 
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable : 4251)
 #endif
 
 namespace mitk
 {
   class CustomMimeType;
 
   /**
    * @ingroup IO
    *
    * @brief The MimeType class represens a registered mime-type. It is an immutable wrapper for mitk::CustomMimeType
    * that makes memory handling easier by providing a stack-object for the user.
    *
    * If you want to register a new MimeType, use the CustomMimeType class instead. Wrapping will be performed for you
    * automatically.
    * In all other cases you should use mitk::MimeType when working with mime-types.
    */
   class MITKCORE_EXPORT MimeType
   {
   public:
     MimeType();
     MimeType(const MimeType &other);
     MimeType(const CustomMimeType &x, int rank, long id);
 
     ~MimeType();
 
     MimeType &operator=(const MimeType &other);
     bool operator==(const MimeType &other) const;
 
     bool operator<(const MimeType &other) const;
 
     /** @See mitk::CustomMimeType::GetName()*/
     std::string GetName() const;
 
     /** @See mitk::CustomMimeType::GetCategory()*/
     std::string GetCategory() const;
 
     /** @See mitk::CustomMimeType::GetExtensions()*/
     std::vector<std::string> GetExtensions() const;
 
     /** @See mitk::CustomMimeType::GetComment()*/
     std::string GetComment() const;
 
     /** @See mitk::CustomMimeType::GetFileNameWithoutExtension()*/
     std::string GetFilenameWithoutExtension(const std::string &path) const;
 
     /** @See mitk::CustomMimeType::AppliesTo()*/
     bool AppliesTo(const std::string &path) const;
 
     /** @See mitk::CustomMimeType::MatchesExtension()*/
     bool MatchesExtension(const std::string &path) const;
 
     /** @See mitk::CustomMimeType::IsValid()*/
     bool IsValid() const;
 
     /** @See mitk::CustomMimeType::Swap()*/
     void Swap(MimeType &m);
 
   private:
     struct Impl;
 
     // Use C++11 shared_ptr instead
     us::SharedDataPointer<const Impl> m_Data;
   };
 
-  void swap(MimeType &m1, MimeType &m2);
+  MITKCORE_EXPORT void swap(MimeType &m1, MimeType &m2);
 
-  std::ostream &operator<<(std::ostream &os, const MimeType &mimeType);
+  MITKCORE_EXPORT std::ostream &operator<<(std::ostream &os, const MimeType &mimeType);
 }
 
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif
 
 #endif // MITKMIMETYPE_H
diff --git a/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp b/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp
index 5f044a9fbf..caed56dd1e 100644
--- a/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp
+++ b/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp
@@ -1,131 +1,195 @@
 /*===================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center,
 Division of Medical and Biological Informatics.
 All rights reserved.
 
 This software is distributed WITHOUT ANY WARRANTY; without
 even the implied warranty of MERCHANTABILITY or FITNESS FOR
 A PARTICULAR PURPOSE.
 
 See LICENSE.txt or http://www.mitk.org for details.
 
 ===================================================================*/
 
 #include "mitkTrackingVolumeGenerator.h"
 #include "mitkStandardFileLocations.h"
 #include "mitkConfig.h"
 #include <vtkCubeSource.h>
 #include <mitkTrackingTypes.h>
 #include <mitkTrackingDevice.h>
 #include <mitkVirtualTrackingDevice.h>
 #include <vtkSmartPointer.h>
 #include <mitkSurface.h>
 #include <mitkIOMimeTypes.h>
 #include <mitkFileReaderRegistry.h>
 
 #include <usModuleContext.h>
 #include <usGetModuleContext.h>
 #include <usModule.h>
 #include <usModuleResource.h>
 #include <usModuleResourceStream.h>
 
+#include <mitkCoreServices.h>
+#include <mitkIFileReader.h>
 #include <mitkIOUtil.h>
+#include <mitkIOMimeTypes.h>
+#include <mitkMimeType.h>
+#include <mitkIMimeTypeProvider.h>
 
 #include "mitkUnspecifiedTrackingTypeInformation.h"
 #include "mitkTrackingDeviceTypeCollection.h"
 
+#include <algorithm>
+
+namespace {
+
+//! Workaround until IOUtil::LoadSurface will guarantee to load mitk::Surface
+//! even in presence of reader services that load STL as another type of
+//! BaseData (T19825).
+mitk::Surface::Pointer LoadCoreSurface(const us::ModuleResource& usResource)
+{
+  us::ModuleResourceStream resStream(usResource, std::ios_base::in);
+
+  mitk::CoreServicePointer<mitk::IMimeTypeProvider> mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider());
+  // get mime types for file (extension) and for surfaces
+  std::vector<mitk::MimeType> mimetypesForFile = mimeTypeProvider->GetMimeTypesForFile(usResource.GetResourcePath());
+  std::vector<mitk::MimeType> mimetypesForSurface = mimeTypeProvider->GetMimeTypesForCategory(mitk::IOMimeTypes::CATEGORY_SURFACES());
+
+  // construct our candidates as the intersection of both sets because we need something that
+  // handles the type type _and_ produces a surface out of it
+  std::vector<mitk::MimeType> mimetypes;
+
+  std::sort(mimetypesForFile.begin(), mimetypesForFile.end());
+  std::sort(mimetypesForSurface.begin(), mimetypesForSurface.end());
+  std::set_intersection(mimetypesForFile.begin(), mimetypesForFile.end(),
+                        mimetypesForSurface.begin(), mimetypesForSurface.end(),
+                        std::back_inserter(mimetypes));
+
+  mitk::Surface::Pointer surface;
+  if (mimetypes.empty())
+  {
+    mitkThrow() << "No mimetype for resource stream: " << usResource.GetResourcePath();
+    return surface;
+  }
+
+  mitk::FileReaderRegistry fileReaderRegistry;
+  std::vector<us::ServiceReference<mitk::IFileReader>> refs = fileReaderRegistry.GetReferences(mimetypes[0]);
+  if (refs.empty())
+  {
+    mitkThrow() << "No reader available for resource stream: " << usResource.GetResourcePath();
+    return surface;
+  }
+
+  mitk::IFileReader *reader = fileReaderRegistry.GetReader(refs[0]);
+  reader->SetInput(usResource.GetResourcePath(), &resStream);
+  auto basedatas = reader->Read();
+  if (!basedatas.empty())
+  {
+    surface = dynamic_cast<mitk::Surface*>(basedatas.front().GetPointer());
+  }
+
+  return surface;
+}
+
+} // unnamed namespace
+
 
 mitk::TrackingVolumeGenerator::TrackingVolumeGenerator()
 {
   m_Data = mitk::UnspecifiedTrackingTypeInformation::GetDeviceDataUnspecified();
 }
 
 void mitk::TrackingVolumeGenerator::SetTrackingDevice (mitk::TrackingDevice::Pointer tracker)
 {
   std::vector<us::ServiceReference<mitk::TrackingDeviceTypeCollection> > refs = us::GetModuleContext()->GetServiceReferences<mitk::TrackingDeviceTypeCollection>();
   if (refs.empty())
   {
     MITK_ERROR << "No tracking device service found!";
   }
   mitk::TrackingDeviceTypeCollection* deviceTypeCollection = us::GetModuleContext()->GetService<mitk::TrackingDeviceTypeCollection>(refs.front());
 
   this->m_Data = deviceTypeCollection->GetFirstCompatibleDeviceDataForLine(tracker->GetType());
 }
 
 void mitk::TrackingVolumeGenerator::GenerateData()
 {
   mitk::Surface::Pointer output = this->GetOutput();  //the surface wich represents the tracking volume
 
-  std::string filepath = ""; // Full path to file (wil be resolved later)
   std::string filename = this->m_Data.VolumeModelLocation; // Name of the file or possibly a magic String, e.g. "cube"
 
   MITK_INFO << "volume: " << filename;
 
   // See if filename matches a magic string.
   if (filename.compare("cube") == 0){
     vtkSmartPointer<vtkCubeSource> cubeSource = vtkSmartPointer<vtkCubeSource>::New();
     double bounds[6];
     bounds[0] = bounds[2] = bounds[4] = -400.0;  // initialize bounds to -400 ... +400 cube. This is the default value of the
     bounds[1] = bounds[3] = bounds[5] =  400.0;  // virtual tracking device, but it can be changed. In that case,
     // the tracking volume polydata has to be updated manually
     cubeSource->SetBounds(bounds);
     cubeSource->Update();
 
     output->SetVtkPolyData(cubeSource->GetOutput()); //set the vtkCubeSource as polyData of the surface
     return;
   }
   if (filename.compare("") == 0) // empty String means no model, return empty output
   {
     // initialize with empty poly data (otherwise old surfaces may be returned) => so an empty surface is returned
     vtkPolyData *emptyPolyData = vtkPolyData::New();
     output->SetVtkPolyData(emptyPolyData);
     emptyPolyData->Delete();
     return;
   }
 
   // from here on, we assume that filename contains an actual filename and not a magic string
 
   us::Module* module = us::GetModuleContext()->GetModule();
-
   us::ModuleResource moduleResource = module->GetResource(filename);
 
-  std::vector<mitk::BaseData::Pointer> data = mitk::IOUtil::Load(moduleResource);
-
-   if(data.empty())
-     MITK_ERROR << "Exception while reading file:";
-
-   mitk::Surface::Pointer fileoutput = dynamic_cast<mitk::Surface*>(data[0].GetPointer());
-
-   output->SetVtkPolyData(fileoutput->GetVtkPolyData());
+  // TODO one would want to call mitk::IOUtils::LoadSurface(moduleResource) here.
+  //      However this function is not guaranteed to find a reader that loads
+  //      named resource as a Surface (given the presence of alternative readers
+  //      that produce another data type but has a higher ranking than the core
+  //      surface reader) - see bug T22608.
+  mitk::Surface::Pointer fileoutput = LoadCoreSurface(moduleResource);
 
+  if (fileoutput == nullptr)
+  {
+     MITK_ERROR << "Exception while casting data loaded from file: " << moduleResource.GetResourcePath();
+     output->SetVtkPolyData(vtkSmartPointer<vtkPolyData>(vtkPolyData::New()));
+  }
+  else
+  {
+      output->SetVtkPolyData(fileoutput->GetVtkPolyData());
+  }
 }
 
 void mitk::TrackingVolumeGenerator::SetTrackingDeviceType(mitk::TrackingDeviceType deviceType)
 {
   std::vector<us::ServiceReference<mitk::TrackingDeviceTypeCollection> > refs = us::GetModuleContext()->GetServiceReferences<mitk::TrackingDeviceTypeCollection>();
   if (refs.empty())
   {
     MITK_ERROR << "No tracking device service found!";
   }
   mitk::TrackingDeviceTypeCollection* deviceTypeCollection = us::GetModuleContext()->GetService<mitk::TrackingDeviceTypeCollection>(refs.front());
 
   m_Data = deviceTypeCollection->GetFirstCompatibleDeviceDataForLine(deviceType);
 }
 
 mitk::TrackingDeviceType mitk::TrackingVolumeGenerator::GetTrackingDeviceType() const
 {
   return m_Data.Line;
 }
 
 void mitk::TrackingVolumeGenerator::SetTrackingDeviceData(mitk::TrackingDeviceData deviceData)
 {
   m_Data= deviceData;
 }
 
 mitk::TrackingDeviceData mitk::TrackingVolumeGenerator::GetTrackingDeviceData() const
 {
   return m_Data;
 }