diff --git a/BDInfo/BDInfo.csproj b/BDInfo/BDInfo.csproj
index c598f0f3d8..1d19fec698 100644
--- a/BDInfo/BDInfo.csproj
+++ b/BDInfo/BDInfo.csproj
@@ -34,10 +34,10 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/BDInfo/packages.config b/BDInfo/packages.config
index 3585af4ad8..c6ba3586c6 100644
--- a/BDInfo/packages.config
+++ b/BDInfo/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/DvdLib/DvdLib.csproj b/DvdLib/DvdLib.csproj
index 65626b1eac..350d453a7b 100644
--- a/DvdLib/DvdLib.csproj
+++ b/DvdLib/DvdLib.csproj
@@ -49,10 +49,10 @@
     <Compile Include="Ifo\VideoAttributes.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/DvdLib/packages.config b/DvdLib/packages.config
index 3585af4ad8..c6ba3586c6 100644
--- a/DvdLib/packages.config
+++ b/DvdLib/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index 447d339d19..f42851fc1f 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -481,17 +481,17 @@ private QueryResult<ServerItem> GetUserItems(BaseItem item, StubType? stubType,
         {
             if (item is MusicGenre)
             {
-                return GetMusicGenreItems(item, null, user, sort, startIndex, limit);
+                return GetMusicGenreItems(item, Guid.Empty, user, sort, startIndex, limit);
             }
 
             if (item is MusicArtist)
             {
-                return GetMusicArtistItems(item, null, user, sort, startIndex, limit);
+                return GetMusicArtistItems(item, Guid.Empty, user, sort, startIndex, limit);
             }
 
             if (item is Genre)
             {
-                return GetGenreItems(item, null, user, sort, startIndex, limit);
+                return GetGenreItems(item, Guid.Empty, user, sort, startIndex, limit);
             }
 
             if (!stubType.HasValue || stubType.Value != StubType.Folder)
@@ -1124,10 +1124,10 @@ private QueryResult<ServerItem> GetMusicLatest(BaseItem parent, User user, Inter
 
             var items = _userViewManager.GetLatestItems(new LatestItemsQuery
             {
-                UserId = user.Id.ToString("N"),
+                UserId = user.Id,
                 Limit = 50,
                 IncludeItemTypes = new[] { typeof(Audio).Name },
-                ParentId = parent == null ? null : parent.Id.ToString("N"),
+                ParentId = parent == null ? Guid.Empty : parent.Id,
                 GroupItems = true
 
             }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
@@ -1143,7 +1143,7 @@ private QueryResult<ServerItem> GetNextUp(BaseItem parent, User user, InternalIt
             {
                 Limit = query.Limit,
                 StartIndex = query.StartIndex,
-                UserId = query.User.Id.ToString("N")
+                UserId = query.User.Id
 
             }, new [] { parent }, query.DtoOptions);
 
@@ -1156,10 +1156,10 @@ private QueryResult<ServerItem> GetTvLatest(BaseItem parent, User user, Internal
 
             var items = _userViewManager.GetLatestItems(new LatestItemsQuery
             {
-                UserId = user.Id.ToString("N"),
+                UserId = user.Id,
                 Limit = 50,
                 IncludeItemTypes = new[] { typeof(Episode).Name },
-                ParentId = parent == null ? null : parent.Id.ToString("N"),
+                ParentId = parent == null ? Guid.Empty : parent.Id,
                 GroupItems = false
 
             }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
@@ -1173,10 +1173,10 @@ private QueryResult<ServerItem> GetMovieLatest(BaseItem parent, User user, Inter
 
             var items = _userViewManager.GetLatestItems(new LatestItemsQuery
             {
-                UserId = user.Id.ToString("N"),
+                UserId = user.Id,
                 Limit = 50,
                 IncludeItemTypes = new[] { typeof(Movie).Name },
-                ParentId = parent == null ? null : parent.Id.ToString("N"),
+                ParentId = parent == null ? Guid.Empty : parent.Id,
                 GroupItems = true
 
             }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
@@ -1184,7 +1184,7 @@ private QueryResult<ServerItem> GetMovieLatest(BaseItem parent, User user, Inter
             return ToResult(items);
         }
 
-        private QueryResult<ServerItem> GetMusicArtistItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
+        private QueryResult<ServerItem> GetMusicArtistItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit)
         {
             var query = new InternalItemsQuery(user)
             {
@@ -1204,7 +1204,7 @@ private QueryResult<ServerItem> GetMusicArtistItems(BaseItem item, Guid? parentI
             return ToResult(result);
         }
 
-        private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
+        private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit)
         {
             var query = new InternalItemsQuery(user)
             {
@@ -1224,7 +1224,7 @@ private QueryResult<ServerItem> GetGenreItems(BaseItem item, Guid? parentId, Use
             return ToResult(result);
         }
 
-        private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit)
+        private QueryResult<ServerItem> GetMusicGenreItems(BaseItem item, Guid parentId, User user, SortCriteria sort, int? startIndex, int? limit)
         {
             var query = new InternalItemsQuery(user)
             {
diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs
index 0cd544aeae..9832122bfd 100644
--- a/Emby.Dlna/Didl/DidlBuilder.cs
+++ b/Emby.Dlna/Didl/DidlBuilder.cs
@@ -142,9 +142,9 @@ public void WriteItemElement(DlnaOptions options,
             else
             {
                 var parent = item.DisplayParentId;
-                if (parent.HasValue)
+                if (!parent.Equals(Guid.Empty))
                 {
-                    writer.WriteAttributeString("parentID", GetClientId(parent.Value, null));
+                    writer.WriteAttributeString("parentID", GetClientId(parent, null));
                 }
             }
 
@@ -204,7 +204,7 @@ private void AddVideoResource(DlnaOptions options, XmlWriter writer, BaseItem vi
 
                 streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
                 {
-                    ItemId = GetClientId(video),
+                    ItemId = video.Id,
                     MediaSources = sources.ToArray(sources.Count),
                     Profile = _profile,
                     DeviceId = deviceId,
@@ -517,7 +517,7 @@ private void AddAudioResource(DlnaOptions options, XmlWriter writer, BaseItem au
 
                 streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
                 {
-                    ItemId = GetClientId(audio),
+                    ItemId = audio.Id,
                     MediaSources = sources.ToArray(sources.Count),
                     Profile = _profile,
                     DeviceId = deviceId
@@ -641,13 +641,13 @@ public void WriteFolderElement(XmlWriter writer, BaseItem folder, StubType? stub
                 else
                 {
                     var parent = folder.DisplayParentId;
-                    if (!parent.HasValue)
+                    if (parent.Equals(Guid.Empty))
                     {
                         writer.WriteAttributeString("parentID", "0");
                     }
                     else
                     {
-                        writer.WriteAttributeString("parentID", GetClientId(parent.Value, null));
+                        writer.WriteAttributeString("parentID", GetClientId(parent, null));
                     }
                 }
             }
@@ -1138,7 +1138,7 @@ private ImageDownloadInfo GetImageInfo(BaseItem item, ImageType type)
 
             return new ImageDownloadInfo
             {
-                ItemId = item.Id.ToString("N"),
+                ItemId = item.Id,
                 Type = type,
                 ImageTag = tag,
                 Width = width,
@@ -1150,7 +1150,7 @@ private ImageDownloadInfo GetImageInfo(BaseItem item, ImageType type)
 
         class ImageDownloadInfo
         {
-            internal string ItemId;
+            internal Guid ItemId;
             internal string ImageTag;
             internal ImageType Type;
 
@@ -1189,18 +1189,11 @@ public static string GetClientId(Guid idValue, StubType? stubType)
             return id;
         }
 
-        public static string GetClientId(BaseItem item)
-        {
-            var id = item.Id.ToString("N");
-
-            return id;
-        }
-
         private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
         {
             var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/0/0",
                 _serverAddress,
-                info.ItemId,
+                info.ItemId.ToString("N"),
                 info.Type,
                 info.ImageTag,
                 format,
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index c3dc19a500..6adc558ecb 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -174,13 +174,13 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs
index 6759f005a1..e03ec229d3 100644
--- a/Emby.Dlna/PlayTo/PlayToController.cs
+++ b/Emby.Dlna/PlayTo/PlayToController.cs
@@ -321,12 +321,12 @@ public async Task SendPlayCommand(PlayRequest command, CancellationToken cancell
         {
             _logger.Debug("{0} - Received PlayRequest: {1}", this._session.DeviceName, command.PlayCommand);
 
-            var user = String.IsNullOrEmpty(command.ControllingUserId) ? null : _userManager.GetUserById(command.ControllingUserId);
+            var user = command.ControllingUserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(command.ControllingUserId);
 
             var items = new List<BaseItem>();
-            foreach (string id in command.ItemIds)
+            foreach (var id in command.ItemIds)
             {
-                AddItemFromId(Guid.Parse(id), items);
+                AddItemFromId(id, items);
             }
 
             var startIndex = command.StartIndex ?? 0;
@@ -362,9 +362,9 @@ public async Task SendPlayCommand(PlayRequest command, CancellationToken cancell
                 Playlist.AddRange(playlist);
             }
 
-            if (!String.IsNullOrEmpty(command.ControllingUserId))
+            if (!command.ControllingUserId.Equals(Guid.Empty))
             {
-                _sessionManager.LogSessionActivity(_session.AppName, _session.ApplicationVersion, _session.DeviceId,
+                _sessionManager.LogSessionActivity(_session.Client, _session.ApplicationVersion, _session.DeviceId,
                        _session.DeviceName, _session.RemoteEndPoint, user);
             }
 
@@ -413,7 +413,7 @@ private async Task Seek(long newPosition)
 
                 if (info.Item != null && !EnableClientSideSeek(info))
                 {
-                    var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
+                    var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
                     var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, info.SubtitleStreamIndex);
 
                     await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
@@ -550,7 +550,7 @@ private PlaylistItem GetPlaylistItem(BaseItem item, List<MediaSourceInfo> mediaS
                 {
                     StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions
                     {
-                        ItemId = item.Id.ToString("N"),
+                        ItemId = item.Id,
                         MediaSources = mediaSources.ToArray(mediaSources.Count),
                         Profile = profile,
                         DeviceId = deviceId,
@@ -570,7 +570,7 @@ private PlaylistItem GetPlaylistItem(BaseItem item, List<MediaSourceInfo> mediaS
                 {
                     StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions
                     {
-                        ItemId = item.Id.ToString("N"),
+                        ItemId = item.Id,
                         MediaSources = mediaSources.ToArray(mediaSources.Count),
                         Profile = profile,
                         DeviceId = deviceId,
@@ -741,7 +741,7 @@ private async Task SetAudioStreamIndex(int? newIndex)
                 {
                     var newPosition = GetProgressPositionTicks(media, info) ?? 0;
 
-                    var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
+                    var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
                     var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, newIndex, info.SubtitleStreamIndex);
 
                     await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
@@ -766,7 +766,7 @@ private async Task SetSubtitleStreamIndex(int? newIndex)
                 {
                     var newPosition = GetProgressPositionTicks(media, info) ?? 0;
 
-                    var user = _session.UserId.HasValue ? _userManager.GetUserById(_session.UserId.Value) : null;
+                    var user = !_session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(_session.UserId) : null;
                     var newItem = CreatePlaylistItem(info.Item, user, newPosition, info.MediaSourceId, info.AudioStreamIndex, newIndex);
 
                     await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl, CancellationToken.None).ConfigureAwait(false);
@@ -795,7 +795,7 @@ private async Task SeekAfterTransportChange(long positionTicks, CancellationToke
 
         private class StreamParams
         {
-            public string ItemId { get; set; }
+            public Guid ItemId { get; set; }
 
             public bool IsDirectStream { get; set; }
 
@@ -835,7 +835,7 @@ public async Task<MediaSourceInfo> GetMediaSource(CancellationToken cancellation
                 return MediaSource;
             }
 
-            private static string GetItemId(string url)
+            private static Guid GetItemId(string url)
             {
                 if (string.IsNullOrEmpty(url))
                 {
@@ -853,12 +853,12 @@ private static string GetItemId(string url)
                     {
                         if (parts.Length > i + 1)
                         {
-                            return parts[i + 1];
+                            return Guid.Parse(parts[i + 1]);
                         }
                     }
                 }
 
-                return null;
+                return Guid.Empty;
             }
 
             public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager)
@@ -873,9 +873,7 @@ public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManag
                     ItemId = GetItemId(url)
                 };
 
-                Guid parsedId;
-
-                if (string.IsNullOrWhiteSpace(request.ItemId) || !Guid.TryParse(request.ItemId, out parsedId))
+                if (request.ItemId.Equals(Guid.Empty))
                 {
                     return request;
                 }
@@ -896,9 +894,7 @@ public static StreamParams ParseFromUrl(string url, ILibraryManager libraryManag
                 request.SubtitleStreamIndex = GetIntValue(values, "SubtitleStreamIndex");
                 request.StartPositionTicks = GetLongValue(values, "StartPositionTicks");
 
-                request.Item = string.IsNullOrEmpty(request.ItemId)
-                    ? null
-                    : libraryManager.GetItemById(parsedId);
+                request.Item = libraryManager.GetItemById(request.ItemId);
 
                 request._mediaSourceManager = mediaSourceManager;
 
diff --git a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs
index d31dc155e9..e2d6e43c04 100644
--- a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs
+++ b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs
@@ -18,7 +18,7 @@ public PlaylistItem Create(Photo item, DeviceProfile profile)
             {
                 StreamInfo = new StreamInfo
                 {
-                    ItemId = item.Id.ToString("N"),
+                    ItemId = item.Id,
                     MediaType = DlnaProfileType.Photo,
                     DeviceProfile = profile
                 },
diff --git a/Emby.Dlna/packages.config b/Emby.Dlna/packages.config
index fc087e29c3..7fa2eeafee 100644
--- a/Emby.Dlna/packages.config
+++ b/Emby.Dlna/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
   <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.0" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj b/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj
index c7c10016ad..01006b6306 100644
--- a/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj
+++ b/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj
@@ -35,13 +35,13 @@
       <HintPath>..\packages\ImageMagickSharp.1.0.0.19\lib\net45\ImageMagickSharp.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
diff --git a/Emby.Drawing.ImageMagick/packages.config b/Emby.Drawing.ImageMagick/packages.config
index 2b23a5e0bd..9d33c994b9 100644
--- a/Emby.Drawing.ImageMagick/packages.config
+++ b/Emby.Drawing.ImageMagick/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="ImageMagickSharp" version="1.0.0.19" targetFramework="net452" />
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
index 405e2a658f..21ba38973c 100644
--- a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
+++ b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
@@ -43,13 +43,13 @@
     <Compile Include="StripCollageBuilder.cs" />
     <Compile Include="UnplayedCountIndicator.cs" />
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/Emby.Drawing.Skia/packages.config b/Emby.Drawing.Skia/packages.config
index 5eb4c5824a..86da08bfd2 100644
--- a/Emby.Drawing.Skia/packages.config
+++ b/Emby.Drawing.Skia/packages.config
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
   <package id="SkiaSharp" version="1.58.1" targetFramework="portable45-net45+win8" requireReinstallation="true" />
 </packages>
\ No newline at end of file
diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index 74a7d4dfea..e6a3ab2c69 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -41,13 +41,13 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/Emby.Drawing/packages.config
+++ b/Emby.Drawing/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj
index 471bc3db9f..0e28328048 100644
--- a/Emby.Photos/Emby.Photos.csproj
+++ b/Emby.Photos/Emby.Photos.csproj
@@ -32,13 +32,13 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="TagLib.Portable">
       <HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath>
diff --git a/Emby.Photos/packages.config b/Emby.Photos/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/Emby.Photos/packages.config
+++ b/Emby.Photos/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
index c01f6670cc..298ce5107a 100644
--- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
+++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
@@ -200,7 +200,7 @@ void _sessionManager_SessionEnded(object sender, SessionEventArgs e)
                 Name = name,
                 Type = "SessionEnded",
                 ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint),
-                UserId = session.UserId.HasValue ? session.UserId.Value.ToString("N") : null
+                UserId = !session.UserId.Equals(Guid.Empty) ? session.UserId.ToString("N") : null
             });
         }
 
@@ -326,7 +326,7 @@ void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
                 Name = name,
                 Type = "SessionStarted",
                 ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint),
-                UserId = session.UserId.HasValue ? session.UserId.Value.ToString("N") : null
+                UserId = !session.UserId.Equals(Guid.Empty) ? session.UserId.ToString("N") : null
             });
         }
 
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index b800593d96..8fc8c2501d 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -138,7 +138,7 @@ public IEnumerable<Guid> GetInstalledChannelIds()
 
         public QueryResult<Channel> GetChannelsInternal(ChannelQuery query)
         {
-            var user = string.IsNullOrEmpty(query.UserId)
+            var user = query.UserId.Equals(Guid.Empty)
                 ? null
                 : _userManager.GetUserById(query.UserId);
 
@@ -259,7 +259,7 @@ public QueryResult<Channel> GetChannelsInternal(ChannelQuery query)
 
         public QueryResult<BaseItemDto> GetChannels(ChannelQuery query)
         {
-            var user = string.IsNullOrEmpty(query.UserId)
+            var user = query.UserId.Equals(Guid.Empty)
                 ? null
                 : _userManager.GetUserById(query.UserId);
 
@@ -431,7 +431,6 @@ private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken c
             var parentFolderId = Guid.Empty;
 
             var id = GetInternalChannelId(channelInfo.Name);
-            var idString = id.ToString("N");
 
             var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
 
@@ -459,11 +458,11 @@ private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken c
             }
             item.Path = path;
 
-            if (!string.Equals(item.ChannelId, idString, StringComparison.OrdinalIgnoreCase))
+            if (!item.ChannelId.Equals(id))
             {
                 forceUpdate = true;
             }
-            item.ChannelId = idString;
+            item.ChannelId = id;
 
             if (item.ParentId != parentFolderId)
             {
@@ -545,15 +544,10 @@ public ChannelFeatures GetChannelFeatures(string id)
             return GetChannelFeaturesDto(channel, channelProvider, channelProvider.GetChannelFeatures());
         }
 
-        public bool SupportsSync(string channelId)
+        public bool SupportsSync(Guid channelId)
         {
-            if (string.IsNullOrEmpty(channelId))
-            {
-                throw new ArgumentNullException("channelId");
-            }
-
             //var channel = GetChannel(channelId);
-            var channelProvider = GetChannelProvider(channelId);
+            var channelProvider = GetChannelProvider(channelId.ToString("N"));
 
             return channelProvider.GetChannelFeatures().SupportsContentDownloading;
         }
@@ -697,7 +691,7 @@ public async Task<QueryResult<BaseItem>> GetChannelItemsInternal(InternalItemsQu
             ChannelItemSortField? sortField = null;
             var sortDescending = false;
 
-            var parentItem = query.ParentId.HasValue ? _libraryManager.GetItemById(query.ParentId.Value) : channel;
+            var parentItem = !query.ParentId.Equals(Guid.Empty) ? _libraryManager.GetItemById(query.ParentId) : channel;
 
             var itemsResult = await GetChannelItems(channelProvider,
                 user,
@@ -707,7 +701,7 @@ public async Task<QueryResult<BaseItem>> GetChannelItemsInternal(InternalItemsQu
                 cancellationToken)
                 .ConfigureAwait(false);
 
-            if (!query.ParentId.HasValue)
+            if (query.ParentId.Equals(Guid.Empty))
             {
                 query.Parent = channel;
             }
@@ -821,7 +815,7 @@ private async Task<ChannelItemResult> GetChannelItems(IChannel channel,
 
                 var query = new InternalChannelItemQuery
                 {
-                    UserId = userId,
+                    UserId = user == null ? Guid.Empty : user.Id,
                     SortBy = sortField,
                     SortDescending = sortDescending,
                     FolderId = externalFolderId
@@ -1079,13 +1073,12 @@ private BaseItem GetChannelItemEntity(ChannelItemInfo info, IChannel channelProv
                 _logger.Debug("Forcing update due to ExternalEtag {0}", item.Name);
             }
 
-            var channelIdString = internalChannelId.ToString("N");
-            if (!string.Equals(item.ChannelId, channelIdString, StringComparison.OrdinalIgnoreCase))
+            if (!internalChannelId.Equals(item.ChannelId))
             {
                 forceUpdate = true;
                 _logger.Debug("Forcing update due to ChannelId {0}", item.Name);
             }
-            item.ChannelId = channelIdString;
+            item.ChannelId = internalChannelId;
 
             if (!item.ParentId.Equals(parentFolderId))
             {
@@ -1200,7 +1193,7 @@ internal IChannel GetChannelProvider(Channel channel)
             }
 
             var result = GetAllChannels()
-                .FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase));
+                .FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(channel.ChannelId) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase));
 
             if (result == null)
             {
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index e9e3c58033..157c52b9b7 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -739,7 +739,7 @@ private void SaveItem(BaseItem item, BaseItem topParent, string userDataKey, ISt
                 saveItemStatement.TryBindNull("@EndDate");
             }
 
-            saveItemStatement.TryBind("@ChannelId", item.ChannelId);
+            saveItemStatement.TryBind("@ChannelId", item.ChannelId.Equals(Guid.Empty) ? null : item.ChannelId.ToString("N"));
 
             var hasProgramAttributes = item as IHasProgramAttributes;
             if (hasProgramAttributes != null)
@@ -948,7 +948,10 @@ private void SaveItem(BaseItem item, BaseItem topParent, string userDataKey, ISt
             if (episode != null)
             {
                 saveItemStatement.TryBind("@SeasonName", episode.SeasonName);
-                saveItemStatement.TryBind("@SeasonId", episode.SeasonId);
+
+                var nullableSeasonId = episode.SeasonId.Equals(Guid.Empty) ? (Guid?)null : episode.SeasonId;
+
+                saveItemStatement.TryBind("@SeasonId", nullableSeasonId);
             }
             else
             {
@@ -958,7 +961,9 @@ private void SaveItem(BaseItem item, BaseItem topParent, string userDataKey, ISt
 
             if (hasSeries != null)
             {
-                saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId);
+                var nullableSeriesId = hasSeries.SeriesId.Equals(Guid.Empty) ? (Guid?)null : hasSeries.SeriesId;
+
+                saveItemStatement.TryBind("@SeriesId", nullableSeriesId);
                 saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey);
             }
             else
@@ -1394,7 +1399,7 @@ private BaseItem GetItem(IReadOnlyList<IResultSetValue> reader, InternalItemsQue
 
             if (!reader.IsDBNull(index))
             {
-                item.ChannelId = reader.GetString(index);
+                item.ChannelId = new Guid(reader.GetString(index));
             }
             index++;
 
@@ -3608,12 +3613,12 @@ private List<string> GetWhereClauses(InternalItemsQuery query, IStatement statem
                 whereClauses.Add(string.Format("ChannelId in ({0})", inClause));
             }
 
-            if (query.ParentId.HasValue)
+            if (!query.ParentId.Equals(Guid.Empty))
             {
                 whereClauses.Add("ParentId=@ParentId");
                 if (statement != null)
                 {
-                    statement.TryBind("@ParentId", query.ParentId.Value);
+                    statement.TryBind("@ParentId", query.ParentId);
                 }
             }
 
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index 77a3954ec4..46a1b65243 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -157,7 +157,7 @@ public QueryResult<DeviceInfo> GetDevices(DeviceQuery query)
                 });
             }
 
-            if (!string.IsNullOrEmpty(query.UserId))
+            if (!query.UserId.Equals(Guid.Empty))
             {
                 var user = _userManager.GetUserById(query.UserId);
 
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index cd14e5f151..74d8d95d89 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -553,7 +553,7 @@ private void SetPhotoProperties(BaseItemDto dto, Photo item)
             if (album != null)
             {
                 dto.Album = album.Name;
-                dto.AlbumId = album.Id.ToString("N");
+                dto.AlbumId = album.Id;
             }
         }
 
@@ -571,7 +571,7 @@ private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item)
 
                 if (parentAlbumIds.Count > 0)
                 {
-                    dto.AlbumId = parentAlbumIds[0].ToString("N");
+                    dto.AlbumId = parentAlbumIds[0];
                 }
             }
 
@@ -719,10 +719,10 @@ private void AttachStudios(BaseItemDto dto, BaseItem item)
         {
             dto.Studios = item.Studios
                 .Where(i => !string.IsNullOrEmpty(i))
-                .Select(i => new NameIdPair
+                .Select(i => new NameGuidPair
                 {
                     Name = i,
-                    Id = _libraryManager.GetStudioId(i).ToString("N")
+                    Id = _libraryManager.GetStudioId(i)
                 })
                 .ToArray();
         }
@@ -731,7 +731,7 @@ private void AttachGenreItems(BaseItemDto dto, BaseItem item)
         {
             dto.GenreItems = item.Genres
                 .Where(i => !string.IsNullOrEmpty(i))
-                .Select(i => new NameIdPair
+                .Select(i => new NameGuidPair
                 {
                     Name = i,
                     Id = GetGenreId(i, item)
@@ -739,19 +739,19 @@ private void AttachGenreItems(BaseItemDto dto, BaseItem item)
                 .ToArray();
         }
 
-        private string GetGenreId(string name, BaseItem owner)
+        private Guid GetGenreId(string name, BaseItem owner)
         {
             if (owner is IHasMusicGenres)
             {
-                return _libraryManager.GetMusicGenreId(name).ToString("N");
+                return _libraryManager.GetMusicGenreId(name);
             }
 
             if (owner is Game || owner is GameSystem)
             {
-                return _libraryManager.GetGameGenreId(name).ToString("N");
+                return _libraryManager.GetGameGenreId(name);
             }
 
-            return _libraryManager.GetGenreId(name).ToString("N");
+            return _libraryManager.GetGenreId(name);
         }
 
         /// <summary>
@@ -877,7 +877,7 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
                 }
             }
 
-            dto.Id = GetDtoId(item);
+            dto.Id = item.Id;
             dto.IndexNumber = item.IndexNumber;
             dto.ParentIndexNumber = item.ParentIndexNumber;
 
@@ -951,11 +951,7 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
 
             if (fields.Contains(ItemFields.ParentId))
             {
-                var displayParentId = item.DisplayParentId;
-                if (displayParentId.HasValue)
-                {
-                    dto.ParentId = displayParentId.Value.ToString("N");
-                }
+                dto.ParentId = item.DisplayParentId;
             }
 
             AddInheritedImages(dto, item, options, owner);
@@ -1029,7 +1025,7 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
 
                 if (albumParent != null)
                 {
-                    dto.AlbumId = GetDtoId(albumParent);
+                    dto.AlbumId = albumParent.Id;
 
                     dto.AlbumPrimaryImageTag = GetImageCacheTag(albumParent, ImageType.Primary);
                 }
@@ -1238,19 +1234,9 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
                     dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber;
                 }
 
-                var seasonId = episode.SeasonId;
-                if (seasonId.HasValue)
-                {
-                    dto.SeasonId = seasonId.Value.ToString("N");
-                }
-
                 dto.SeasonName = episode.SeasonName;
-
-                var seriesId = episode.SeriesId;
-                if (seriesId.HasValue)
-                {
-                    dto.SeriesId = seriesId.Value.ToString("N");
-                }
+                dto.SeasonId = episode.SeasonId;
+                dto.SeriesId = episode.SeriesId;
 
                 Series episodeSeries = null;
 
@@ -1287,12 +1273,7 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
             if (season != null)
             {
                 dto.SeriesName = season.SeriesName;
-
-                var seriesId = season.SeriesId;
-                if (seriesId.HasValue)
-                {
-                    dto.SeriesId = seriesId.Value.ToString("N");
-                }
+                dto.SeriesId = season.SeriesId;
 
                 series = null;
 
@@ -1357,7 +1338,7 @@ private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem owner, D
 
             dto.ChannelId = item.ChannelId;
 
-            if (item.SourceType == SourceType.Channel && !string.IsNullOrEmpty(item.ChannelId))
+            if (item.SourceType == SourceType.Channel)
             {
                 var channel = _libraryManager.GetItemById(item.ChannelId);
                 if (channel != null)
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 62fec369da..609d72b066 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -614,13 +614,13 @@
       <HintPath>..\packages\Emby.XmlTv.1.0.14\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 98b1326466..3333c94241 100644
--- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
@@ -316,7 +316,7 @@ private void LibraryUpdateTimerCallback(object state)
         private async void SendChangeNotifications(List<BaseItem> itemsAdded, List<BaseItem> itemsUpdated, List<BaseItem> itemsRemoved, List<Folder> foldersAddedTo, List<Folder> foldersRemovedFrom, CancellationToken cancellationToken)
         {
             var userIds = _sessionManager.Sessions
-                .Select(i => i.UserId ?? Guid.Empty)
+                .Select(i => i.UserId)
                 .Where(i => !i.Equals(Guid.Empty))
                 .Distinct()
                 .ToArray();
@@ -340,11 +340,9 @@ private async void SendChangeNotifications(List<BaseItem> itemsAdded, List<BaseI
                     continue;
                 }
 
-                var userIdString = userId.ToString("N");
-
                 try
                 {
-                    await _sessionManager.SendMessageToUserSessions(new List<string> { userIdString }, "LibraryChanged", info, cancellationToken).ConfigureAwait(false);
+                    await _sessionManager.SendMessageToUserSessions(new List<Guid> { userId }, "LibraryChanged", info, cancellationToken).ConfigureAwait(false);
                 }
                 catch (Exception ex)
                 {
diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
index 34d66bad1a..d41d76c6b8 100644
--- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
@@ -54,7 +54,7 @@ private void _liveTvManager_TimerCancelled(object sender, MediaBrowser.Model.Eve
 
         private async void SendMessage(string name, TimerEventInfo info)
         {
-            var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id.ToString("N")).ToList();
+            var users = _userManager.Users.Where(i => i.Policy.EnableLiveTvAccess).Select(i => i.Id).ToList();
 
             try
             {
diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs
index 7f672d32ed..e5748989e7 100644
--- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs
@@ -171,7 +171,7 @@ private async void SendMessageToUserSession<T>(User user, string name, T data)
         {
             try
             {
-                await _sessionManager.SendMessageToUserSessions(new List<string> { user.Id.ToString("N") }, name, data, CancellationToken.None);
+                await _sessionManager.SendMessageToUserSessions(new List<Guid> { user.Id }, name, data, CancellationToken.None);
             }
             catch (ObjectDisposedException)
             {
diff --git a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs
index 7d93f7495e..97feb32c08 100644
--- a/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs
+++ b/Emby.Server.Implementations/EntryPoints/UsageEntryPoint.cs
@@ -45,14 +45,14 @@ void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
         {
             var session = e.SessionInfo;
 
-            if (!string.IsNullOrEmpty(session.AppName) &&
+            if (!string.IsNullOrEmpty(session.Client) &&
                 !string.IsNullOrEmpty(session.DeviceName) &&
                 !string.IsNullOrEmpty(session.DeviceId) &&
                 !string.IsNullOrEmpty(session.ApplicationVersion))
             {
                 var keys = new List<string>
                 {
-                    session.AppName,
+                    session.Client,
                     session.DeviceName,
                     session.DeviceId,
                     session.ApplicationVersion
@@ -65,7 +65,7 @@ void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
                 {
                     info = new ClientInfo
                     {
-                        AppName = session.AppName,
+                        AppName = session.Client,
                         AppVersion = session.ApplicationVersion,
                         DeviceName = session.DeviceName,
                         DeviceId = session.DeviceId
diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index 16f16a6009..36e29e46ae 100644
--- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -115,9 +115,7 @@ private async Task SendNotifications(List<KeyValuePair<Guid, List<BaseItem>>> ch
 
         private Task SendNotifications(Guid userId, List<BaseItem> changedItems, CancellationToken cancellationToken)
         {
-            var userIdString = userId.ToString("N");
-
-            return _sessionManager.SendMessageToUserSessions(new List<string> { userIdString }, "UserDataChanged", () => GetUserDataChangeInfo(userId, changedItems), cancellationToken);
+            return _sessionManager.SendMessageToUserSessions(new List<Guid> { userId }, "UserDataChanged", () => GetUserDataChangeInfo(userId, changedItems), cancellationToken);
         }
 
         private UserDataChangeInfo GetUserDataChangeInfo(Guid userId, List<BaseItem> changedItems)
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index 1c5d47e3ba..683dc3ace0 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -645,7 +645,7 @@ private void AddAgeHeader(IDictionary<string, string> responseHeaders, DateTime?
         /// <param name="lastDateModified">The last date modified.</param>
         /// <param name="cacheDuration">Duration of the cache.</param>
         /// <returns><c>true</c> if [is not modified] [the specified cache key]; otherwise, <c>false</c>.</returns>
-        private bool IsNotModified(IRequest requestContext, Guid? cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
+        private bool IsNotModified(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
         {
             //var isNotModified = true;
 
@@ -666,8 +666,10 @@ private bool IsNotModified(IRequest requestContext, Guid? cacheKey, DateTime? la
 
             var ifNoneMatchHeader = requestContext.Headers.Get("If-None-Match");
 
+            var hasCacheKey = !cacheKey.Equals(Guid.Empty);
+
             // Validate If-None-Match
-            if ((cacheKey.HasValue || !string.IsNullOrEmpty(ifNoneMatchHeader)))
+            if ((hasCacheKey || !string.IsNullOrEmpty(ifNoneMatchHeader)))
             {
                 Guid ifNoneMatch;
 
@@ -675,7 +677,7 @@ private bool IsNotModified(IRequest requestContext, Guid? cacheKey, DateTime? la
 
                 if (Guid.TryParse(ifNoneMatchHeader, out ifNoneMatch))
                 {
-                    if (cacheKey.HasValue && cacheKey.Value == ifNoneMatch)
+                    if (hasCacheKey && cacheKey.Equals(ifNoneMatch))
                     {
                         return true;
                     }
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
index 4ecdee9fac..88f8967db5 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -61,11 +61,11 @@ private void ValidateUser(IRequest request,
                 }
             }
 
-            var user = string.IsNullOrEmpty(auth.UserId)
+            var user = auth.UserId.Equals(Guid.Empty)
                 ? null
                 : UserManager.GetUserById(auth.UserId);
 
-            if (user == null & !string.IsNullOrEmpty(auth.UserId))
+            if (user == null & !auth.UserId.Equals(Guid.Empty))
             {
                 throw new SecurityException("User with Id " + auth.UserId + " not found");
             }
@@ -162,7 +162,7 @@ private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes
                 return true;
             }
 
-            if (tokenInfo != null && string.IsNullOrEmpty(tokenInfo.UserId))
+            if (tokenInfo != null && tokenInfo.UserId.Equals(Guid.Empty))
             {
                 return true;
             }
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index e51557fa8a..5693b8ce0a 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -140,7 +140,7 @@ private AuthorizationInfo GetAuthorization(IRequest httpReq)
                     var user = _connectManager.GetUserFromExchangeToken(token);
                     if (user != null)
                     {
-                        info.UserId = user.Id.ToString("N");
+                        info.UserId = user.Id;
                     }
                 }
                 httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo;
diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
index 841e2167f1..b25daf554d 100644
--- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -5,6 +5,7 @@
 using MediaBrowser.Controller.Session;
 using System.Threading.Tasks;
 using MediaBrowser.Model.Services;
+using System;
 
 namespace Emby.Server.Implementations.HttpServer.Security
 {
@@ -25,7 +26,7 @@ public SessionInfo GetSession(IRequest requestContext)
         {
             var authorization = _authContext.GetAuthorizationInfo(requestContext);
 
-            var user = string.IsNullOrEmpty(authorization.UserId) ? null : _userManager.GetUserById(authorization.UserId);
+            var user = authorization.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(authorization.UserId);
             return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.RemoteIp, user);
         }
 
@@ -45,7 +46,7 @@ public User GetUser(IRequest requestContext)
         {
             var session = GetSession(requestContext);
 
-            return session == null || !session.UserId.HasValue ? null : _userManager.GetUserById(session.UserId.Value);
+            return session == null || session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId);
         }
 
         public User GetUser(object requestContext)
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index aeec8170bf..206ce2ac30 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1274,9 +1274,9 @@ public BaseItem GetItemById(Guid id)
 
         public List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent)
         {
-            if (query.Recursive && query.ParentId.HasValue)
+            if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
             {
-                var parent = GetItemById(query.ParentId.Value);
+                var parent = GetItemById(query.ParentId);
                 if (parent != null)
                 {
                     SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
@@ -1298,9 +1298,9 @@ public List<BaseItem> GetItemList(InternalItemsQuery query)
 
         public int GetCount(InternalItemsQuery query)
         {
-            if (query.Recursive && query.ParentId.HasValue)
+            if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
             {
-                var parent = GetItemById(query.ParentId.Value);
+                var parent = GetItemById(query.ParentId);
                 if (parent != null)
                 {
                     SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
@@ -1470,9 +1470,9 @@ public QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQue
 
         public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query)
         {
-            if (query.Recursive && query.ParentId.HasValue)
+            if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
             {
-                var parent = GetItemById(query.ParentId.Value);
+                var parent = GetItemById(query.ParentId);
                 if (parent != null)
                 {
                     SetTopParentIdsOrAncestors(query, new List<BaseItem> { parent });
@@ -1538,7 +1538,7 @@ private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem>
         private void AddUserToQuery(InternalItemsQuery query, User user, bool allowExternalContent = true)
         {
             if (query.AncestorIds.Length == 0 &&
-                !query.ParentId.HasValue &&
+                query.ParentId.Equals(Guid.Empty) &&
                 query.ChannelIds.Length == 0 &&
                 query.TopParentIds.Length == 0 &&
                 string.IsNullOrEmpty(query.AncestorWithPresentationUniqueKey) &&
@@ -1547,7 +1547,7 @@ private void AddUserToQuery(InternalItemsQuery query, User user, bool allowExter
             {
                 var userViews = _userviewManager().GetUserViews(new UserViewQuery
                 {
-                    UserId = user.Id.ToString("N"),
+                    UserId = user.Id,
                     IncludeHidden = true,
                     IncludeExternalContent = allowExternalContent
                 });
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 5332c0c980..0dc436800f 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -484,10 +484,10 @@ public async Task<Tuple<LiveStreamResponse, IDirectStreamProvider>> OpenLiveStre
             _logger.Info("Live stream opened: " + json);
             var clone = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json);
 
-            if (!string.IsNullOrEmpty(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = _userManager.GetUserById(request.UserId);
-                var item = string.IsNullOrEmpty(request.ItemId)
+                var item = request.ItemId.Equals(Guid.Empty)
                     ? null
                     : _libraryManager.GetItemById(request.ItemId);
                 SetDefaultAudioAndSubtitleStreamIndexes(item, clone, user);
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index fe776f91ad..3ec5919571 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -35,7 +35,7 @@ public QueryResult<SearchHintInfo> GetSearchHints(SearchQuery query)
         {
             User user = null;
 
-            if (string.IsNullOrEmpty(query.UserId))
+            if (query.UserId.Equals(Guid.Empty))
             {
             }
             else
@@ -169,7 +169,7 @@ private List<SearchHintInfo> GetSearchHints(SearchQuery query, User user)
                 IncludeItemTypes = includeItemTypes.ToArray(includeItemTypes.Count),
                 Limit = query.Limit,
                 IncludeItemsByName = string.IsNullOrEmpty(query.ParentId),
-                ParentId = string.IsNullOrEmpty(query.ParentId) ? (Guid?)null : new Guid(query.ParentId),
+                ParentId = string.IsNullOrEmpty(query.ParentId) ? Guid.Empty : new Guid(query.ParentId),
                 OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
                 Recursive = true,
 
@@ -196,11 +196,11 @@ private List<SearchHintInfo> GetSearchHints(SearchQuery query, User user)
 
             if (searchQuery.IncludeItemTypes.Length == 1 && string.Equals(searchQuery.IncludeItemTypes[0], "MusicArtist", StringComparison.OrdinalIgnoreCase))
             {
-                if (searchQuery.ParentId.HasValue)
+                if (!searchQuery.ParentId.Equals(Guid.Empty))
                 {
-                    searchQuery.AncestorIds = new Guid[] { searchQuery.ParentId.Value };
+                    searchQuery.AncestorIds = new[] { searchQuery.ParentId };
                 }
-                searchQuery.ParentId = null;
+                searchQuery.ParentId = Guid.Empty;
                 searchQuery.IncludeItemsByName = true;
                 searchQuery.IncludeItemTypes = Array.Empty<string>();
                 mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item1).ToList();
diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs
index 6270557c3a..74a44752d7 100644
--- a/Emby.Server.Implementations/Library/UserManager.cs
+++ b/Emby.Server.Implementations/Library/UserManager.cs
@@ -575,7 +575,7 @@ public UserDto GetUserDto(User user, string remoteEndPoint = null)
 
             var dto = new UserDto
             {
-                Id = user.Id.ToString("N"),
+                Id = user.Id,
                 Name = user.Name,
                 HasPassword = hasPassword,
                 HasConfiguredPassword = hasConfiguredPassword,
@@ -779,7 +779,7 @@ public async Task DeleteUser(User user)
 
             if (user.ConnectLinkType.HasValue)
             {
-                await _connectFactory().RemoveConnect(user.Id.ToString("N")).ConfigureAwait(false);
+                await _connectFactory().RemoveConnect(user).ConfigureAwait(false);
             }
 
             var allUsers = Users.ToList();
@@ -1099,7 +1099,7 @@ private UserPolicy GetDefaultPolicy(User user)
         }
 
         private readonly object _policySyncLock = new object();
-        public void UpdateUserPolicy(string userId, UserPolicy userPolicy)
+        public void UpdateUserPolicy(Guid userId, UserPolicy userPolicy)
         {
             var user = GetUserById(userId);
             UpdateUserPolicy(user, userPolicy, true);
@@ -1189,7 +1189,7 @@ public UserConfiguration GetUserConfiguration(User user)
         }
 
         private readonly object _configSyncLock = new object();
-        public void UpdateConfiguration(string userId, UserConfiguration config)
+        public void UpdateConfiguration(Guid userId, UserConfiguration config)
         {
             var user = GetUserById(userId);
             UpdateConfiguration(user, config);
@@ -1259,7 +1259,7 @@ private void UpdateDeviceAccess(User user)
         {
             var existing = _authRepo.Get(new AuthenticationInfoQuery
             {
-                UserId = user.Id.ToString("N")
+                UserId = user.Id
 
             }).Items;
 
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index c4e58b0717..f273bb2eae 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -111,7 +111,7 @@ public Folder[] GetUserViews(UserViewQuery query)
 
                 list.AddRange(channels);
 
-                if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId))
+                if (_liveTvManager.GetEnabledUsers().Select(i => i.Id).Contains(query.UserId))
                 {
                     list.Add(_liveTvManager.GetInternalLiveTvFolder(CancellationToken.None));
                 }
@@ -234,7 +234,7 @@ private List<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery reques
 
             var parents = new List<BaseItem>();
 
-            if (!string.IsNullOrEmpty(parentId))
+            if (!parentId.Equals(Guid.Empty))
             {
                 var parentItem = _libraryManager.GetItemById(parentId);
                 var parentItemChannel = parentItem as Channel;
@@ -242,7 +242,7 @@ private List<BaseItem> GetItemsForLatestItems(User user, LatestItemsQuery reques
                 {
                     return _channelManager.GetLatestChannelItemsInternal(new InternalItemsQuery(user)
                     {
-                        ChannelIds = new Guid[] { new Guid(request.ParentId) },
+                        ChannelIds = new [] { parentId },
                         IsPlayed = request.IsPlayed,
                         StartIndex = request.StartIndex,
                         Limit = request.Limit,
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index f0b7da61cf..3943175e13 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -296,7 +296,7 @@ public async Task RefreshTimers(CancellationToken cancellationToken, IProgress<d
         {
             var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false);
 
-            var tempChannelCache = new Dictionary<string, LiveTvChannel>();
+            var tempChannelCache = new Dictionary<Guid, LiveTvChannel>();
 
             foreach (var timer in timers)
             {
@@ -1372,7 +1372,7 @@ private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, Acti
                 {
                     var liveStreamResponse = await _mediaSourceManager.OpenLiveStreamInternal(new LiveStreamRequest
                     {
-                        ItemId = channelItem.Id.ToString("N"),
+                        ItemId = channelItem.Id,
                         OpenToken = mediaStreamInfo.OpenToken
 
                     }, CancellationToken.None).ConfigureAwait(false);
@@ -2521,16 +2521,16 @@ private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer)
                 query.ChannelIds = new[] { _liveTvManager.GetInternalChannelId(Name, seriesTimer.ChannelId) };
             }
 
-            var tempChannelCache = new Dictionary<string, LiveTvChannel>();
+            var tempChannelCache = new Dictionary<Guid, LiveTvChannel>();
 
             return _libraryManager.GetItemList(query).Cast<LiveTvProgram>().Select(i => CreateTimer(i, seriesTimer, tempChannelCache));
         }
 
-        private TimerInfo CreateTimer(LiveTvProgram parent, SeriesTimerInfo seriesTimer, Dictionary<string, LiveTvChannel> tempChannelCache)
+        private TimerInfo CreateTimer(LiveTvProgram parent, SeriesTimerInfo seriesTimer, Dictionary<Guid, LiveTvChannel> tempChannelCache)
         {
             string channelId = seriesTimer.RecordAnyChannel ? null : seriesTimer.ChannelId;
 
-            if (string.IsNullOrWhiteSpace(channelId) && !string.IsNullOrWhiteSpace(parent.ChannelId))
+            if (string.IsNullOrWhiteSpace(channelId) && !parent.ChannelId.Equals(Guid.Empty))
             {
                 LiveTvChannel channel;
 
@@ -2539,7 +2539,7 @@ private TimerInfo CreateTimer(LiveTvProgram parent, SeriesTimerInfo seriesTimer,
                     channel = _libraryManager.GetItemList(new InternalItemsQuery
                     {
                         IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name },
-                        ItemIds = new[] { new Guid(parent.ChannelId) },
+                        ItemIds = new[] { parent.ChannelId },
                         DtoOptions = new DtoOptions()
 
                     }).Cast<LiveTvChannel>().FirstOrDefault();
@@ -2583,15 +2583,15 @@ private TimerInfo CreateTimer(LiveTvProgram parent, SeriesTimerInfo seriesTimer,
 
         private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo)
         {
-            var tempChannelCache = new Dictionary<string, LiveTvChannel>();
+            var tempChannelCache = new Dictionary<Guid, LiveTvChannel>();
             CopyProgramInfoToTimerInfo(programInfo, timerInfo, tempChannelCache);
         }
 
-        private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo, Dictionary<string, LiveTvChannel> tempChannelCache)
+        private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo timerInfo, Dictionary<Guid, LiveTvChannel> tempChannelCache)
         {
             string channelId = null;
 
-            if (!string.IsNullOrWhiteSpace(programInfo.ChannelId))
+            if (!programInfo.ChannelId.Equals(Guid.Empty))
             {
                 LiveTvChannel channel;
 
@@ -2600,7 +2600,7 @@ private void CopyProgramInfoToTimerInfo(LiveTvProgram programInfo, TimerInfo tim
                     channel = _libraryManager.GetItemList(new InternalItemsQuery
                     {
                         IncludeItemTypes = new string[] { typeof(LiveTvChannel).Name },
-                        ItemIds = new[] { new Guid(programInfo.ChannelId) },
+                        ItemIds = new[] { programInfo.ChannelId },
                         DtoOptions = new DtoOptions()
 
                     }).Cast<LiveTvChannel>().FirstOrDefault();
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
index e11721b8fc..8c74dcb0a4 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -47,7 +47,7 @@ public TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service, Live
                 Name = info.Name,
                 StartDate = info.StartDate,
                 ExternalId = info.Id,
-                ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N"),
+                ChannelId = GetInternalChannelId(service.Name, info.ChannelId),
                 Status = info.Status,
                 SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId) ? null : GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N"),
                 PrePaddingSeconds = info.PrePaddingSeconds,
@@ -131,7 +131,7 @@ public SeriesTimerInfoDto GetSeriesTimerInfoDto(SeriesTimerInfo info, ILiveTvSer
 
             if (!string.IsNullOrEmpty(info.ChannelId))
             {
-                dto.ChannelId = GetInternalChannelId(service.Name, info.ChannelId).ToString("N");
+                dto.ChannelId = GetInternalChannelId(service.Name, info.ChannelId);
             }
 
             if (!string.IsNullOrEmpty(info.ProgramId))
@@ -441,7 +441,7 @@ public async Task<TimerInfo> GetTimerInfo(TimerInfoDto dto, bool isNew, LiveTvMa
                 info.Id = timer.ExternalId;
             }
 
-            if (!string.IsNullOrEmpty(dto.ChannelId) && string.IsNullOrEmpty(info.ChannelId))
+            if (!dto.ChannelId.Equals(Guid.Empty) && string.IsNullOrEmpty(info.ChannelId))
             {
                 var channel = _libraryManager.GetItemById(dto.ChannelId);
 
@@ -507,7 +507,7 @@ public async Task<SeriesTimerInfo> GetSeriesTimerInfo(SeriesTimerInfoDto dto, bo
                 info.Id = timer.ExternalId;
             }
 
-            if (!string.IsNullOrEmpty(dto.ChannelId) && string.IsNullOrEmpty(info.ChannelId))
+            if (!dto.ChannelId.Equals(Guid.Empty) && string.IsNullOrEmpty(info.ChannelId))
             {
                 var channel = _libraryManager.GetItemById(dto.ChannelId);
 
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 8c1f761d41..2fbb7f3478 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -162,7 +162,7 @@ private void EmbyTv_TimerCreated(object sender, GenericEventArgs<TimerInfo> e)
             {
                 Argument = new TimerEventInfo
                 {
-                    ProgramId = _tvDtoService.GetInternalProgramId(service.Name, timer.ProgramId).ToString("N"),
+                    ProgramId = _tvDtoService.GetInternalProgramId(service.Name, timer.ProgramId),
                     Id = timer.Id
                 }
             }, _logger);
@@ -203,7 +203,7 @@ void service_DataSourceChanged(object sender, EventArgs e)
 
         public QueryResult<BaseItem> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken)
         {
-            var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
+            var user = query.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(query.UserId);
 
             var topFolder = GetInternalLiveTvFolder(cancellationToken);
 
@@ -550,7 +550,7 @@ private Tuple<LiveTvProgram, bool, bool> GetProgram(ProgramInfo info, Dictionary
             item.ServiceName = serviceName;
 
             item.Audio = info.Audio;
-            item.ChannelId = channel.Id.ToString("N");
+            item.ChannelId = channel.Id;
             item.CommunityRating = item.CommunityRating ?? info.CommunityRating;
             if ((item.CommunityRating ?? 0).Equals(0))
             {
@@ -756,7 +756,7 @@ public async Task<BaseItemDto> GetProgram(string id, CancellationToken cancellat
 
         public async Task<QueryResult<BaseItemDto>> GetPrograms(ProgramQuery query, DtoOptions options, CancellationToken cancellationToken)
         {
-            var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
+            var user = query.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(query.UserId);
 
             var topFolder = GetInternalLiveTvFolder(cancellationToken);
 
@@ -1470,7 +1470,7 @@ private QueryResult<BaseItem> GetEmbyRecordings(RecordingQuery query, DtoOptions
 
         public QueryResult<BaseItemDto> GetRecordingSeries(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
         {
-            var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
+            var user = query.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(query.UserId);
             if (user != null && !IsLiveTvEnabled(user))
             {
                 return new QueryResult<BaseItemDto>();
@@ -1668,7 +1668,7 @@ public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordin
 
         public QueryResult<BaseItemDto> GetRecordings(RecordingQuery query, DtoOptions options)
         {
-            var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
+            var user = query.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(query.UserId);
 
             RemoveFields(options);
 
@@ -1753,7 +1753,7 @@ public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, Cancell
             {
                 var program = string.IsNullOrEmpty(i.Item1.ProgramId) ?
                     null :
-                    _libraryManager.GetItemById(_tvDtoService.GetInternalProgramId(i.Item2.Name, i.Item1.ProgramId).ToString("N")) as LiveTvProgram;
+                    _libraryManager.GetItemById(_tvDtoService.GetInternalProgramId(i.Item2.Name, i.Item1.ProgramId)) as LiveTvProgram;
 
                 var channel = string.IsNullOrEmpty(i.Item1.ChannelId) ? null : _libraryManager.GetItemById(_tvDtoService.GetInternalChannelId(i.Item2.Name, i.Item1.ChannelId));
 
@@ -1969,7 +1969,7 @@ public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOp
             RemoveFields(options);
 
             var currentProgramsList = new List<BaseItem>();
-            var currentChannelsDict = new Dictionary<string, BaseItemDto>();
+            var currentChannelsDict = new Dictionary<Guid, BaseItemDto>();
 
             var addCurrentProgram = options.AddCurrentProgram;
             var addServiceName = options.Fields.Contains(ItemFields.ServiceName);
@@ -1992,8 +1992,7 @@ public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOp
 
                 if (addCurrentProgram)
                 {
-                    var channelIdString = channel.Id.ToString("N");
-                    var currentProgram = programs.FirstOrDefault(i => string.Equals(i.ChannelId, channelIdString));
+                    var currentProgram = programs.FirstOrDefault(i => channel.Id.Equals(i.ChannelId));
 
                     if (currentProgram != null)
                     {
@@ -2008,13 +2007,10 @@ public void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> tuples, DtoOp
 
                 foreach (var programDto in currentProgramDtos)
                 {
-                    if (!string.IsNullOrWhiteSpace(programDto.ChannelId))
+                    BaseItemDto channelDto;
+                    if (currentChannelsDict.TryGetValue(programDto.ChannelId, out channelDto))
                     {
-                        BaseItemDto channelDto;
-                        if (currentChannelsDict.TryGetValue(programDto.ChannelId, out channelDto))
-                        {
-                            channelDto.CurrentProgram = programDto;
-                        }
+                        channelDto.CurrentProgram = programDto;
                     }
                 }
             }
@@ -2105,7 +2101,7 @@ public async Task<SeriesTimerInfoDto> GetNewTimerDefaults(string programId, Canc
             info.StartDate = program.StartDate;
             info.Name = program.Name;
             info.Overview = program.Overview;
-            info.ProgramId = programDto.Id;
+            info.ProgramId = programDto.Id.ToString("N");
             info.ExternalProgramId = program.ExternalId;
 
             if (program.EndDate.HasValue)
@@ -2146,7 +2142,7 @@ public async Task CreateTimer(TimerInfoDto timer, CancellationToken cancellation
                 {
                     Argument = new TimerEventInfo
                     {
-                        ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId).ToString("N"),
+                        ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId),
                         Id = newTimerId
                     }
                 }, _logger);
@@ -2187,7 +2183,7 @@ public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken
             {
                 Argument = new TimerEventInfo
                 {
-                    ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId).ToString("N"),
+                    ProgramId = _tvDtoService.GetInternalProgramId(timer.ServiceName, info.ProgramId),
                     Id = newTimerId
                 }
             }, _logger);
@@ -2306,9 +2302,9 @@ public Task ResetTuner(string id, CancellationToken cancellationToken)
             return service.ResetTuner(parts[1], cancellationToken);
         }
 
-        public BaseItemDto GetLiveTvFolder(string userId, CancellationToken cancellationToken)
+        public BaseItemDto GetLiveTvFolder(Guid userId, CancellationToken cancellationToken)
         {
-            var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId);
+            var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId);
 
             var folder = GetInternalLiveTvFolder(cancellationToken);
 
@@ -2578,7 +2574,7 @@ private List<BaseItem> GetRecordingFolders(User user, bool refreshChannels)
 
             folders.AddRange(_channelManager().GetChannelsInternal(new MediaBrowser.Model.Channels.ChannelQuery
             {
-                UserId = user.Id.ToString("N"),
+                UserId = user.Id,
                 IsRecordingsFolder = true,
                 RefreshLatestChannelItems = refreshChannels
 
diff --git a/Emby.Server.Implementations/News/NewsEntryPoint.cs b/Emby.Server.Implementations/News/NewsEntryPoint.cs
index 84e7ee5fbf..3ce3d23151 100644
--- a/Emby.Server.Implementations/News/NewsEntryPoint.cs
+++ b/Emby.Server.Implementations/News/NewsEntryPoint.cs
@@ -118,7 +118,7 @@ private Task CreateNotifications(List<NewsItem> items, DateTime? lastUpdate, Can
                 Name = i.Title,
                 Description = i.Description,
                 Url = i.Link,
-                UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList()
+                UserIds = _userManager.Users.Select(u => u.Id).ToArray()
 
             }, cancellationToken));
 
diff --git a/Emby.Server.Implementations/Notifications/NotificationManager.cs b/Emby.Server.Implementations/Notifications/NotificationManager.cs
index 5f436f0a8d..81d0f59f6e 100644
--- a/Emby.Server.Implementations/Notifications/NotificationManager.cs
+++ b/Emby.Server.Implementations/Notifications/NotificationManager.cs
@@ -78,7 +78,7 @@ private Task SendNotification(NotificationRequest request,
             return Task.WhenAll(tasks);
         }
 
-        private IEnumerable<string> GetUserIds(NotificationRequest request, NotificationOption options)
+        private IEnumerable<Guid> GetUserIds(NotificationRequest request, NotificationOption options)
         {
             if (request.SendToUserMode.HasValue)
             {
@@ -86,9 +86,9 @@ private IEnumerable<string> GetUserIds(NotificationRequest request, Notification
                 {
                     case SendToUserType.Admins:
                         return _userManager.Users.Where(i => i.Policy.IsAdministrator)
-                                .Select(i => i.Id.ToString("N"));
+                                .Select(i => i.Id);
                     case SendToUserType.All:
-                        return _userManager.Users.Select(i => i.Id.ToString("N"));
+                        return _userManager.Users.Select(i => i.Id);
                     case SendToUserType.Custom:
                         return request.UserIds;
                     default:
@@ -102,7 +102,7 @@ private IEnumerable<string> GetUserIds(NotificationRequest request, Notification
 
                 return _userManager.Users
                     .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Policy))
-                    .Select(i => i.Id.ToString("N"));
+                    .Select(i => i.Id);
             }
 
             return request.UserIds;
diff --git a/Emby.Server.Implementations/Notifications/Notifications.cs b/Emby.Server.Implementations/Notifications/Notifications.cs
index 222d5aac0f..5744dfa235 100644
--- a/Emby.Server.Implementations/Notifications/Notifications.cs
+++ b/Emby.Server.Implementations/Notifications/Notifications.cs
@@ -452,7 +452,7 @@ async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
         {
             var notification = new NotificationRequest
             {
-                UserIds = new List<string> { e.Argument.Id.ToString("N") },
+                UserIds = new[] { e.Argument.Id },
                 Name = "Welcome to Emby!",
                 Description = "Check back here for more notifications."
             };
diff --git a/Emby.Server.Implementations/Notifications/WebSocketNotifier.cs b/Emby.Server.Implementations/Notifications/WebSocketNotifier.cs
index df8228e2ee..cfadb2c4a8 100644
--- a/Emby.Server.Implementations/Notifications/WebSocketNotifier.cs
+++ b/Emby.Server.Implementations/Notifications/WebSocketNotifier.cs
@@ -40,21 +40,21 @@ void _notificationsRepo_NotificationsMarkedRead(object sender, NotificationReadE
 
             var msg = string.Join("|", list.ToArray(list.Count));
 
-            SendMessageToUserSession(e.UserId, "NotificationsMarkedRead", msg);
+            SendMessageToUserSession(new Guid(e.UserId), "NotificationsMarkedRead", msg);
         }
 
         void _notificationsRepo_NotificationAdded(object sender, NotificationUpdateEventArgs e)
         {
             var msg = e.Notification.UserId + "|" + e.Notification.Id;
 
-            SendMessageToUserSession(e.Notification.UserId, "NotificationAdded", msg);
+            SendMessageToUserSession(new Guid(e.Notification.UserId), "NotificationAdded", msg);
         }
 
-        private async void SendMessageToUserSession<T>(string userId, string name, T data)
+        private async void SendMessageToUserSession<T>(Guid userId, string name, T data)
         {
             try
             {
-                await _sessionManager.SendMessageToUserSessions(new List<string> { userId }, name, data, CancellationToken.None);
+                await _sessionManager.SendMessageToUserSessions(new List<Guid> { userId }, name, data, CancellationToken.None);
             }
             catch (ObjectDisposedException)
             {
diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
index f0cb4e6709..e0a6f56ecf 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
@@ -41,7 +41,7 @@ public PlaylistManager(ILibraryManager libraryManager, IFileSystem fileSystem, I
             _providerManager = providerManager;
         }
 
-        public IEnumerable<Playlist> GetPlaylists(string userId)
+        public IEnumerable<Playlist> GetPlaylists(Guid userId)
         {
             var user = _userManager.GetUserById(userId);
 
@@ -54,7 +54,7 @@ public async Task<PlaylistCreationResult> CreatePlaylist(PlaylistCreationRequest
 
             var folderName = _fileSystem.GetValidFilename(name) + " [playlist]";
 
-            var parentFolder = GetPlaylistsFolder(null);
+            var parentFolder = GetPlaylistsFolder(Guid.Empty);
 
             if (parentFolder == null)
             {
@@ -126,7 +126,7 @@ public async Task<PlaylistCreationResult> CreatePlaylist(PlaylistCreationRequest
                     {
                         new Share
                         {
-                            UserId = options.UserId,
+                            UserId = options.UserId.Equals(Guid.Empty) ? null : options.UserId.ToString("N"),
                             CanEdit = true
                         }
                     }
@@ -169,16 +169,16 @@ private string GetTargetPath(string path)
             return path;
         }
 
-        private List<BaseItem> GetPlaylistItems(IEnumerable<string> itemIds, string playlistMediaType, User user, DtoOptions options)
+        private List<BaseItem> GetPlaylistItems(IEnumerable<Guid> itemIds, string playlistMediaType, User user, DtoOptions options)
         {
             var items = itemIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null);
 
             return Playlist.GetPlaylistItems(playlistMediaType, items, user, options);
         }
 
-        public void AddToPlaylist(string playlistId, IEnumerable<string> itemIds, string userId)
+        public void AddToPlaylist(string playlistId, IEnumerable<Guid> itemIds, Guid userId)
         {
-            var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId);
+            var user = userId.Equals(Guid.Empty) ? null : _userManager.GetUserById(userId);
 
             AddToPlaylistInternal(playlistId, itemIds, user, new DtoOptions(false)
             {
@@ -186,7 +186,7 @@ public void AddToPlaylist(string playlistId, IEnumerable<string> itemIds, string
             });
         }
 
-        private void AddToPlaylistInternal(string playlistId, IEnumerable<string> itemIds, User user, DtoOptions options)
+        private void AddToPlaylistInternal(string playlistId, IEnumerable<Guid> itemIds, User user, DtoOptions options)
         {
             var playlist = _libraryManager.GetItemById(playlistId) as Playlist;
 
@@ -493,7 +493,7 @@ private static string Escape(string content)
             return content.Replace("&", "&amp;").Replace("'", "&apos;").Replace("\"", "&quot;").Replace(">", "&gt;").Replace("<", "&lt;");
         }
 
-        public Folder GetPlaylistsFolder(string userId)
+        public Folder GetPlaylistsFolder(Guid userId)
         {
             var typeName = "PlaylistsFolder";
 
diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
index 6edee9dbd2..1a2c2ebcc0 100644
--- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs
+++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
@@ -81,7 +81,7 @@ public void Update(AuthenticationInfo info, CancellationToken cancellationToken)
                             statement.TryBind("@AppName", info.AppName);
                             statement.TryBind("@AppVersion", info.AppVersion);
                             statement.TryBind("@DeviceName", info.DeviceName);
-                            statement.TryBind("@UserId", info.UserId);
+                            statement.TryBind("@UserId", (info.UserId.Equals(Guid.Empty) ? null : info.UserId.ToString("N")));
                             statement.TryBind("@IsActive", info.IsActive);
                             statement.TryBind("@DateCreated", info.DateCreated.ToDateTimeParamValue());
 
@@ -111,9 +111,9 @@ private void BindAuthenticationQueryParams(AuthenticationInfoQuery query, IState
                 statement.TryBind("@AccessToken", query.AccessToken);
             }
 
-            if (!string.IsNullOrEmpty(query.UserId))
+            if (!query.UserId.Equals(Guid.Empty))
             {
-                statement.TryBind("@UserId", query.UserId);
+                statement.TryBind("@UserId", query.UserId.ToString("N"));
             }
 
             if (!string.IsNullOrEmpty(query.DeviceId))
@@ -145,7 +145,7 @@ public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
                 whereClauses.Add("AccessToken=@AccessToken");
             }
 
-            if (!string.IsNullOrEmpty(query.UserId))
+            if (!query.UserId.Equals(Guid.Empty))
             {
                 whereClauses.Add("UserId=@UserId");
             }
@@ -301,7 +301,7 @@ private AuthenticationInfo Get(IReadOnlyList<IResultSetValue> reader)
 
             if (reader[6].SQLiteType != SQLiteType.Null)
             {
-                info.UserId = reader[6].ToString();
+                info.UserId = new Guid(reader[6].ToString());
             }
 
             info.IsActive = reader[7].ToBool();
diff --git a/Emby.Server.Implementations/Serialization/JsonSerializer.cs b/Emby.Server.Implementations/Serialization/JsonSerializer.cs
index 67f17731d4..26371d21d5 100644
--- a/Emby.Server.Implementations/Serialization/JsonSerializer.cs
+++ b/Emby.Server.Implementations/Serialization/JsonSerializer.cs
@@ -220,6 +220,18 @@ private void Configure()
             ServiceStack.Text.JsConfig.IncludeNullValues = false;
             ServiceStack.Text.JsConfig.AlwaysUseUtc = true;
             ServiceStack.Text.JsConfig.AssumeUtc = true;
+
+            ServiceStack.Text.JsConfig<Guid>.SerializeFn = SerializeGuid;
+        }
+
+        private string SerializeGuid(Guid guid)
+        {
+            if (guid.Equals(Guid.Empty))
+            {
+                return null;
+            }
+
+            return guid.ToString("N");
         }
 
         /// <summary>
diff --git a/Emby.Server.Implementations/Session/HttpSessionController.cs b/Emby.Server.Implementations/Session/HttpSessionController.cs
index 4acbad638e..ff9b3fefc8 100644
--- a/Emby.Server.Implementations/Session/HttpSessionController.cs
+++ b/Emby.Server.Implementations/Session/HttpSessionController.cs
@@ -79,7 +79,7 @@ private Task SendPlayCommand(PlayRequest command, string messageId, Cancellation
         {
             var dict = new Dictionary<string, string>();
 
-            dict["ItemIds"] = string.Join(",", command.ItemIds);
+            dict["ItemIds"] = string.Join(",", command.ItemIds.Select(i => i.ToString("N")).ToArray());
 
             if (command.StartPositionTicks.HasValue)
             {
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index fc03f70905..b665136db9 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -30,6 +30,7 @@
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Threading;
 using MediaBrowser.Model.Extensions;
+using MediaBrowser.Controller.Authentication;
 
 namespace Emby.Server.Implementations.Session
 {
@@ -180,7 +181,7 @@ public void UpdateDeviceName(string sessionId, string deviceName)
         {
             var session = GetSession(sessionId);
 
-            var key = GetSessionKey(session.AppName, session.DeviceId);
+            var key = GetSessionKey(session.Client, session.DeviceId);
 
             if (session != null)
             {
@@ -273,7 +274,7 @@ public void CloseIfNeeded(SessionInfo session)
         {
             if (!session.SessionControllers.Any(i => i.IsSessionActive))
             {
-                var key = GetSessionKey(session.AppName, session.DeviceId);
+                var key = GetSessionKey(session.Client, session.DeviceId);
 
                 SessionInfo removed;
                 _activeConnections.TryRemove(key, out removed);
@@ -289,7 +290,7 @@ public void ReportSessionEnded(string sessionId)
 
             if (session != null)
             {
-                var key = GetSessionKey(session.AppName, session.DeviceId);
+                var key = GetSessionKey(session.Client, session.DeviceId);
 
                 SessionInfo removed;
                 _activeConnections.TryRemove(key, out removed);
@@ -310,14 +311,14 @@ private async Task UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInf
         {
             if (string.IsNullOrEmpty(info.MediaSourceId))
             {
-                info.MediaSourceId = info.ItemId;
+                info.MediaSourceId = info.ItemId.ToString("N");
             }
 
-            if (!string.IsNullOrEmpty(info.ItemId) && info.Item == null && libraryItem != null)
+            if (!info.ItemId.Equals(Guid.Empty) && info.Item == null && libraryItem != null)
             {
                 var current = session.NowPlayingItem;
 
-                if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase))
+                if (current == null || !info.ItemId.Equals(current.Id))
                 {
                     var runtimeTicks = libraryItem.RunTimeTicks;
 
@@ -361,6 +362,14 @@ private async Task UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInf
             session.PlayState.SubtitleStreamIndex = info.SubtitleStreamIndex;
             session.PlayState.PlayMethod = info.PlayMethod;
             session.PlayState.RepeatMode = info.RepeatMode;
+            session.PlaylistItemId = info.PlaylistItemId;
+
+            var nowPlayingQueue = info.NowPlayingQueue;
+
+            if (nowPlayingQueue != null)
+            {
+                session.NowPlayingQueue = nowPlayingQueue;
+            }
         }
 
         /// <summary>
@@ -404,22 +413,20 @@ private SessionInfo GetSessionInfo(string appName, string appVersion, string dev
             }
             var key = GetSessionKey(appName, deviceId);
 
-            var userId = user == null ? (Guid?)null : user.Id;
-            var username = user == null ? null : user.Name;
-
             CheckDisposed();
 
             SessionInfo sessionInfo = _activeConnections.GetOrAdd(key, k =>
             {
-                return CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, userId, username);
+                return CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, user);
             });
 
-            sessionInfo.UserId = userId;
-            sessionInfo.UserName = username;
+            sessionInfo.UserId = user == null ? Guid.Empty : user.Id;
+            sessionInfo.UserName = user == null ? null : user.Name;
+            sessionInfo.UserPrimaryImageTag = user == null ? null : GetImageCacheTag(user, ImageType.Primary);
             sessionInfo.RemoteEndPoint = remoteEndPoint;
             sessionInfo.ApplicationVersion = appVersion;
 
-            if (!userId.HasValue)
+            if (user == null)
             {
                 sessionInfo.AdditionalUsers = new SessionUserInfo[] { };
             }
@@ -427,20 +434,23 @@ private SessionInfo GetSessionInfo(string appName, string appVersion, string dev
             return sessionInfo;
         }
 
-        private SessionInfo CreateSession(string key, string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Guid? userId, string username)
+        private SessionInfo CreateSession(string key, string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user)
         {
             DeviceInfo device = null;
 
             var sessionInfo = new SessionInfo(this, _logger)
             {
-                AppName = appName,
+                Client = appName,
                 DeviceId = deviceId,
                 ApplicationVersion = appVersion,
                 Id = key.GetMD5().ToString("N")
             };
 
-            sessionInfo.UserId = userId;
+            var username = user == null ? null : user.Name;
+
+            sessionInfo.UserId = user == null ? Guid.Empty : user.Id;
             sessionInfo.UserName = username;
+            sessionInfo.UserPrimaryImageTag = user == null ? null : GetImageCacheTag(user, ImageType.Primary);
             sessionInfo.RemoteEndPoint = remoteEndPoint;
 
             if (string.IsNullOrEmpty(deviceName))
@@ -450,7 +460,7 @@ private SessionInfo CreateSession(string key, string appName, string appVersion,
 
             if (!string.IsNullOrEmpty(deviceId))
             {
-                var userIdString = userId.HasValue ? userId.Value.ToString("N") : null;
+                var userIdString = user != null ? user.Id.ToString("N") : null;
                 device = _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString, username);
             }
 
@@ -472,9 +482,9 @@ private List<User> GetUsers(SessionInfo session)
         {
             var users = new List<User>();
 
-            if (session.UserId.HasValue)
+            if (!session.UserId.Equals(Guid.Empty))
             {
-                var user = _userManager.GetUserById(session.UserId.Value);
+                var user = _userManager.GetUserById(session.UserId);
 
                 if (user == null)
                 {
@@ -483,11 +493,9 @@ private List<User> GetUsers(SessionInfo session)
 
                 users.Add(user);
 
-                var additionalUsers = session.AdditionalUsers
+                users.AddRange(session.AdditionalUsers
                     .Select(i => _userManager.GetUserById(i.UserId))
-                    .Where(i => i != null);
-
-                users.AddRange(additionalUsers);
+                    .Where(i => i != null));
             }
 
             return users;
@@ -531,7 +539,7 @@ private async void CheckForIdlePlayback(object state)
                         await OnPlaybackStopped(new PlaybackStopInfo
                         {
                             Item = session.NowPlayingItem,
-                            ItemId = session.NowPlayingItem == null ? null : session.NowPlayingItem.Id,
+                            ItemId = session.NowPlayingItem == null ? Guid.Empty : session.NowPlayingItem.Id,
                             SessionId = session.Id,
                             MediaSourceId = session.PlayState == null ? null : session.PlayState.MediaSourceId,
                             PositionTicks = session.PlayState == null ? null : session.PlayState.PositionTicks
@@ -553,12 +561,10 @@ await OnPlaybackStopped(new PlaybackStopInfo
             }
         }
 
-        private BaseItem GetNowPlayingItem(SessionInfo session, string itemId)
+        private BaseItem GetNowPlayingItem(SessionInfo session, Guid itemId)
         {
-            var idGuid = new Guid(itemId);
-
             var item = session.FullNowPlayingItem;
-            if (item != null && item.Id == idGuid)
+            if (item != null && item.Id.Equals(itemId))
             {
                 return item;
             }
@@ -587,7 +593,7 @@ public async Task OnPlaybackStart(PlaybackStartInfo info)
 
             var session = GetSession(info.SessionId);
 
-            var libraryItem = string.IsNullOrEmpty(info.ItemId)
+            var libraryItem = info.ItemId.Equals(Guid.Empty)
                 ? null
                 : GetNowPlayingItem(session, info.ItemId);
 
@@ -619,7 +625,7 @@ public async Task OnPlaybackStart(PlaybackStartInfo info)
                 MediaSourceId = info.MediaSourceId,
                 MediaInfo = info.Item,
                 DeviceName = session.DeviceName,
-                ClientName = session.AppName,
+                ClientName = session.Client,
                 DeviceId = session.DeviceId,
                 Session = session
 
@@ -674,7 +680,7 @@ public async Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated
 
             var session = GetSession(info.SessionId);
 
-            var libraryItem = string.IsNullOrEmpty(info.ItemId)
+            var libraryItem = info.ItemId.Equals(Guid.Empty)
                 ? null
                 : GetNowPlayingItem(session, info.ItemId);
 
@@ -699,7 +705,7 @@ public async Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated
                 MediaSourceId = session.PlayState.MediaSourceId,
                 MediaInfo = info.Item,
                 DeviceName = session.DeviceName,
-                ClientName = session.AppName,
+                ClientName = session.Client,
                 DeviceId = session.DeviceId,
                 IsPaused = info.IsPaused,
                 PlaySessionId = info.PlaySessionId,
@@ -778,21 +784,21 @@ public async Task OnPlaybackStopped(PlaybackStopInfo info)
 
             session.StopAutomaticProgress();
 
-            var libraryItem = string.IsNullOrEmpty(info.ItemId)
+            var libraryItem = info.ItemId.Equals(Guid.Empty)
                 ? null
                 : GetNowPlayingItem(session, info.ItemId);
 
             // Normalize
             if (string.IsNullOrEmpty(info.MediaSourceId))
             {
-                info.MediaSourceId = info.ItemId;
+                info.MediaSourceId = info.ItemId.ToString("N");
             }
 
-            if (!string.IsNullOrEmpty(info.ItemId) && info.Item == null && libraryItem != null)
+            if (!info.ItemId.Equals(Guid.Empty) && info.Item == null && libraryItem != null)
             {
                 var current = session.NowPlayingItem;
 
-                if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase))
+                if (current == null || !info.ItemId.Equals(current.Id))
                 {
                     MediaSourceInfo mediaSource = null;
 
@@ -815,12 +821,19 @@ public async Task OnPlaybackStopped(PlaybackStopInfo info)
                 var msString = info.PositionTicks.HasValue ? (info.PositionTicks.Value / 10000).ToString(CultureInfo.InvariantCulture) : "unknown";
 
                 _logger.Info("Playback stopped reported by app {0} {1} playing {2}. Stopped at {3} ms",
-                    session.AppName,
+                    session.Client,
                     session.ApplicationVersion,
                     info.Item.Name,
                     msString);
             }
 
+            if (info.NowPlayingQueue != null)
+            {
+                session.NowPlayingQueue = info.NowPlayingQueue;
+            }
+
+            session.PlaylistItemId = info.PlaylistItemId;
+
             RemoveNowPlayingItem(session);
 
             var users = GetUsers(session);
@@ -855,7 +868,7 @@ public async Task OnPlaybackStopped(PlaybackStopInfo info)
                 MediaSourceId = info.MediaSourceId,
                 MediaInfo = info.Item,
                 DeviceName = session.DeviceName,
-                ClientName = session.AppName,
+                ClientName = session.Client,
                 DeviceId = session.DeviceId,
                 Session = session
 
@@ -973,7 +986,7 @@ public async Task SendPlayCommand(string controllingSessionId, string sessionId,
 
             var session = GetSessionToRemoteControl(sessionId);
 
-            var user = session.UserId.HasValue ? _userManager.GetUserById(session.UserId.Value) : null;
+            var user = !session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(session.UserId) : null;
 
             List<BaseItem> items;
 
@@ -1002,7 +1015,7 @@ public async Task SendPlayCommand(string controllingSessionId, string sessionId,
                 command.PlayCommand = PlayCommand.PlayNow;
             }
 
-            command.ItemIds = items.Select(i => i.Id.ToString("N")).ToArray(items.Count);
+            command.ItemIds = items.Select(i => i.Id).ToArray(items.Count);
 
             if (user != null)
             {
@@ -1030,7 +1043,7 @@ public async Task SendPlayCommand(string controllingSessionId, string sessionId,
 
                         if (episodes.Count > 0)
                         {
-                            command.ItemIds = episodes.Select(i => i.Id.ToString("N")).ToArray(episodes.Count);
+                            command.ItemIds = episodes.Select(i => i.Id).ToArray(episodes.Count);
                         }
                     }
                 }
@@ -1040,16 +1053,16 @@ public async Task SendPlayCommand(string controllingSessionId, string sessionId,
             {
                 var controllingSession = GetSession(controllingSessionId);
                 AssertCanControl(session, controllingSession);
-                if (controllingSession.UserId.HasValue)
+                if (!controllingSession.UserId.Equals(Guid.Empty))
                 {
-                    command.ControllingUserId = controllingSession.UserId.Value.ToString("N");
+                    command.ControllingUserId = controllingSession.UserId;
                 }
             }
 
             await SendMessageToSession(session, "Play", command, cancellationToken).ConfigureAwait(false);
         }
 
-        private IList<BaseItem> TranslateItemForPlayback(string id, User user)
+        private IList<BaseItem> TranslateItemForPlayback(Guid id, User user)
         {
             var item = _libraryManager.GetItemById(id);
 
@@ -1105,7 +1118,7 @@ private IList<BaseItem> TranslateItemForPlayback(string id, User user)
             return new List<BaseItem> { item };
         }
 
-        private IEnumerable<BaseItem> TranslateItemForInstantMix(string id, User user)
+        private IEnumerable<BaseItem> TranslateItemForInstantMix(Guid id, User user)
         {
             var item = _libraryManager.GetItemById(id);
 
@@ -1142,9 +1155,9 @@ public Task SendPlaystateCommand(string controllingSessionId, string sessionId,
             {
                 var controllingSession = GetSession(controllingSessionId);
                 AssertCanControl(session, controllingSession);
-                if (controllingSession.UserId.HasValue)
+                if (!controllingSession.UserId.Equals(Guid.Empty))
                 {
-                    command.ControllingUserId = controllingSession.UserId.Value.ToString("N");
+                    command.ControllingUserId = controllingSession.UserId.ToString("N");
                 }
             }
 
@@ -1253,18 +1266,18 @@ public Task SendServerRestartNotification(CancellationToken cancellationToken)
         /// <param name="userId">The user identifier.</param>
         /// <exception cref="System.UnauthorizedAccessException">Cannot modify additional users without authenticating first.</exception>
         /// <exception cref="System.ArgumentException">The requested user is already the primary user of the session.</exception>
-        public void AddAdditionalUser(string sessionId, string userId)
+        public void AddAdditionalUser(string sessionId, Guid userId)
         {
             CheckDisposed();
 
             var session = GetSession(sessionId);
 
-            if (session.UserId.HasValue && session.UserId.Value == new Guid(userId))
+            if (session.UserId.Equals(userId))
             {
                 throw new ArgumentException("The requested user is already the primary user of the session.");
             }
 
-            if (session.AdditionalUsers.All(i => new Guid(i.UserId) != new Guid(userId)))
+            if (session.AdditionalUsers.All(i => !i.UserId.Equals(userId)))
             {
                 var user = _userManager.GetUserById(userId);
 
@@ -1287,18 +1300,18 @@ public void AddAdditionalUser(string sessionId, string userId)
         /// <param name="userId">The user identifier.</param>
         /// <exception cref="System.UnauthorizedAccessException">Cannot modify additional users without authenticating first.</exception>
         /// <exception cref="System.ArgumentException">The requested user is already the primary user of the session.</exception>
-        public void RemoveAdditionalUser(string sessionId, string userId)
+        public void RemoveAdditionalUser(string sessionId, Guid userId)
         {
             CheckDisposed();
 
             var session = GetSession(sessionId);
 
-            if (session.UserId.HasValue && session.UserId.Value == new Guid(userId))
+            if (session.UserId.Equals(userId))
             {
                 throw new ArgumentException("The requested user is already the primary user of the session.");
             }
 
-            var user = session.AdditionalUsers.FirstOrDefault(i => new Guid(i.UserId) == new Guid(userId));
+            var user = session.AdditionalUsers.FirstOrDefault(i => i.UserId.Equals(userId));
 
             if (user != null)
             {
@@ -1329,11 +1342,10 @@ private async Task<AuthenticationResult> AuthenticateNewSessionInternal(Authenti
             CheckDisposed();
 
             User user = null;
-            if (!string.IsNullOrEmpty(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
-                var idGuid = new Guid(request.UserId);
                 user = _userManager.Users
-                    .FirstOrDefault(i => i.Id == idGuid);
+                    .FirstOrDefault(i => i.Id == request.UserId);
             }
 
             if (user == null)
@@ -1368,7 +1380,7 @@ private async Task<AuthenticationResult> AuthenticateNewSessionInternal(Authenti
                 user = result;
             }
 
-            var token = GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.AppVersion, request.DeviceName);
+            var token = GetAuthorizationToken(user.Id, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
 
             EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
 
@@ -1382,13 +1394,13 @@ private async Task<AuthenticationResult> AuthenticateNewSessionInternal(Authenti
             return new AuthenticationResult
             {
                 User = _userManager.GetUserDto(user, request.RemoteEndPoint),
-                SessionInfo = GetSessionInfoDto(session),
+                SessionInfo = session,
                 AccessToken = token,
                 ServerId = _appHost.SystemId
             };
         }
 
-        private string GetAuthorizationToken(string userId, string deviceId, string app, string appVersion, string deviceName)
+        private string GetAuthorizationToken(Guid userId, string deviceId, string app, string appVersion, string deviceName)
         {
             var existing = _authRepo.Get(new AuthenticationInfoQuery
             {
@@ -1465,7 +1477,7 @@ public void Logout(string accessToken)
             }
         }
 
-        public void RevokeUserTokens(string userId, string currentAccessToken)
+        public void RevokeUserTokens(Guid userId, string currentAccessToken)
         {
             CheckDisposed();
 
@@ -1509,7 +1521,11 @@ private void ReportCapabilities(SessionInfo session,
         {
             session.Capabilities = capabilities;
 
-            if (!string.IsNullOrEmpty(capabilities.MessageCallbackUrl))
+            if ((session.Client ?? string.Empty).IndexOf("Roku", StringComparison.OrdinalIgnoreCase) != -1)
+            {
+                EnsureRokuController(session);
+            }
+            else if (!string.IsNullOrEmpty(capabilities.MessageCallbackUrl))
             {
                 EnsureHttpController(session, capabilities.MessageCallbackUrl);
             }
@@ -1550,6 +1566,10 @@ private void EnsureHttpController(SessionInfo session, string messageCallbackUrl
             session.EnsureController<HttpSessionController>(s => new HttpSessionController(_httpClient, _jsonSerializer, s, messageCallbackUrl, this));
         }
 
+        private void EnsureRokuController(SessionInfo session)
+        {
+        }
+
         private ClientCapabilities GetSavedCapabilities(string deviceId)
         {
             return _deviceManager.GetCapabilities(deviceId);
@@ -1560,45 +1580,6 @@ private void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
             _deviceManager.SaveCapabilities(deviceId, capabilities);
         }
 
-        public SessionInfoDto GetSessionInfoDto(SessionInfo session)
-        {
-            var dto = new SessionInfoDto
-            {
-                Client = session.AppName,
-                DeviceId = session.DeviceId,
-                DeviceType = session.DeviceType,
-                DeviceName = session.DeviceName,
-                Id = session.Id,
-                LastActivityDate = session.LastActivityDate,
-                ApplicationVersion = session.ApplicationVersion,
-                PlayableMediaTypes = session.PlayableMediaTypes,
-                AdditionalUsers = session.AdditionalUsers,
-                SupportedCommands = session.SupportedCommands,
-                UserName = session.UserName,
-                NowPlayingItem = session.NowPlayingItem,
-                SupportsRemoteControl = session.SupportsMediaControl,
-                PlayState = session.PlayState,
-                AppIconUrl = session.AppIconUrl,
-                TranscodingInfo = session.NowPlayingItem == null ? null : session.TranscodingInfo,
-                RemoteEndPoint = session.RemoteEndPoint,
-                ServerId = _appHost.SystemId
-            };
-
-            if (session.UserId.HasValue)
-            {
-                dto.UserId = session.UserId.Value.ToString("N");
-
-                var user = _userManager.GetUserById(session.UserId.Value);
-
-                if (user != null)
-                {
-                    dto.UserPrimaryImageTag = GetImageCacheTag(user, ImageType.Primary);
-                }
-            }
-
-            return dto;
-        }
-
         private DtoOptions _itemInfoDtoOptions;
 
         /// <summary>
@@ -1680,11 +1661,6 @@ private string GetImageCacheTag(BaseItem item, ImageType type)
             }
         }
 
-        private string GetDtoId(BaseItem item)
-        {
-            return _dtoService.GetDtoId(item);
-        }
-
         public void ReportNowViewingItem(string sessionId, string itemId)
         {
             if (string.IsNullOrEmpty(itemId))
@@ -1724,7 +1700,7 @@ public void ClearTranscodingInfo(string deviceId)
         public SessionInfo GetSession(string deviceId, string client, string version)
         {
             return Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
-                string.Equals(i.AppName, client));
+                string.Equals(i.Client, client));
         }
 
         public SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion)
@@ -1734,7 +1710,7 @@ public SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, stri
                 throw new ArgumentNullException("info");
             }
 
-            var user = string.IsNullOrEmpty(info.UserId)
+            var user = info.UserId.Equals(Guid.Empty)
                 ? null
                 : _userManager.GetUserById(info.UserId);
 
@@ -1795,12 +1771,12 @@ public Task SendMessageToAdminSessions<T>(string name, T data, CancellationToken
         {
             CheckDisposed();
 
-            var adminUserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id.ToString("N")).ToList();
+            var adminUserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToList();
 
             return SendMessageToUserSessions(adminUserIds, name, data, cancellationToken);
         }
 
-        public Task SendMessageToUserSessions<T>(List<string> userIds, string name, Func<T> dataFn, CancellationToken cancellationToken)
+        public Task SendMessageToUserSessions<T>(List<Guid> userIds, string name, Func<T> dataFn, CancellationToken cancellationToken)
         {
             CheckDisposed();
 
@@ -1829,7 +1805,7 @@ public Task SendMessageToUserSessions<T>(List<string> userIds, string name, Func
             return Task.WhenAll(tasks);
         }
 
-        public Task SendMessageToUserSessions<T>(List<string> userIds, string name, T data, CancellationToken cancellationToken)
+        public Task SendMessageToUserSessions<T>(List<Guid> userIds, string name, T data, CancellationToken cancellationToken)
         {
             CheckDisposed();
 
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 2a06a8611c..435bcfd043 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -434,7 +434,7 @@ public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IPro
 
             var installationInfo = new InstallationInfo
             {
-                Id = Guid.NewGuid().ToString("N"),
+                Id = Guid.NewGuid(),
                 Name = package.name,
                 AssemblyGuid = package.guid,
                 UpdateClass = package.classification,
diff --git a/Emby.Server.Implementations/packages.config b/Emby.Server.Implementations/packages.config
index 311ce4c313..5ff60e31de 100644
--- a/Emby.Server.Implementations/packages.config
+++ b/Emby.Server.Implementations/packages.config
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Emby.XmlTv" version="1.0.14" targetFramework="net46" />
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
   <package id="MediaBrowser.Naming" version="1.1.5-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
   <package id="Microsoft.NETCore.Platforms" version="2.1.0" targetFramework="net47" />
   <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net47" />
   <package id="NETStandard.Library" version="2.0.3" targetFramework="net47" />
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 61f60769d1..e98915e908 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -84,14 +84,14 @@ protected object ToOptimizedResult<T>(T result)
             return ResultFactory.GetResult(Request, result);
         }
 
-        protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId, bool restrictUserPreferences)
+        protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, Guid userId, bool restrictUserPreferences)
         {
             var auth = authContext.GetAuthorizationInfo(Request);
 
             var authenticatedUser = userManager.GetUserById(auth.UserId);
 
             // If they're going to update the record of another user, they must be an administrator
-            if (!string.Equals(userId, auth.UserId, StringComparison.OrdinalIgnoreCase))
+            if (!userId.Equals(auth.UserId))
             {
                 if (!authenticatedUser.Policy.IsAdministrator)
                 {
diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs
index b683ed6a3c..94c1acaa28 100644
--- a/MediaBrowser.Api/ChannelService.cs
+++ b/MediaBrowser.Api/ChannelService.cs
@@ -24,7 +24,7 @@ public class GetChannels : IReturn<QueryResult<BaseItemDto>>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -78,7 +78,7 @@ public class GetChannelItems : IReturn<QueryResult<BaseItemDto>>, IHasItemFields
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -140,7 +140,7 @@ public class GetLatestChannelItems : IReturn<QueryResult<BaseItemDto>>, IHasItem
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -225,7 +225,7 @@ public object Get(GetChannels request)
 
         public async Task<object> Get(GetChannelItems request)
         {
-            var user = string.IsNullOrEmpty(request.UserId)
+            var user = request.UserId.Equals(Guid.Empty)
                 ? null
                 : _userManager.GetUserById(request.UserId);
 
@@ -234,7 +234,7 @@ public async Task<object> Get(GetChannelItems request)
                 Limit = request.Limit,
                 StartIndex = request.StartIndex,
                 ChannelIds = new Guid[] { new Guid(request.Id) },
-                ParentId = string.IsNullOrWhiteSpace(request.FolderId) ? (Guid?)null : new Guid(request.FolderId),
+                ParentId = string.IsNullOrWhiteSpace(request.FolderId) ? Guid.Empty : new Guid(request.FolderId),
                 OrderBy = request.GetOrderBy(),
                 DtoOptions = new Controller.Dto.DtoOptions
                 {
@@ -284,7 +284,7 @@ public async Task<object> Get(GetChannelItems request)
 
         public async Task<object> Get(GetLatestChannelItems request)
         {
-            var user = string.IsNullOrEmpty(request.UserId)
+            var user = request.UserId.Equals(Guid.Empty)
                 ? null
                 : _userManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs
index 037fbeee2f..59e203b7f7 100644
--- a/MediaBrowser.Api/FilterService.cs
+++ b/MediaBrowser.Api/FilterService.cs
@@ -19,7 +19,7 @@ public class GetQueryFiltersLegacy : IReturn<QueryFiltersLegacy>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string ParentId { get; set; }
@@ -49,7 +49,7 @@ public class GetQueryFilters : IReturn<QueryFilters>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string ParentId { get; set; }
@@ -94,7 +94,7 @@ public FilterService(ILibraryManager libraryManager, IUserManager userManager)
         public object Get(GetQueryFilters request)
         {
             var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
                 string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
@@ -138,29 +138,29 @@ public object Get(GetQueryFilters request)
                 string.Equals(request.IncludeItemTypes, "MusicArtist", StringComparison.OrdinalIgnoreCase) ||
                 string.Equals(request.IncludeItemTypes, "Audio", StringComparison.OrdinalIgnoreCase))
             {
-                filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameIdPair
+                filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
                 {
                     Name = i.Item1.Name,
-                    Id = i.Item1.Id.ToString("N")
+                    Id = i.Item1.Id
 
                 }).ToArray();
             }
             else if (string.Equals(request.IncludeItemTypes, "Game", StringComparison.OrdinalIgnoreCase) ||
                 string.Equals(request.IncludeItemTypes, "GameSystem", StringComparison.OrdinalIgnoreCase))
             {
-                filters.Genres = _libraryManager.GetGameGenres(genreQuery).Items.Select(i => new NameIdPair
+                filters.Genres = _libraryManager.GetGameGenres(genreQuery).Items.Select(i => new NameGuidPair
                 {
                     Name = i.Item1.Name,
-                    Id = i.Item1.Id.ToString("N")
+                    Id = i.Item1.Id
 
                 }).ToArray();
             }
             else
             {
-                filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameIdPair
+                filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair
                 {
                     Name = i.Item1.Name,
-                    Id = i.Item1.Id.ToString("N")
+                    Id = i.Item1.Id
 
                 }).ToArray();
             }
@@ -171,7 +171,7 @@ public object Get(GetQueryFilters request)
         public object Get(GetQueryFiltersLegacy request)
         {
             var parentItem = string.IsNullOrEmpty(request.ParentId) ? null : _libraryManager.GetItemById(request.ParentId);
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase) ||
                 string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) ||
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs
index 8e597b471b..e5247d957a 100644
--- a/MediaBrowser.Api/GamesService.cs
+++ b/MediaBrowser.Api/GamesService.cs
@@ -35,7 +35,7 @@ public class GetGameSystemSummaries : IReturn<GameSystemSummary[]>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -164,10 +164,10 @@ public object Get(GetSimilarGames request)
 
         private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id) ?
-                (!string.IsNullOrWhiteSpace(request.UserId) ? _libraryManager.GetUserRootFolder() :
+                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
                 _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
 
             var dtoOptions = GetDtoOptions(_authContext, request);
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 2d24fb0bbc..276781d34c 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -51,7 +51,7 @@ public class GetItemImage : ImageRequest
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -145,7 +145,7 @@ public class GetUserImage : ImageRequest
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -177,7 +177,7 @@ public class DeleteUserImage : DeleteImageRequest, IReturnVoid
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -395,14 +395,14 @@ public object Get(GetUserImage request)
         {
             var item = _userManager.GetUserById(request.Id);
 
-            return GetImage(request, null, item, false);
+            return GetImage(request, Guid.Empty, item, false);
         }
 
         public object Head(GetUserImage request)
         {
             var item = _userManager.GetUserById(request.Id);
 
-            return GetImage(request, null, item, true);
+            return GetImage(request, Guid.Empty, item, true);
         }
 
         public object Get(GetItemByNameImage request)
@@ -411,7 +411,7 @@ public object Get(GetItemByNameImage request)
 
             var item = GetItemByName(request.Name, type, _libraryManager, new DtoOptions(false));
 
-            return GetImage(request, item.Id.ToString("N"), item, false);
+            return GetImage(request, item.Id, item, false);
         }
 
         public object Head(GetItemByNameImage request)
@@ -420,7 +420,7 @@ public object Head(GetItemByNameImage request)
 
             var item = GetItemByName(request.Name, type, _libraryManager, new DtoOptions(false));
 
-            return GetImage(request, item.Id.ToString("N"), item, true);
+            return GetImage(request, item.Id, item, true);
         }
 
         /// <summary>
@@ -430,7 +430,7 @@ public object Head(GetItemByNameImage request)
         public Task Post(PostUserImage request)
         {
             var userId = GetPathValue(1);
-            AssertCanUpdateUser(_authContext, _userManager, userId, true);
+            AssertCanUpdateUser(_authContext, _userManager, new Guid(userId), true);
 
             request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
 
@@ -511,7 +511,7 @@ private void UpdateItemIndex(BaseItem item, ImageType type, int currentIndex, in
         /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
         /// <returns>System.Object.</returns>
         /// <exception cref="ResourceNotFoundException"></exception>
-        public Task<object> GetImage(ImageRequest request, string itemId, BaseItem item, bool isHeadRequest)
+        public Task<object> GetImage(ImageRequest request, Guid itemId, BaseItem item, bool isHeadRequest)
         {
             if (request.PercentPlayed.HasValue)
             {
@@ -546,7 +546,7 @@ public Task<object> GetImage(ImageRequest request, string itemId, BaseItem item,
 
             if (imageInfo == null)
             {
-                var displayText = item == null ? itemId : item.Name;
+                var displayText = item == null ? itemId.ToString() : item.Name;
                 throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", displayText, request.Type));
             }
 
@@ -602,7 +602,7 @@ public Task<object> GetImage(ImageRequest request, string itemId, BaseItem item,
         }
 
         private async Task<object> GetImageResult(BaseItem item,
-            string itemId,
+            Guid itemId,
             ImageRequest request,
             ItemImageInfo image,
             bool cropwhitespace,
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index 6329d85af0..39a7904866 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -29,7 +29,7 @@ public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     [Route("/Items/RemoteSearch/Movie", "POST")]
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 929303bc7a..295fdb6965 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -37,7 +37,7 @@ public class GetMetadataEditorInfo : IReturn<MetadataEditorInfo>
     public class UpdateItemContentType : IReturnVoid
     {
         [ApiMember(Name = "ItemId", Description = "The id of the item", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string ItemId { get; set; }
+        public Guid ItemId { get; set; }
 
         [ApiMember(Name = "ContentType", Description = "The content type of the item", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
         public string ContentType { get; set; }
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 92b9abdad4..a083566f7b 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -88,7 +88,7 @@ public class GetThemeSongs : IReturn<ThemeMediaResult>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -113,7 +113,7 @@ public class GetThemeVideos : IReturn<ThemeMediaResult>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -138,7 +138,7 @@ public class GetThemeMedia : IReturn<AllThemeMediaResult>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -178,7 +178,7 @@ public class DeleteItems : IReturnVoid
     public class GetItemCounts : IReturn<ItemCounts>
     {
         [ApiMember(Name = "UserId", Description = "Optional. Get counts from a specific user's library.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "IsFavorite", Description = "Optional. Get counts of favorite items", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         public bool? IsFavorite { get; set; }
@@ -193,7 +193,7 @@ public class GetAncestors : IReturn<BaseItemDto[]>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -624,10 +624,10 @@ public object Get(GetLibraryOptionsInfo request)
 
         public object Get(GetSimilarItems request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id) ?
-                (!string.IsNullOrWhiteSpace(request.UserId) ? _libraryManager.GetUserRootFolder() :
+                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
                 _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
 
             if (item is Game)
@@ -851,7 +851,7 @@ private void LogDownload(BaseItem item, User user, AuthorizationInfo auth)
                     Name = string.Format(_localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Name, item.Name),
                     Type = "UserDownloadingContent",
                     ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device),
-                    UserId = auth.UserId
+                    UserId = auth.UserId.ToString("N")
 
                 });
             }
@@ -914,7 +914,7 @@ public List<BaseItemDto> GetAncestors(GetAncestors request)
 
             var baseItemDtos = new List<BaseItemDto>();
 
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
@@ -962,7 +962,7 @@ public object Get(GetCriticReviews request)
         /// <returns>System.Object.</returns>
         public object Get(GetItemCounts request)
         {
-            var user = string.IsNullOrWhiteSpace(request.UserId) ? null : _userManager.GetUserById(request.UserId);
+            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
 
             var counts = new ItemCounts
             {
@@ -1105,10 +1105,10 @@ public object Get(GetThemeSongs request)
 
         private ThemeMediaResult GetThemeSongs(GetThemeSongs request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id)
-                           ? (!string.IsNullOrWhiteSpace(request.UserId)
+                           ? (!request.UserId.Equals(Guid.Empty)
                                   ? _libraryManager.GetUserRootFolder()
                                   : (Folder)_libraryManager.RootFolder)
                            : _libraryManager.GetItemById(request.Id);
@@ -1144,7 +1144,7 @@ private ThemeMediaResult GetThemeSongs(GetThemeSongs request)
             {
                 Items = items,
                 TotalRecordCount = items.Length,
-                OwnerId = _dtoService.GetDtoId(item)
+                OwnerId = item.Id
             };
         }
 
@@ -1162,10 +1162,10 @@ public object Get(GetThemeVideos request)
 
         public ThemeMediaResult GetThemeVideos(GetThemeVideos request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id)
-                           ? (!string.IsNullOrWhiteSpace(request.UserId)
+                           ? (!request.UserId.Equals(Guid.Empty)
                                   ? _libraryManager.GetUserRootFolder()
                                   : (Folder)_libraryManager.RootFolder)
                            : _libraryManager.GetItemById(request.Id);
@@ -1201,7 +1201,7 @@ public ThemeMediaResult GetThemeVideos(GetThemeVideos request)
             {
                 Items = items,
                 TotalRecordCount = items.Length,
-                OwnerId = _dtoService.GetDtoId(item)
+                OwnerId = item.Id
             };
         }
     }
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 8edaafc005..d10b9205e9 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -45,7 +45,7 @@ public class GetChannels : IReturn<QueryResult<ChannelInfoDto>>, IHasDtoOptions
         public ChannelType? Type { get; set; }
 
         [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -148,7 +148,7 @@ public class GetChannel : IReturn<ChannelInfoDto>
         public string Id { get; set; }
 
         [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Route("/LiveTv/Recordings", "GET", Summary = "Gets live tv recordings")]
@@ -159,7 +159,7 @@ public class GetRecordings : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
         public string ChannelId { get; set; }
 
         [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
         public int? StartIndex { get; set; }
@@ -278,7 +278,7 @@ public class GetRecordingGroups : IReturn<QueryResult<BaseItemDto>>
     public class GetRecordingFolders : IReturn<BaseItemDto[]>
     {
         [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Route("/LiveTv/Recordings/{Id}", "GET", Summary = "Gets a live tv recording")]
@@ -289,7 +289,7 @@ public class GetRecording : IReturn<BaseItemDto>
         public string Id { get; set; }
 
         [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Route("/LiveTv/Tuners/{Id}/Reset", "POST", Summary = "Resets a tv tuner")]
@@ -339,7 +339,7 @@ public class GetPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
         public string ChannelIds { get; set; }
 
         [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "MinStartDate", Description = "Optional. The minimum premiere date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
         public string MinStartDate { get; set; }
@@ -404,7 +404,7 @@ public class GetPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
         public bool? EnableUserData { get; set; }
 
         public string SeriesTimerId { get; set; }
-        public string LibrarySeriesId { get; set; }
+        public Guid LibrarySeriesId { get; set; }
 
         /// <summary>
         /// Fields to return within the items, in addition to basic information
@@ -431,7 +431,7 @@ public GetRecommendedPrograms()
         }
 
         [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
         public int? Limit { get; set; }
@@ -488,7 +488,7 @@ public class GetProgram : IReturn<BaseItemDto>
         public string Id { get; set; }
 
         [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
 
@@ -497,7 +497,7 @@ public class GetProgram : IReturn<BaseItemDto>
     public class DeleteRecording : IReturnVoid
     {
         [ApiMember(Name = "Id", Description = "Recording Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     [Route("/LiveTv/Timers/{Id}", "DELETE", Summary = "Cancels a live tv timer")]
@@ -578,7 +578,7 @@ public class GetGuideInfo : IReturn<GuideInfo>
     public class GetLiveTvFolder : IReturn<BaseItemDto>
     {
         [ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Route("/LiveTv/TunerHosts", "POST", Summary = "Adds a tuner host")]
@@ -735,7 +735,7 @@ public object Get(GetTunerHostTypes request)
 
         public object Get(GetRecordingFolders request)
         {
-            var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
+            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
             var folders = _liveTvManager.GetRecordingFolders(user);
 
             var returnArray = _dtoService.GetBaseItemDtos(folders.ToArray(), new DtoOptions(), user);
@@ -955,7 +955,7 @@ public object Get(GetChannels request)
 
             }, options, CancellationToken.None);
 
-            var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
+            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
 
             RemoveFields(options);
 
@@ -1043,7 +1043,7 @@ public async Task<object> Get(GetPrograms request)
             query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
             query.GenreIds = GetGuids(request.GenreIds);
 
-            if (!string.IsNullOrWhiteSpace(request.LibrarySeriesId))
+            if (!request.LibrarySeriesId.Equals(Guid.Empty))
             {
                 query.IsSeries = true;
 
@@ -1230,7 +1230,7 @@ public async Task<object> Get(GetDefaultTimer request)
 
         public async Task<object> Get(GetProgram request)
         {
-            var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
+            var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
 
             var result = await _liveTvManager.GetProgram(request.Id, CancellationToken.None, user).ConfigureAwait(false);
 
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 5ac75805b9..77768cc8e5 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -105,13 +105,13 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs
index 62e0a90e87..47bac4f2f3 100644
--- a/MediaBrowser.Api/Movies/CollectionService.cs
+++ b/MediaBrowser.Api/Movies/CollectionService.cs
@@ -69,7 +69,7 @@ public object Post(CreateCollection request)
                 Name = request.Name,
                 ParentId = parentId,
                 ItemIdList = SplitValue(request.Ids, ','),
-                UserIds = new string[] { userId }
+                UserIds = new [] { userId }
 
             });
 
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index 6911d0984a..088ef68f6f 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -49,7 +49,7 @@ public class GetMovieRecommendations : IReturn<RecommendationDto[]>, IHasDtoOpti
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Specify this to localize the search to a specific item or folder. Omit to use the root.
@@ -140,10 +140,10 @@ public object Get(GetMovieRecommendations request)
 
         private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id) ?
-                (!string.IsNullOrWhiteSpace(request.UserId) ? _libraryManager.GetUserRootFolder() :
+                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
                 _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
 
             var itemTypes = new List<string> { typeof(Movie).Name };
@@ -182,7 +182,7 @@ private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, st
         {
             var categories = new List<RecommendationDto>();
 
-            var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? (Guid?)null : new Guid(parentId);
+            var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? Guid.Empty : new Guid(parentId);
 
             var query = new InternalItemsQuery(user)
             {
@@ -316,7 +316,7 @@ private IEnumerable<RecommendationDto> GetWithDirector(User user, IEnumerable<st
                     yield return new RecommendationDto
                     {
                         BaselineItemName = name,
-                        CategoryId = name.GetMD5().ToString("N"),
+                        CategoryId = name.GetMD5(),
                         RecommendationType = type,
                         Items = returnItems
                     };
@@ -356,7 +356,7 @@ private IEnumerable<RecommendationDto> GetWithActor(User user, IEnumerable<strin
                     yield return new RecommendationDto
                     {
                         BaselineItemName = name,
-                        CategoryId = name.GetMD5().ToString("N"),
+                        CategoryId = name.GetMD5(),
                         RecommendationType = type,
                         Items = returnItems
                     };
@@ -393,7 +393,7 @@ private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> ba
                     yield return new RecommendationDto
                     {
                         BaselineItemName = item.Name,
-                        CategoryId = item.Id.ToString("N"),
+                        CategoryId = item.Id,
                         RecommendationType = type,
                         Items = returnItems
                     };
diff --git a/MediaBrowser.Api/NotificationsService.cs b/MediaBrowser.Api/NotificationsService.cs
index c5065d3655..1124f3539c 100644
--- a/MediaBrowser.Api/NotificationsService.cs
+++ b/MediaBrowser.Api/NotificationsService.cs
@@ -127,7 +127,7 @@ private Task AddNotification(AddAdminNotification request)
                 Level = request.Level,
                 Name = request.Name,
                 Url = request.Url,
-                UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id.ToString("N")).ToList()
+                UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id).ToArray()
             };
 
             return _notificationManager.SendNotification(notification, CancellationToken.None);
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index c29dc68dff..44d7ca62d5 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -244,7 +244,7 @@ await _installationManager.GetLatestCompatibleVersion(request.Name, request.Asse
         /// <param name="request">The request.</param>
         public void Delete(CancelPackageInstallation request)
         {
-            var info = _installationManager.CurrentInstallations.FirstOrDefault(i => string.Equals(i.Item1.Id, request.Id));
+            var info = _installationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id.Equals(request.Id));
 
             if (info != null)
             {
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
index 289e915b00..27bd81a890 100644
--- a/MediaBrowser.Api/PlaylistService.cs
+++ b/MediaBrowser.Api/PlaylistService.cs
@@ -9,6 +9,7 @@
 using System.Threading.Tasks;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Extensions;
+using System;
 
 namespace MediaBrowser.Api
 {
@@ -22,7 +23,7 @@ public class CreatePlaylist : IReturn<PlaylistCreationResult>
         public string Ids { get; set; }
 
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "MediaType", Description = "The playlist media type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string MediaType { get; set; }
@@ -42,7 +43,7 @@ public class AddToPlaylist : IReturnVoid
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Route("/Playlists/{Id}/Items/{ItemId}/Move/{NewIndex}", "POST", Summary = "Moves a playlist item")]
@@ -76,14 +77,14 @@ public class RemoveFromPlaylist : IReturnVoid
     public class GetPlaylistItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
     {
         [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         /// <summary>
         /// Gets or sets the user id.
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -147,7 +148,7 @@ public async Task<object> Post(CreatePlaylist request)
             var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
             {
                 Name = request.Name,
-                ItemIdList = SplitValue(request.Ids, ','),
+                ItemIdList = GetGuids(request.Ids),
                 UserId = request.UserId,
                 MediaType = request.MediaType
 
@@ -158,7 +159,7 @@ public async Task<object> Post(CreatePlaylist request)
 
         public void Post(AddToPlaylist request)
         {
-            _playlistManager.AddToPlaylist(request.Id, request.Ids.Split(','), request.UserId);
+            _playlistManager.AddToPlaylist(request.Id, GetGuids(request.Ids), request.UserId);
         }
 
         public void Delete(RemoveFromPlaylist request)
@@ -169,7 +170,7 @@ public void Delete(RemoveFromPlaylist request)
         public object Get(GetPlaylistItems request)
         {
             var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var items = playlist.GetManageableItems().ToArray();
 
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index c4a32d70ce..0473dd9245 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -11,6 +11,7 @@
 using System.Threading.Tasks;
 using MediaBrowser.Controller.LiveTv;
 using MediaBrowser.Model.Services;
+using System;
 
 namespace MediaBrowser.Api
 {
@@ -39,7 +40,7 @@ public class GetSearchHints : IReturn<SearchHintResult>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Supply a user id to search within a user's library or omit to search all.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Search characters used to find items
@@ -194,7 +195,7 @@ private SearchHint GetSearchHintResult(SearchHintInfo hintInfo)
                 Name = item.Name,
                 IndexNumber = item.IndexNumber,
                 ParentIndexNumber = item.ParentIndexNumber,
-                Id = _dtoService.GetDtoId(item),
+                Id = item.Id,
                 Type = item.GetClientTypeName(),
                 MediaType = item.MediaType,
                 MatchedTerm = hintInfo.MatchedTerm,
@@ -264,7 +265,7 @@ private SearchHint GetSearchHintResult(SearchHintInfo hintInfo)
                 if (album != null)
                 {
                     result.Album = album.Name;
-                    result.AlbumId = album.Id.ToString("N");
+                    result.AlbumId = album.Id;
                 }
                 else
                 {
@@ -272,7 +273,7 @@ private SearchHint GetSearchHintResult(SearchHintInfo hintInfo)
                 }
             }
 
-            if (!string.IsNullOrWhiteSpace(item.ChannelId))
+            if (!item.ChannelId.Equals(Guid.Empty))
             {
                 var channel = _libraryManager.GetItemById(item.ChannelId);
                 result.ChannelName = channel == null ? null : channel.Name;
diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
index 355699c718..ca2c381cf6 100644
--- a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
@@ -14,7 +14,7 @@ namespace MediaBrowser.Api.Session
     /// <summary>
     /// Class SessionInfoWebSocketListener
     /// </summary>
-    class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, WebSocketListenerState>
+    class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfo>, WebSocketListenerState>
     {
         /// <summary>
         /// Gets the name.
@@ -87,9 +87,9 @@ void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
         /// </summary>
         /// <param name="state">The state.</param>
         /// <returns>Task{SystemInfo}.</returns>
-        protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
+        protected override Task<IEnumerable<SessionInfo>> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
         {
-            return Task.FromResult(_sessionManager.Sessions.Select(_sessionManager.GetSessionInfoDto));
+            return Task.FromResult(_sessionManager.Sessions);
         }
 
         protected override void Dispose(bool dispose)
diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index ddffb84b43..4150a42f21 100644
--- a/MediaBrowser.Api/Session/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -20,10 +20,10 @@ namespace MediaBrowser.Api.Session
     /// </summary>
     [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
     [Authenticated]
-    public class GetSessions : IReturn<SessionInfoDto[]>
+    public class GetSessions : IReturn<SessionInfo[]>
     {
         [ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ControllableByUserId { get; set; }
+        public Guid ControllableByUserId { get; set; }
 
         [ApiMember(Name = "DeviceId", Description = "Optional. Filter by device id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
         public string DeviceId { get; set; }
@@ -351,20 +351,20 @@ public object Get(GetSessions request)
                 result = result.Where(i => string.Equals(i.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase));
             }
 
-            if (!string.IsNullOrWhiteSpace(request.ControllableByUserId))
+            if (!request.ControllableByUserId.Equals(Guid.Empty))
             {
-                result = result.Where(i => i.SupportsMediaControl);
+                result = result.Where(i => i.SupportsRemoteControl);
 
                 var user = _userManager.GetUserById(request.ControllableByUserId);
 
                 if (!user.Policy.EnableRemoteControlOfOtherUsers)
                 {
-                    result = result.Where(i => !i.UserId.HasValue || i.ContainsUser(request.ControllableByUserId));
+                    result = result.Where(i => i.UserId.Equals(Guid.Empty) || i.ContainsUser(request.ControllableByUserId));
                 }
 
                 if (!user.Policy.EnableSharedDeviceControl)
                 {
-                    result = result.Where(i => i.UserId.HasValue);
+                    result = result.Where(i => !i.UserId.Equals(Guid.Empty));
                 }
 
                 result = result.Where(i =>
@@ -383,7 +383,7 @@ public object Get(GetSessions request)
                 });
             }
 
-            return ToOptimizedResult(result.Select(_sessionManager.GetSessionInfoDto).ToArray());
+            return ToOptimizedResult(result.ToArray());
         }
 
         public Task Post(SendPlaystateCommand request)
@@ -426,7 +426,7 @@ public Task Post(SendSystemCommand request)
             var command = new GeneralCommand
             {
                 Name = name,
-                ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null
+                ControllingUserId = currentSession.UserId
             };
 
             return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
@@ -464,7 +464,7 @@ public Task Post(SendGeneralCommand request)
             var command = new GeneralCommand
             {
                 Name = request.Command,
-                ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null
+                ControllingUserId = currentSession.UserId
             };
 
             return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
@@ -474,19 +474,19 @@ public Task Post(SendFullGeneralCommand request)
         {
             var currentSession = GetSession(_sessionContext);
 
-            request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null;
+            request.ControllingUserId = currentSession.UserId;
 
             return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None);
         }
 
         public void Post(AddUserToSession request)
         {
-            _sessionManager.AddAdditionalUser(request.Id, request.UserId);
+            _sessionManager.AddAdditionalUser(request.Id, new Guid(request.UserId));
         }
 
         public void Delete(RemoveUserFromSession request)
         {
-            _sessionManager.RemoveAdditionalUser(request.Id, request.UserId);
+            _sessionManager.RemoveAdditionalUser(request.Id, new Guid(request.UserId));
         }
 
         public void Post(PostCapabilities request)
diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs
index f6367fa37c..be9c1a4c58 100644
--- a/MediaBrowser.Api/SimilarItemsHelper.cs
+++ b/MediaBrowser.Api/SimilarItemsHelper.cs
@@ -49,7 +49,7 @@ public class BaseGetSimilarItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOpt
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// The maximum number of items to return
@@ -73,10 +73,10 @@ public static class SimilarItemsHelper
     {
         internal static QueryResult<BaseItemDto> GetSimilarItemsResult(DtoOptions dtoOptions, IUserManager userManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, ILogger logger, BaseGetSimilarItemsFromItem request, Type[] includeTypes, Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id) ?
-                (!string.IsNullOrWhiteSpace(request.UserId) ? libraryManager.GetUserRootFolder() :
+                (!request.UserId.Equals(Guid.Empty) ? libraryManager.GetUserRootFolder() :
                 libraryManager.RootFolder) : libraryManager.GetItemById(request.Id);
 
             var query = new InternalItemsQuery(user)
diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs
index 7f7d7cbea0..4fbe6841e3 100644
--- a/MediaBrowser.Api/StartupWizardService.cs
+++ b/MediaBrowser.Api/StartupWizardService.cs
@@ -165,11 +165,11 @@ public async Task<object> Post(UpdateStartupUser request)
             if (!string.IsNullOrWhiteSpace(user.ConnectUserName) &&
                 string.IsNullOrWhiteSpace(request.ConnectUserName))
             {
-                await _connectManager.RemoveConnect(user.Id.ToString("N")).ConfigureAwait(false);
+                await _connectManager.RemoveConnect(user).ConfigureAwait(false);
             }
             else if (!string.Equals(user.ConnectUserName, request.ConnectUserName, StringComparison.OrdinalIgnoreCase))
             {
-                result.UserLinkResult = await _connectManager.LinkUser(user.Id.ToString("N"), request.ConnectUserName).ConfigureAwait(false);
+                result.UserLinkResult = await _connectManager.LinkUser(user, request.ConnectUserName).ConfigureAwait(false);
             }
 
             return result;
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index bfd8e4b43f..59e861492d 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -29,7 +29,7 @@ public class DeleteSubtitle
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "DELETE")]
         public int Index { get; set; }
@@ -40,7 +40,7 @@ public class DeleteSubtitle
     public class SearchRemoteSubtitles : IReturn<RemoteSubtitleInfo[]>
     {
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         [ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string Language { get; set; }
@@ -53,7 +53,7 @@ public class SearchRemoteSubtitles : IReturn<RemoteSubtitleInfo[]>
     public class DownloadRemoteSubtitles : IReturnVoid
     {
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         [ApiMember(Name = "SubtitleId", Description = "SubtitleId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
         public string SubtitleId { get; set; }
@@ -76,7 +76,7 @@ public class GetSubtitle
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
         public string MediaSourceId { get; set; }
@@ -198,10 +198,11 @@ public async Task<object> Get(GetSubtitle request)
             }
             if (string.IsNullOrEmpty(request.Format))
             {
-                var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
+                var item = (Video)_libraryManager.GetItemById(request.Id);
 
+                var idString = request.Id.ToString("N");
                 var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false, null)
-                    .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id));
+                    .First(i => string.Equals(i.Id, request.MediaSourceId ?? idString));
 
                 var subtitleStream = mediaSource.MediaStreams
                     .First(i => i.Type == MediaStreamType.Subtitle && i.Index == request.Index);
diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs
index 2ad18796ab..84a73130c1 100644
--- a/MediaBrowser.Api/SuggestionsService.cs
+++ b/MediaBrowser.Api/SuggestionsService.cs
@@ -18,7 +18,7 @@ public class GetSuggestedItems : IReturn<QueryResult<BaseItem>>
     {
         public string MediaType { get; set; }
         public string Type { get; set; }
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
         public bool EnableTotalRecordCount { get; set; }
         public int? StartIndex { get; set; }
         public int? Limit { get; set; }
@@ -56,7 +56,7 @@ public object Get(GetSuggestedItems request)
 
         private QueryResult<BaseItemDto> GetResultItems(GetSuggestedItems request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var dtoOptions = GetDtoOptions(_authContext, request);
             var result = GetItems(request, user, dtoOptions);
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index 7c08966026..4d6ba02266 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -28,7 +28,7 @@ public class GetNextUpEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptio
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -88,7 +88,7 @@ public class GetUpcomingEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasDtoOpt
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
@@ -144,7 +144,7 @@ public class GetEpisodes : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IH
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Fields to return within the items, in addition to basic information
@@ -212,7 +212,7 @@ public class GetSeasons : IReturn<QueryResult<BaseItemDto>>, IHasItemFields, IHa
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Fields to return within the items, in addition to basic information
@@ -302,10 +302,10 @@ public object Get(GetSimilarShows request)
 
         private QueryResult<BaseItemDto> GetSimilarItemsResult(BaseGetSimilarItemsFromItem request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id) ?
-                (!string.IsNullOrWhiteSpace(request.UserId) ? _libraryManager.GetUserRootFolder() :
+                (!request.UserId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() :
                 _libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id);
 
             var dtoOptions = GetDtoOptions(_authContext, request);
@@ -340,7 +340,7 @@ public object Get(GetUpcomingEpisodes request)
 
             var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1);
 
-            var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
+            var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId);
 
             var options = GetDtoOptions(_authContext, request);
 
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
index a911d1c62d..cd3c80463b 100644
--- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
@@ -40,7 +40,7 @@ public class GetArtist : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -70,7 +70,7 @@ private BaseItemDto GetItem(GetArtist request)
 
             var item = GetArtist(request.Name, LibraryManager, dtoOptions);
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
index bbd06eccc4..8e5a54523a 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
@@ -56,7 +56,7 @@ protected BaseItem GetParentItem(GetItemsByName request)
         {
             BaseItem parentItem;
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
                 parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
@@ -95,7 +95,7 @@ protected QueryResult<BaseItemDto> GetResultSlim(GetItemsByName request)
             User user = null;
             BaseItem parentItem;
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 user = UserManager.GetUserById(request.UserId);
                 parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
@@ -246,7 +246,7 @@ protected QueryResult<BaseItemDto> GetResult(GetItemsByName request)
             User user = null;
             BaseItem parentItem;
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 user = UserManager.GetUserById(request.UserId);
                 parentItem = string.IsNullOrEmpty(request.ParentId) ? LibraryManager.GetUserRootFolder() : LibraryManager.GetItemById(request.ParentId);
@@ -276,7 +276,7 @@ protected QueryResult<BaseItemDto> GetResult(GetItemsByName request)
             {
                 var folder = (Folder)parentItem;
 
-                if (!string.IsNullOrWhiteSpace(request.UserId))
+                if (!request.UserId.Equals(Guid.Empty))
                 {
                     items = request.Recursive ?
                         folder.GetRecursiveChildren(user, query).ToList() :
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index d265067d51..96b854ece5 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -298,7 +298,7 @@ protected BaseItemsRequest()
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the min offical rating.
diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
index dd1da7b862..476e881b97 100644
--- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
@@ -31,7 +31,7 @@ public class GetGameGenre : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Authenticated]
@@ -60,7 +60,7 @@ private BaseItemDto GetItem(GetGameGenre request)
 
             var item = GetGameGenre(request.Name, LibraryManager, dtoOptions);
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs
index 9bf38a78a1..0bb7d7865a 100644
--- a/MediaBrowser.Api/UserLibrary/GenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GenresService.cs
@@ -38,7 +38,7 @@ public class GetGenre : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -70,7 +70,7 @@ private BaseItemDto GetItem(GetGenre request)
 
             var item = GetGenre(request.Name, LibraryManager, dtoOptions);
             
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index ade73931f6..adb510bf88 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -88,14 +88,14 @@ public object Get(GetResumeItems request)
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId);
+            var parentIdGuid = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId);
 
             var options = GetDtoOptions(_authContext, request);
 
             var ancestorIds = new List<Guid>();
 
             var excludeFolderIds = user.Configuration.LatestItemsExcludes;
-            if (!parentIdGuid.HasValue && excludeFolderIds.Length > 0)
+            if (parentIdGuid.Equals(Guid.Empty) && excludeFolderIds.Length > 0)
             {
                 ancestorIds = _libraryManager.GetUserRootFolder().GetChildren(user, true)
                     .Where(i => i is Folder)
@@ -156,7 +156,7 @@ public object Get(GetItems request)
         /// <param name="request">The request.</param>
         private QueryResult<BaseItemDto> GetItems(GetItems request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var dtoOptions = GetDtoOptions(_authContext, request);
 
@@ -302,7 +302,7 @@ private InternalItemsQuery GetItemsQuery(GetItems request, DtoOptions dtoOptions
                 MaxPlayers = request.MaxPlayers,
                 MinCommunityRating = request.MinCommunityRating,
                 MinCriticRating = request.MinCriticRating,
-                ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId),
+                ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? Guid.Empty : new Guid(request.ParentId),
                 ParentIndexNumber = request.ParentIndexNumber,
                 AiredDuringSeason = request.AiredDuringSeason,
                 EnableTotalRecordCount = request.EnableTotalRecordCount,
diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
index 90da90bc20..d4f1b3fa8d 100644
--- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
@@ -32,7 +32,7 @@ public class GetMusicGenre : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     [Authenticated]
@@ -61,7 +61,7 @@ private BaseItemDto GetItem(GetMusicGenre request)
 
             var item = GetMusicGenre(request.Name, LibraryManager, dtoOptions);
             
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
index efd4c9415b..1b3a79dc05 100644
--- a/MediaBrowser.Api/UserLibrary/PersonsService.cs
+++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs
@@ -37,7 +37,7 @@ public class GetPerson : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -69,7 +69,7 @@ private BaseItemDto GetItem(GetPerson request)
 
             var item = GetPerson(request.Name, LibraryManager, dtoOptions);
             
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs
index 54248c5fd8..4d0f5170c6 100644
--- a/MediaBrowser.Api/UserLibrary/StudiosService.cs
+++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs
@@ -38,7 +38,7 @@ public class GetStudio : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -70,7 +70,7 @@ private BaseItemDto GetItem(GetStudio request)
 
             var item = GetStudio(request.Name, LibraryManager, dtoOptions);
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 80a6a5f070..dbcd61ec6a 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -29,7 +29,7 @@ public class GetItem : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -50,7 +50,7 @@ public class GetRootFolder : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -64,7 +64,7 @@ public class GetIntros : IReturn<QueryResult<BaseItemDto>>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the item id.
@@ -85,14 +85,14 @@ public class MarkFavoriteItem : IReturn<UserItemDataDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -106,14 +106,14 @@ public class UnmarkFavoriteItem : IReturn<UserItemDataDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -127,14 +127,14 @@ public class DeleteUserItemRating : IReturn<UserItemDataDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -148,14 +148,14 @@ public class UpdateUserItemRating : IReturn<UserItemDataDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         /// <summary>
         /// Gets or sets a value indicating whether this <see cref="UpdateUserItemRating" /> is likes.
@@ -176,7 +176,7 @@ public class GetLocalTrailers : IReturn<BaseItemDto[]>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -197,7 +197,7 @@ public class GetSpecialFeatures : IReturn<BaseItemDto[]>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -215,13 +215,13 @@ public class GetLatestMedia : IReturn<BaseItemDto[]>, IHasDtoOptions
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "Limit", Description = "Limit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
         public int Limit { get; set; }
 
         [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string ParentId { get; set; }
+        public Guid ParentId { get; set; }
 
         [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
         public string Fields { get; set; }
@@ -529,11 +529,11 @@ public object Delete(UnmarkFavoriteItem request)
         /// <param name="userId">The user id.</param>
         /// <param name="itemId">The item id.</param>
         /// <param name="isFavorite">if set to <c>true</c> [is favorite].</param>
-        private UserItemDataDto MarkFavorite(string userId, string itemId, bool isFavorite)
+        private UserItemDataDto MarkFavorite(Guid userId, Guid itemId, bool isFavorite)
         {
             var user = _userManager.GetUserById(userId);
 
-            var item = string.IsNullOrEmpty(itemId) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
+            var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
 
             // Get the user data for this item
             var data = _userDataRepository.GetUserData(user, item);
@@ -574,11 +574,11 @@ public object Post(UpdateUserItemRating request)
         /// <param name="userId">The user id.</param>
         /// <param name="itemId">The item id.</param>
         /// <param name="likes">if set to <c>true</c> [likes].</param>
-        private UserItemDataDto UpdateUserItemRating(string userId, string itemId, bool? likes)
+        private UserItemDataDto UpdateUserItemRating(Guid userId, Guid itemId, bool? likes)
         {
             var user = _userManager.GetUserById(userId);
 
-            var item = string.IsNullOrEmpty(itemId) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
+            var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
 
             // Get the user data for this item
             var data = _userDataRepository.GetUserData(user, item);
diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
index 3e15f870f6..8d047c64fd 100644
--- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
@@ -24,7 +24,7 @@ public class GetUserViews : IReturn<QueryResult<BaseItemDto>>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         [ApiMember(Name = "IncludeExternalContent", Description = "Whether or not to include external views such as channels or live tv", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
         public bool? IncludeExternalContent { get; set; }
@@ -41,7 +41,7 @@ public class GetGroupingOptions : IReturn<SpecialViewOption[]>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     public class UserViewsService : BaseApiService
diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs
index 676c1a911c..30ac88e00f 100644
--- a/MediaBrowser.Api/UserLibrary/YearsService.cs
+++ b/MediaBrowser.Api/UserLibrary/YearsService.cs
@@ -7,6 +7,7 @@
 using System.Collections.Generic;
 using System.Linq;
 using MediaBrowser.Model.Services;
+using System;
 
 namespace MediaBrowser.Api.UserLibrary
 {
@@ -36,7 +37,7 @@ public class GetYear : IReturn<BaseItemDto>
         /// </summary>
         /// <value>The user id.</value>
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
     }
 
     /// <summary>
@@ -68,7 +69,7 @@ private BaseItemDto GetItem(GetYear request)
             
             var dtoOptions = GetDtoOptions(AuthorizationContext, request);
 
-            if (!string.IsNullOrWhiteSpace(request.UserId))
+            if (!request.UserId.Equals(Guid.Empty))
             {
                 var user = UserManager.GetUserById(request.UserId);
 
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index fa271dbc80..29f3070a59 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -14,6 +14,7 @@
 using System.Linq;
 using System.Threading.Tasks;
 using MediaBrowser.Model.Services;
+using MediaBrowser.Controller.Authentication;
 
 namespace MediaBrowser.Api
 {
@@ -51,22 +52,7 @@ public class GetUser : IReturn<UserDto>
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
-    }
-
-    /// <summary>
-    /// Class GetUser
-    /// </summary>
-    [Route("/Users/{Id}/Offline", "GET", Summary = "Gets an offline user record by Id")]
-    [Authenticated]
-    public class GetOfflineUser : IReturn<UserDto>
-    {
-        /// <summary>
-        /// Gets or sets the id.
-        /// </summary>
-        /// <value>The id.</value>
-        [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -81,7 +67,7 @@ public class DeleteUser : IReturnVoid
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -95,7 +81,7 @@ public class AuthenticateUser : IReturn<AuthenticationResult>
         /// </summary>
         /// <value>The id.</value>
         [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
         public string Pw { get; set; }
@@ -143,7 +129,7 @@ public class UpdateUserPassword : IReturnVoid
         /// Gets or sets the id.
         /// </summary>
         /// <value>The id.</value>
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         /// <summary>
         /// Gets or sets the password.
@@ -173,7 +159,7 @@ public class UpdateUserEasyPassword : IReturnVoid
         /// Gets or sets the id.
         /// </summary>
         /// <value>The id.</value>
-        public string Id { get; set; }
+        public Guid Id { get; set; }
 
         /// <summary>
         /// Gets or sets the new password.
@@ -207,7 +193,7 @@ public class UpdateUser : UserDto, IReturnVoid
     public class UpdateUserPolicy : UserPolicy, IReturnVoid
     {
         [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -218,7 +204,7 @@ public class UpdateUserPolicy : UserPolicy, IReturnVoid
     public class UpdateUserConfiguration : UserConfiguration, IReturnVoid
     {
         [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
-        public string Id { get; set; }
+        public Guid Id { get; set; }
     }
 
     /// <summary>
@@ -364,20 +350,6 @@ public object Get(GetUser request)
             return ToOptimizedResult(result);
         }
 
-        public object Get(GetOfflineUser request)
-        {
-            var user = _userManager.GetUserById(request.Id);
-
-            if (user == null)
-            {
-                throw new ResourceNotFoundException("User not found");
-            }
-
-            var result = _userManager.GetOfflineUserDto(user);
-
-            return ToOptimizedResult(result);
-        }
-
         /// <summary>
         /// Deletes the specified request.
         /// </summary>
@@ -396,7 +368,7 @@ public Task DeleteAsync(DeleteUser request)
                 throw new ResourceNotFoundException("User not found");
             }
 
-            _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), null);
+            _sessionMananger.RevokeUserTokens(user.Id, null);
 
             return _userManager.DeleteUser(user);
         }
@@ -479,7 +451,7 @@ public async Task PostAsync(UpdateUserPassword request)
 
                 var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
 
-                _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken);
+                _sessionMananger.RevokeUserTokens(user.Id, currentToken);
             }
         }
 
@@ -512,7 +484,7 @@ public async Task Post(UpdateUser request)
         {
             var id = GetPathValue(1);
 
-            AssertCanUpdateUser(_authContext, _userManager, id, false);
+            AssertCanUpdateUser(_authContext, _userManager, new Guid(id), false);
 
             var dtoUser = request;
 
@@ -604,7 +576,7 @@ public void Post(UpdateUserPolicy request)
                 }
 
                 var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
-                _sessionMananger.RevokeUserTokens(user.Id.ToString("N"), currentToken);
+                _sessionMananger.RevokeUserTokens(user.Id, currentToken);
             }
 
             _userManager.UpdateUserPolicy(request.Id, request);
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
index e1b335ca83..8815027982 100644
--- a/MediaBrowser.Api/VideosService.cs
+++ b/MediaBrowser.Api/VideosService.cs
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api
     public class GetAdditionalParts : IReturn<QueryResult<BaseItemDto>>
     {
         [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
-        public string UserId { get; set; }
+        public Guid UserId { get; set; }
 
         /// <summary>
         /// Gets or sets the id.
@@ -76,10 +76,10 @@ public VideosService(ILibraryManager libraryManager, IUserManager userManager, I
         /// <returns>System.Object.</returns>
         public object Get(GetAdditionalParts request)
         {
-            var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null;
+            var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
 
             var item = string.IsNullOrEmpty(request.Id)
-                           ? (!string.IsNullOrWhiteSpace(request.UserId)
+                           ? (!request.UserId.Equals(Guid.Empty)
                                   ? _libraryManager.GetUserRootFolder()
                                   : _libraryManager.RootFolder)
                            : _libraryManager.GetItemById(request.Id);
diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/MediaBrowser.Api/packages.config
+++ b/MediaBrowser.Api/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
index 021f5fd3c7..479f6035c9 100644
--- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
@@ -57,13 +57,13 @@
     <Compile Include="Savers\PersonXmlSaver.cs" />
     <Compile Include="Savers\PlaylistXmlSaver.cs" />
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/MediaBrowser.LocalMetadata/packages.config b/MediaBrowser.LocalMetadata/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/MediaBrowser.LocalMetadata/packages.config
+++ b/MediaBrowser.LocalMetadata/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 185c420498..1e13b6565c 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -734,7 +734,7 @@ public Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, T
         {
             BaseItem referenceItem = null;
 
-            if (!string.IsNullOrEmpty(searchInfo.ItemId))
+            if (!searchInfo.ItemId.Equals(Guid.Empty))
             {
                 referenceItem = _libraryManagerFactory().GetItemById(searchInfo.ItemId);
             }
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index fe00cfb45b..f5c691ddc6 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -140,13 +140,13 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath>
diff --git a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
index 0cb0e643b6..cea907ca3e 100644
--- a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
+++ b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
@@ -35,14 +35,14 @@ protected override ItemUpdateType BeforeSaveInternal(Episode item, bool isFullRe
             }
 
             var seriesId = item.FindSeriesId();
-            if (item.SeriesId != seriesId)
+            if (!item.SeriesId.Equals(seriesId))
             {
                 item.SeriesId = seriesId;
                 updateType |= ItemUpdateType.MetadataImport;
             }
 
             var seasonId = item.FindSeasonId();
-            if (item.SeasonId != seasonId)
+            if (!item.SeasonId.Equals(seasonId))
             {
                 item.SeasonId = seasonId;
                 updateType |= ItemUpdateType.MetadataImport;
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 74140aa8c0..1c97774cad 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -403,7 +403,7 @@ private async Task AddEpisode(Series series, int seasonNumber, int episodeNumber
                 ParentIndexNumber = seasonNumber,
                 Id = _libraryManager.GetNewItemId((series.Id + seasonNumber.ToString(_usCulture) + name), typeof(Episode)),
                 IsVirtualItem = true,
-                SeasonId = season == null ? (Guid?)null : season.Id,
+                SeasonId = season == null ? Guid.Empty : season.Id,
                 SeriesId = series.Id
             };
 
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index f45c5cb0f5..a9a026db9d 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -45,7 +45,7 @@ protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRef
             }
 
             var seriesId = item.FindSeriesId();
-            if (item.SeriesId != seriesId)
+            if (!item.SeriesId.Equals(seriesId))
             {
                 item.SeriesId = seriesId;
                 updateType |= ItemUpdateType.MetadataImport;
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
index 13d21165a7..582093183a 100644
--- a/MediaBrowser.Providers/packages.config
+++ b/MediaBrowser.Providers/packages.config
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
   <package id="Microsoft.NETCore.Platforms" version="2.1.0" targetFramework="net47" />
   <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net47" />
   <package id="NETStandard.Library" version="2.0.3" targetFramework="net47" />
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index 57bb823d66..9b24b2ce90 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -51,13 +51,13 @@
       <HintPath>..\packages\Emby.XmlTv.1.0.14\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
diff --git a/MediaBrowser.Server.Mono/packages.config b/MediaBrowser.Server.Mono/packages.config
index 349d991244..e593753cf8 100644
--- a/MediaBrowser.Server.Mono/packages.config
+++ b/MediaBrowser.Server.Mono/packages.config
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Emby.XmlTv" version="1.0.14" targetFramework="net46" />
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
   <package id="ServiceStack.Text" version="4.5.8" targetFramework="net46" />
   <package id="SharpCompress" version="0.18.2" targetFramework="net46" />
   <package id="SimpleInjector" version="4.3.0" targetFramework="net47" />
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 5784929296..499df40b65 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -77,13 +77,13 @@
       <HintPath>..\packages\Emby.XmlTv.1.0.14\lib\portable-net45+netstandard2.0+win8\Emby.XmlTv.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index 07d6588607..f8f1c5f808 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
   <package id="Emby.XmlTv" version="1.0.14" targetFramework="net462" />
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
   <package id="ServiceStack.Text" version="4.5.8" targetFramework="net462" />
   <package id="SharpCompress" version="0.18.2" targetFramework="net462" />
   <package id="SimpleInjector" version="4.3.0" targetFramework="net47" />
diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
index 0de45edda4..8a9d99bfb2 100644
--- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj
+++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
@@ -41,13 +41,13 @@
       <HintPath>..\ThirdParty\emby\Emby.Server.MediaEncoding.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.XML" />
diff --git a/MediaBrowser.Tests/packages.config b/MediaBrowser.Tests/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/MediaBrowser.Tests/packages.config
+++ b/MediaBrowser.Tests/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 34fa9b1961..6f2c693e1a 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -46,13 +46,13 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ServerEntryPoint.cs" />
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
index bc1798be40..9a3626a8b9 100644
--- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
+++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
@@ -61,13 +61,13 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Controller, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Server.Core.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Controller.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/MediaBrowser.XbmcMetadata/packages.config b/MediaBrowser.XbmcMetadata/packages.config
index 7be57463d7..b703a4ca6e 100644
--- a/MediaBrowser.XbmcMetadata/packages.config
+++ b/MediaBrowser.XbmcMetadata/packages.config
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
-  <package id="MediaBrowser.Server.Core" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Server.Core" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/Mono.Nat/Mono.Nat.csproj b/Mono.Nat/Mono.Nat.csproj
index fe27272d21..496857fcc5 100644
--- a/Mono.Nat/Mono.Nat.csproj
+++ b/Mono.Nat/Mono.Nat.csproj
@@ -32,10 +32,10 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
diff --git a/Mono.Nat/packages.config b/Mono.Nat/packages.config
index 3585af4ad8..c6ba3586c6 100644
--- a/Mono.Nat/packages.config
+++ b/Mono.Nat/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/RSSDP/RSSDP.csproj b/RSSDP/RSSDP.csproj
index 656b4dfe07..5db502cd7a 100644
--- a/RSSDP/RSSDP.csproj
+++ b/RSSDP/RSSDP.csproj
@@ -58,10 +58,10 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
diff --git a/RSSDP/packages.config b/RSSDP/packages.config
index 3585af4ad8..c6ba3586c6 100644
--- a/RSSDP/packages.config
+++ b/RSSDP/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/SharedVersion.cs b/SharedVersion.cs
index e3d43594b1..b7dfc43bdc 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
 using System.Reflection;
 
-[assembly: AssemblyVersion("3.4.1.13")]
+[assembly: AssemblyVersion("3.4.1.14")]
diff --git a/SocketHttpListener/SocketHttpListener.csproj b/SocketHttpListener/SocketHttpListener.csproj
index 558d9de2c4..aacd43e56e 100644
--- a/SocketHttpListener/SocketHttpListener.csproj
+++ b/SocketHttpListener/SocketHttpListener.csproj
@@ -36,10 +36,10 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="MediaBrowser.Common, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Common.dll</HintPath>
     </Reference>
     <Reference Include="MediaBrowser.Model, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\packages\MediaBrowser.Common.3.3.47-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
+      <HintPath>..\packages\MediaBrowser.Common.3.3.48-beta\lib\netstandard2.0\MediaBrowser.Model.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
diff --git a/SocketHttpListener/packages.config b/SocketHttpListener/packages.config
index 3585af4ad8..c6ba3586c6 100644
--- a/SocketHttpListener/packages.config
+++ b/SocketHttpListener/packages.config
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="MediaBrowser.Common" version="3.3.47-beta" targetFramework="net47" />
+  <package id="MediaBrowser.Common" version="3.3.48-beta" targetFramework="net47" />
 </packages>
\ No newline at end of file
diff --git a/ThirdParty/emby/Emby.Server.Connect.dll b/ThirdParty/emby/Emby.Server.Connect.dll
index c6792103d4..bee397c2fd 100644
Binary files a/ThirdParty/emby/Emby.Server.Connect.dll and b/ThirdParty/emby/Emby.Server.Connect.dll differ
diff --git a/ThirdParty/emby/Emby.Server.MediaEncoding.dll b/ThirdParty/emby/Emby.Server.MediaEncoding.dll
index fbcf1c438e..ab0aeed81d 100644
Binary files a/ThirdParty/emby/Emby.Server.MediaEncoding.dll and b/ThirdParty/emby/Emby.Server.MediaEncoding.dll differ
diff --git a/ThirdParty/emby/Emby.Server.Sync.dll b/ThirdParty/emby/Emby.Server.Sync.dll
index ef239a665b..4421cd9bfd 100644
Binary files a/ThirdParty/emby/Emby.Server.Sync.dll and b/ThirdParty/emby/Emby.Server.Sync.dll differ
diff --git a/packages/MediaBrowser.Common.3.3.47-beta/MediaBrowser.Common.3.3.47-beta.nupkg b/packages/MediaBrowser.Common.3.3.47-beta/MediaBrowser.Common.3.3.47-beta.nupkg
deleted file mode 100644
index ccd7b17ee1..0000000000
Binary files a/packages/MediaBrowser.Common.3.3.47-beta/MediaBrowser.Common.3.3.47-beta.nupkg and /dev/null differ
diff --git a/packages/MediaBrowser.Common.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Model.dll b/packages/MediaBrowser.Common.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Model.dll
deleted file mode 100644
index 22842bc4eb..0000000000
Binary files a/packages/MediaBrowser.Common.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Model.dll and /dev/null differ
diff --git a/packages/MediaBrowser.Common.3.3.48-beta/MediaBrowser.Common.3.3.48-beta.nupkg b/packages/MediaBrowser.Common.3.3.48-beta/MediaBrowser.Common.3.3.48-beta.nupkg
new file mode 100644
index 0000000000..10fb24d72d
Binary files /dev/null and b/packages/MediaBrowser.Common.3.3.48-beta/MediaBrowser.Common.3.3.48-beta.nupkg differ
diff --git a/packages/MediaBrowser.Common.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Common.dll b/packages/MediaBrowser.Common.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Common.dll
similarity index 100%
rename from packages/MediaBrowser.Common.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Common.dll
rename to packages/MediaBrowser.Common.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Common.dll
diff --git a/packages/MediaBrowser.Common.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Model.dll b/packages/MediaBrowser.Common.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Model.dll
new file mode 100644
index 0000000000..296c15f662
Binary files /dev/null and b/packages/MediaBrowser.Common.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Model.dll differ
diff --git a/packages/MediaBrowser.Server.Core.3.3.47-beta/MediaBrowser.Server.Core.3.3.47-beta.nupkg b/packages/MediaBrowser.Server.Core.3.3.47-beta/MediaBrowser.Server.Core.3.3.47-beta.nupkg
deleted file mode 100644
index 2cbbd7e8e4..0000000000
Binary files a/packages/MediaBrowser.Server.Core.3.3.47-beta/MediaBrowser.Server.Core.3.3.47-beta.nupkg and /dev/null differ
diff --git a/packages/MediaBrowser.Server.Core.3.3.48-beta/MediaBrowser.Server.Core.3.3.48-beta.nupkg b/packages/MediaBrowser.Server.Core.3.3.48-beta/MediaBrowser.Server.Core.3.3.48-beta.nupkg
new file mode 100644
index 0000000000..fb02e25874
Binary files /dev/null and b/packages/MediaBrowser.Server.Core.3.3.48-beta/MediaBrowser.Server.Core.3.3.48-beta.nupkg differ
diff --git a/packages/MediaBrowser.Server.Core.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Controller.dll b/packages/MediaBrowser.Server.Core.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Controller.dll
similarity index 94%
rename from packages/MediaBrowser.Server.Core.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Controller.dll
rename to packages/MediaBrowser.Server.Core.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Controller.dll
index 8c20a70f08..1de8065f61 100644
Binary files a/packages/MediaBrowser.Server.Core.3.3.47-beta/lib/netstandard2.0/MediaBrowser.Controller.dll and b/packages/MediaBrowser.Server.Core.3.3.48-beta/lib/netstandard2.0/MediaBrowser.Controller.dll differ