diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs
index ebae1caa0e..4de87616c5 100644
--- a/Jellyfin.Api/Controllers/AudioController.cs
+++ b/Jellyfin.Api/Controllers/AudioController.cs
@@ -144,10 +144,10 @@ namespace Jellyfin.Api.Controllers
/// Optional. The streaming options.
/// Audio stream returned.
/// A containing the audio file.
- [HttpGet("{itemId}/{stream=stream}.{container?}")]
- [HttpGet("{itemId}/stream")]
- [HttpHead("{itemId}/{stream=stream}.{container?}")]
- [HttpHead("{itemId}/stream")]
+ [HttpGet("{itemId}/{stream=stream}.{container?}", Name = "GetAudioStreamByContainer")]
+ [HttpGet("{itemId}/stream", Name = "GetAudioStream")]
+ [HttpHead("{itemId}/{stream=stream}.{container?}", Name = "HeadAudioStreamByContainer")]
+ [HttpHead("{itemId}/stream", Name = "HeadAudioStream")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetAudioStream(
[FromRoute] Guid itemId,
diff --git a/Jellyfin.Api/Controllers/BrandingController.cs b/Jellyfin.Api/Controllers/BrandingController.cs
index 67790c0e4a..1d4836f278 100644
--- a/Jellyfin.Api/Controllers/BrandingController.cs
+++ b/Jellyfin.Api/Controllers/BrandingController.cs
@@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers
/// or a if the css is not configured.
///
[HttpGet("Css")]
- [HttpGet("Css.css")]
+ [HttpGet("Css.css", Name = "GetBrandingCss_2")]
[Produces("text/css")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs
index 2f5561adb9..ef507f2ed6 100644
--- a/Jellyfin.Api/Controllers/DlnaServerController.cs
+++ b/Jellyfin.Api/Controllers/DlnaServerController.cs
@@ -42,8 +42,8 @@ namespace Jellyfin.Api.Controllers
/// Server UUID.
/// Description xml returned.
/// An containing the description xml.
- [HttpGet("{serverId}/description.xml")]
[HttpGet("{serverId}/description")]
+ [HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")]
[Produces(XMLContentType)]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetDescriptionXml([FromRoute] string serverId)
@@ -60,8 +60,8 @@ namespace Jellyfin.Api.Controllers
/// Server UUID.
/// Dlna content directory returned.
/// An containing the dlna content directory xml.
- [HttpGet("{serverId}/ContentDirectory/ContentDirectory.xml")]
[HttpGet("{serverId}/ContentDirectory/ContentDirectory")]
+ [HttpGet("{serverId}/ContentDirectory/ContentDirectory.xml", Name = "GetContentDirectory_2")]
[Produces(XMLContentType)]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
@@ -75,8 +75,8 @@ namespace Jellyfin.Api.Controllers
///
/// Server UUID.
/// Dlna media receiver registrar xml.
- [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar.xml")]
[HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar")]
+ [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar.xml", Name = "GetMediaReceiverRegistrar_2")]
[Produces(XMLContentType)]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
@@ -90,8 +90,8 @@ namespace Jellyfin.Api.Controllers
///
/// Server UUID.
/// Dlna media receiver registrar xml.
- [HttpGet("{serverId}/ConnectionManager/ConnectionManager.xml")]
[HttpGet("{serverId}/ConnectionManager/ConnectionManager")]
+ [HttpGet("{serverId}/ConnectionManager/ConnectionManager.xml", Name = "GetConnectionManager_2")]
[Produces(XMLContentType)]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
@@ -181,7 +181,7 @@ namespace Jellyfin.Api.Controllers
/// Server UUID.
/// The icon filename.
/// Icon stream.
- [HttpGet("{serverId}/icons/{filename}")]
+ [HttpGet("{serverId}/icons/{fileName}")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")]
public ActionResult GetIconId([FromRoute] string serverId, [FromRoute] string fileName)
{
@@ -193,7 +193,7 @@ namespace Jellyfin.Api.Controllers
///
/// The icon filename.
/// Icon stream.
- [HttpGet("icons/{filename}")]
+ [HttpGet("icons/{fileName}")]
public ActionResult GetIcon([FromRoute] string fileName)
{
return GetIconInternal(fileName);
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index b7e1837c97..c4f79ce950 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -165,7 +165,7 @@ namespace Jellyfin.Api.Controllers
/// Video stream returned.
/// A containing the playlist file.
[HttpGet("/Videos/{itemId}/master.m3u8")]
- [HttpHead("/Videos/{itemId}/master.m3u8")]
+ [HttpHead("/Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetMasterHlsVideoPlaylist(
[FromRoute] Guid itemId,
@@ -335,7 +335,7 @@ namespace Jellyfin.Api.Controllers
/// Audio stream returned.
/// A containing the playlist file.
[HttpGet("/Audio/{itemId}/master.m3u8")]
- [HttpHead("/Audio/{itemId}/master.m3u8")]
+ [HttpHead("/Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetMasterHlsAudioPlaylist(
[FromRoute] Guid itemId,
diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs
index efdb6a3691..7bf9326a71 100644
--- a/Jellyfin.Api/Controllers/HlsSegmentController.cs
+++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs
@@ -50,8 +50,8 @@ namespace Jellyfin.Api.Controllers
/// A containing the audio stream.
// Can't require authentication just yet due to seeing some requests come from Chrome without full query string
// [Authenticated]
- [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.mp3")]
- [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.aac")]
+ [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.mp3", Name = "GetHlsAudioSegmentLegacyMp3")]
+ [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")]
[ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")]
public ActionResult GetHlsAudioSegmentLegacy([FromRoute] string itemId, [FromRoute] string segmentId)
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index 18220c5f34..3a445b1b3c 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -82,7 +82,7 @@ namespace Jellyfin.Api.Controllers
/// User does not have permission to delete the image.
/// A .
[HttpPost("/Users/{userId}/Images/{imageType}")]
- [HttpPost("/Users/{userId}/Images/{imageType}/{index?}")]
+ [HttpPost("/Users/{userId}/Images/{imageType}/{index?}", Name = "PostUserImage_2")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
@@ -128,7 +128,7 @@ namespace Jellyfin.Api.Controllers
/// User does not have permission to delete the image.
/// A .
[HttpDelete("/Users/{userId}/Images/{itemType}")]
- [HttpDelete("/Users/{userId}/Images/{itemType}/{index?}")]
+ [HttpDelete("/Users/{userId}/Images/{itemType}/{index?}", Name = "DeleteUserImage_2")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
@@ -167,7 +167,7 @@ namespace Jellyfin.Api.Controllers
/// Item not found.
/// A on success, or a if item not found.
[HttpDelete("/Items/{itemId}/Images/{imageType}")]
- [HttpDelete("/Items/{itemId}/Images/{imageType}/{imageIndex?}")]
+ [HttpDelete("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "DeleteItemImage_2")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -196,7 +196,7 @@ namespace Jellyfin.Api.Controllers
/// Item not found.
/// A on success, or a if item not found.
[HttpPost("/Items/{itemId}/Images/{imageType}")]
- [HttpPost("/Items/{itemId}/Images/{imageType}/{imageIndex?}")]
+ [HttpPost("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "SetItemImage_2")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
@@ -342,9 +342,9 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Items/{itemId}/Images/{imageType}")]
- [HttpHead("/Items/{itemId}/Images/{imageType}")]
- [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/Items/{itemId}/Images/{imageType}", Name = "HeadItemImage")]
+ [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "GetItemImage_2")]
+ [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "HeadItemImage_2")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetItemImage(
@@ -422,7 +422,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}")]
- [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}")]
+ [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}", Name = "HeadItemImage2")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetItemImage2(
@@ -500,7 +500,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Artists/{name}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/Artists/{name}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/Artists/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadArtistImage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetArtistImage(
@@ -578,7 +578,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Genres/{name}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/Genres/{name}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/Genres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadGenreImage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetGenreImage(
@@ -656,7 +656,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadMusicGenreImage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetMusicGenreImage(
@@ -734,7 +734,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Persons/{name}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/Persons/{name}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/Persons/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadPersonImage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetPersonImage(
@@ -812,7 +812,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Studios/{name}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/Studios/{name}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/Studios/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadStudioImage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetStudioImage(
@@ -890,7 +890,7 @@ namespace Jellyfin.Api.Controllers
/// or a if item not found.
///
[HttpGet("/Users/{userId}/Images/{imageType}/{imageIndex?}")]
- [HttpHead("/Users/{userId}/Images/{imageType}/{imageIndex?}")]
+ [HttpHead("/Users/{userId}/Images/{imageType}/{imageIndex?}", Name = "HeadUserImage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task GetUserImage(
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 49fb9238f1..354741ced1 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers
/// Optional, include image information in output.
/// A with the items.
[HttpGet("/Items")]
- [HttpGet("/Users/{uId}/Items")]
+ [HttpGet("/Users/{uId}/Items", Name = "GetItems_2")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetItems(
[FromRoute] Guid? uId,
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index 5ad466c557..0ec7e2b8c0 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -521,7 +521,7 @@ namespace Jellyfin.Api.Controllers
/// The tvdbId.
/// Report success.
/// A .
- [HttpPost("/Library/Series/Added")]
+ [HttpPost("/Library/Series/Added", Name = "PostAddedSeries")]
[HttpPost("/Library/Series/Updated")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
@@ -551,7 +551,7 @@ namespace Jellyfin.Api.Controllers
/// The imdbId.
/// Report success.
/// A .
- [HttpPost("/Library/Movies/Added")]
+ [HttpPost("/Library/Movies/Added", Name = "PostAddedMovies")]
[HttpPost("/Library/Movies/Updated")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
@@ -679,12 +679,12 @@ namespace Jellyfin.Api.Controllers
/// Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.
/// Similar items returned.
/// A containing the similar items.
- [HttpGet("/Artists/{itemId}/Similar")]
+ [HttpGet("/Artists/{itemId}/Similar", Name = "GetSimilarArtists2")]
[HttpGet("/Items/{itemId}/Similar")]
- [HttpGet("/Albums/{itemId}/Similar")]
- [HttpGet("/Shows/{itemId}/Similar")]
- [HttpGet("/Movies/{itemId}/Similar")]
- [HttpGet("/Trailers/{itemId}/Similar")]
+ [HttpGet("/Albums/{itemId}/Similar", Name = "GetSimilarAlbums2")]
+ [HttpGet("/Shows/{itemId}/Similar", Name = "GetSimilarShows2")]
+ [HttpGet("/Movies/{itemId}/Similar", Name = "GetSimilarMovies2")]
+ [HttpGet("/Trailers/{itemId}/Similar", Name = "GetSimilarTrailers2")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult> GetSimilarItems(
[FromRoute] Guid itemId,
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index bbe5544f93..89112eea7d 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -127,7 +127,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Channels")]
[ProducesResponseType(StatusCodes.Status200OK)]
[Authorize(Policy = Policies.DefaultAuthorization)]
- public ActionResult> GetChannels(
+ public ActionResult> GetLiveTvChannels(
[FromQuery] ChannelType? type,
[FromQuery] Guid? userId,
[FromQuery] int? startIndex,
@@ -535,7 +535,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Programs")]
[ProducesResponseType(StatusCodes.Status200OK)]
[Authorize(Policy = Policies.DefaultAuthorization)]
- public async Task>> GetPrograms(
+ public async Task>> GetLiveTvPrograms(
[FromQuery] string? channelIds,
[FromQuery] Guid? userId,
[FromQuery] DateTime? minStartDate,
@@ -933,7 +933,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Obsolete("This endpoint is obsolete.")]
- public ActionResult GetRecordingGroup([FromQuery] Guid? groupId)
+ public ActionResult GetRecordingGroup([FromRoute] Guid? groupId)
{
return NotFound();
}
diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs
index 0c98a8e711..1b300e0d8a 100644
--- a/Jellyfin.Api/Controllers/SessionController.cs
+++ b/Jellyfin.Api/Controllers/SessionController.cs
@@ -241,7 +241,7 @@ namespace Jellyfin.Api.Controllers
/// The command to send.
/// General command sent to session.
/// A .
- [HttpPost("/Sessions/{sessionId}/Command/{Command}")]
+ [HttpPost("/Sessions/{sessionId}/Command/{command}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendGeneralCommand(
[FromRoute] string? sessionId,
diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs
index f9e4e61b5e..c8e3cc4f52 100644
--- a/Jellyfin.Api/Controllers/StartupController.cs
+++ b/Jellyfin.Api/Controllers/StartupController.cs
@@ -106,7 +106,7 @@ namespace Jellyfin.Api.Controllers
/// Initial user retrieved.
/// The first user.
[HttpGet("User")]
- [HttpGet("FirstUser")]
+ [HttpGet("FirstUser", Name = "GetFirstUser_2")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetFirstUser()
{
@@ -131,7 +131,7 @@ namespace Jellyfin.Api.Controllers
///
[HttpPost("User")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public async Task UpdateUser([FromForm] StartupUserDto startupUserDto)
+ public async Task UpdateStartupUser([FromForm] StartupUserDto startupUserDto)
{
var user = _userManager.Users.First();
diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs
index b62ff80fcf..f8c19d15c4 100644
--- a/Jellyfin.Api/Controllers/SubtitleController.cs
+++ b/Jellyfin.Api/Controllers/SubtitleController.cs
@@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers
/// File returned.
/// A with the subtitle file.
[HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")]
- [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}")]
+ [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}", Name = "GetSubtitle_2")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetSubtitle(
[FromRoute, Required] Guid itemId,
diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs
index 55ed42227d..2b1b95b1b5 100644
--- a/Jellyfin.Api/Controllers/SyncPlayController.cs
+++ b/Jellyfin.Api/Controllers/SyncPlayController.cs
@@ -47,7 +47,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("New")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult CreateNewGroup()
+ public ActionResult SyncPlayCreateGroup()
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
_syncPlayManager.NewGroup(currentSession, CancellationToken.None);
@@ -62,7 +62,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Join")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult JoinGroup([FromQuery, Required] Guid groupId)
+ public ActionResult SyncPlayJoinGroup([FromQuery, Required] Guid groupId)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
@@ -82,7 +82,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Leave")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult LeaveGroup()
+ public ActionResult SyncPlayLeaveGroup()
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
_syncPlayManager.LeaveGroup(currentSession, CancellationToken.None);
@@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers
/// An containing the available SyncPlay groups.
[HttpGet("List")]
[ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult> GetSyncPlayGroups([FromQuery] Guid? filterItemId)
+ public ActionResult> SyncPlayGetGroups([FromQuery] Guid? filterItemId)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
return Ok(_syncPlayManager.ListGroups(currentSession, filterItemId.HasValue ? filterItemId.Value : Guid.Empty));
@@ -110,7 +110,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Play")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult Play()
+ public ActionResult SyncPlayPlay()
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
var syncPlayRequest = new PlaybackRequest()
@@ -128,7 +128,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Pause")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult Pause()
+ public ActionResult SyncPlayPause()
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
var syncPlayRequest = new PlaybackRequest()
@@ -147,7 +147,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Seek")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult Seek([FromQuery] long positionTicks)
+ public ActionResult SyncPlaySeek([FromQuery] long positionTicks)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
var syncPlayRequest = new PlaybackRequest()
@@ -169,7 +169,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Buffering")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult Buffering([FromQuery] DateTime when, [FromQuery] long positionTicks, [FromQuery] bool bufferingDone)
+ public ActionResult SyncPlayBuffering([FromQuery] DateTime when, [FromQuery] long positionTicks, [FromQuery] bool bufferingDone)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
var syncPlayRequest = new PlaybackRequest()
@@ -190,7 +190,7 @@ namespace Jellyfin.Api.Controllers
/// A indicating success.
[HttpPost("Ping")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult Ping([FromQuery] double ping)
+ public ActionResult SyncPlayPing([FromQuery] double ping)
{
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request);
var syncPlayRequest = new PlaybackRequest()
diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs
index bc606f7aad..e0bce3a417 100644
--- a/Jellyfin.Api/Controllers/SystemController.cs
+++ b/Jellyfin.Api/Controllers/SystemController.cs
@@ -85,8 +85,8 @@ namespace Jellyfin.Api.Controllers
///
/// Information retrieved.
/// The server name.
- [HttpGet("Ping")]
- [HttpPost("Ping")]
+ [HttpGet("Ping", Name = "GetPingSystem")]
+ [HttpPost("Ping", Name = "PostPingSystem")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult PingSystem()
{
diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs
index 50ab0ac054..5a9bec2b05 100644
--- a/Jellyfin.Api/Controllers/UniversalAudioController.cs
+++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs
@@ -69,9 +69,9 @@ namespace Jellyfin.Api.Controllers
/// Redirected to remote audio stream.
/// A containing the audio file.
[HttpGet("/Audio/{itemId}/universal")]
- [HttpGet("/Audio/{itemId}/{universal=universal}.{container?}")]
- [HttpHead("/Audio/{itemId}/universal")]
- [HttpHead("/Audio/{itemId}/{universal=universal}.{container?}")]
+ [HttpGet("/Audio/{itemId}/{universal=universal}.{container?}", Name = "GetUniversalAudioStream_2")]
+ [HttpHead("/Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")]
+ [HttpHead("/Audio/{itemId}/{universal=universal}.{container?}", Name = "HeadUniversalAudioStream_2")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status302Found)]
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index d1ef817eb6..ebe88a9c05 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -316,10 +316,10 @@ namespace Jellyfin.Api.Controllers
/// Optional. The streaming options.
/// Video stream returned.
/// A containing the audio file.
- [HttpGet("{itemId}/{stream=stream}.{container?}")]
+ [HttpGet("{itemId}/{stream=stream}.{container?}", Name = "GetVideoStream_2")]
[HttpGet("{itemId}/stream")]
- [HttpHead("{itemId}/{stream=stream}.{container?}")]
- [HttpHead("{itemId}/stream")]
+ [HttpHead("{itemId}/{stream=stream}.{container?}", Name = "HeadVideoStream_2")]
+ [HttpHead("{itemId}/stream", Name = "HeadVideoStream")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task GetVideoStream(
[FromRoute] Guid itemId,
diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
index cfbabf7954..6e91042dfd 100644
--- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
@@ -198,8 +198,15 @@ namespace Jellyfin.Server.Extensions
$"{description.ActionDescriptor.RouteValues["controller"]}_{description.RelativePath}");
// Use method name as operationId
- c.CustomOperationIds(description =>
- description.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null);
+ c.CustomOperationIds(
+ description =>
+ {
+ description.TryGetMethodInfo(out MethodInfo methodInfo);
+ // Attribute name, method name, none.
+ return description?.ActionDescriptor?.AttributeRouteInfo?.Name
+ ?? methodInfo?.Name
+ ?? null;
+ });
// TODO - remove when all types are supported in System.Text.Json
c.AddSwaggerTypeMappings();
diff --git a/tests/Jellyfin.Api.Tests/GetPathValueTests.cs b/tests/Jellyfin.Api.Tests/GetPathValueTests.cs
deleted file mode 100644
index 397eb2edc3..0000000000
--- a/tests/Jellyfin.Api.Tests/GetPathValueTests.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using MediaBrowser.Api;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging.Abstractions;
-using Moq;
-using Xunit;
-
-namespace Jellyfin.Api.Tests
-{
- public class GetPathValueTests
- {
- [Theory]
- [InlineData("https://localhost:8096/ScheduledTasks/1234/Triggers", "", 1, "1234")]
- [InlineData("https://localhost:8096/emby/ScheduledTasks/1234/Triggers", "", 1, "1234")]
- [InlineData("https://localhost:8096/mediabrowser/ScheduledTasks/1234/Triggers", "", 1, "1234")]
- [InlineData("https://localhost:8096/jellyfin/2/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")]
- [InlineData("https://localhost:8096/jellyfin/2/emby/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")]
- [InlineData("https://localhost:8096/jellyfin/2/mediabrowser/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")]
- [InlineData("https://localhost:8096/JELLYFIN/2/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")]
- [InlineData("https://localhost:8096/JELLYFIN/2/Emby/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")]
- [InlineData("https://localhost:8096/JELLYFIN/2/MediaBrowser/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")]
- public void GetPathValueTest(string path, string baseUrl, int index, string value)
- {
- var reqMock = Mock.Of(x => x.PathInfo == path);
- var conf = new ServerConfiguration()
- {
- BaseUrl = baseUrl
- };
-
- var confManagerMock = Mock.Of(x => x.Configuration == conf);
-
- var service = new TestService(
- new NullLogger(),
- confManagerMock,
- Mock.Of())
- {
- Request = reqMock
- };
-
- Assert.Equal(value, service.GetPathValue(index).ToString());
- }
- }
-}