TypedResults for API v5 endpoints

This commit is contained in:
Bogdan 2026-04-13 11:10:34 +03:00 committed by Mark McDowall
parent 92334b3fb9
commit f4a160cb29
61 changed files with 447 additions and 317 deletions

View file

@ -108,6 +108,11 @@ public void ConfigureServices(IServiceCollection services)
})
.AddControllersAsServices();
services.ConfigureHttpJsonOptions(options =>
{
STJson.ApplySerializerSettings(options.SerializerOptions);
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v3", new OpenApiInfo

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.HealthCheck;
@ -23,7 +24,7 @@ public HealthController(IBroadcastSignalRMessage signalRBroadcaster, IHealthChec
}
[NonAction]
public override ActionResult<HealthResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<HealthResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.DecisionEngine;
using NzbDrone.Core.Profiles.Qualities;
@ -17,7 +18,7 @@ public ReleaseControllerBase(IQualityProfileService qualityProfileService)
}
[NonAction]
public override ActionResult<ReleaseResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<ReleaseResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Languages;
using Sonarr.Http;
@ -33,7 +34,7 @@ public LanguageProfileResource GetSchema()
}
[NonAction]
public override ActionResult<LanguageProfileResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<LanguageProfileResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Blocklisting;
@ -61,7 +62,7 @@ public QueueController(IBroadcastSignalRMessage broadcastSignalRMessage,
}
[NonAction]
public override ActionResult<QueueResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<QueueResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Download.Pending;
@ -28,7 +29,7 @@ public QueueDetailsController(IBroadcastSignalRMessage broadcastSignalRMessage,
}
[NonAction]
public override ActionResult<QueueResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<QueueResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,5 +1,6 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.TPL;
using NzbDrone.Core.Datastore.Events;
@ -31,7 +32,7 @@ public QueueStatusController(IBroadcastSignalRMessage broadcastSignalRMessage, I
}
[NonAction]
public override ActionResult<QueueStatusResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<QueueStatusResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using FluentValidation;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.DataAugmentation.Scene;
@ -130,7 +131,7 @@ public List<SeriesResource> AllSeries(int? tvdbId, bool includeSeasonImages = fa
}
[NonAction]
public override ActionResult<SeriesResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<SeriesResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Blocklisting;
using NzbDrone.Core.CustomFormats;
@ -24,7 +26,7 @@ public BlocklistController(IBlocklistService blocklistService,
[HttpGet]
[Produces("application/json")]
public PagingResource<BlocklistResource> GetBlocklist([FromQuery] PagingRequestResource paging, [FromQuery] int[]? seriesIds = null, [FromQuery] DownloadProtocol[]? protocols = null)
public Ok<PagingResource<BlocklistResource>> GetBlocklist([FromQuery] PagingRequestResource paging, [FromQuery] int[]? seriesIds = null, [FromQuery] DownloadProtocol[]? protocols = null)
{
var pagingResource = new PagingResource<BlocklistResource>(paging);
var pagingSpec = pagingResource.MapToPagingSpec<BlocklistResource, NzbDrone.Core.Blocklisting.Blocklist>(
@ -48,23 +50,23 @@ public PagingResource<BlocklistResource> GetBlocklist([FromQuery] PagingRequestR
pagingSpec.FilterExpressions.Add(b => protocols.Contains(b.Protocol));
}
return pagingSpec.ApplyToPage(b => _blocklistService.Paged(pagingSpec), b => BlocklistResourceMapper.MapToResource(b, _formatCalculator));
return TypedResults.Ok(pagingSpec.ApplyToPage(b => _blocklistService.Paged(pagingSpec), b => BlocklistResourceMapper.MapToResource(b, _formatCalculator)));
}
[RestDeleteById]
public ActionResult DeleteBlocklist(int id)
public NoContent DeleteBlocklist(int id)
{
_blocklistService.Delete(id);
return NoContent();
return TypedResults.NoContent();
}
[HttpDelete("bulk")]
[Produces("application/json")]
public ActionResult Remove([FromBody] BlocklistBulkResource resource)
public NoContent Remove([FromBody] BlocklistBulkResource resource)
{
_blocklistService.Delete(resource.Ids);
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.CustomFormats;
@ -28,7 +30,7 @@ public CalendarController(IBroadcastSignalRMessage signalR,
[HttpGet]
[Produces("application/json")]
public List<EpisodeResource> GetCalendar(DateTime? start, DateTime? end, bool includeUnmonitored = false, bool includeSpecials = true, string tags = "", [FromQuery] CalendarSubresource[]? includeSubresources = null)
public Ok<List<EpisodeResource>> GetCalendar(DateTime? start, DateTime? end, bool includeUnmonitored = false, bool includeSpecials = true, string tags = "", [FromQuery] CalendarSubresource[]? includeSubresources = null)
{
var startUse = start ?? DateTime.Today;
var endUse = end ?? DateTime.Today.AddDays(2);
@ -65,7 +67,7 @@ public List<EpisodeResource> GetCalendar(DateTime? start, DateTime? end, bool in
var resources = MapToResource(result, includeSeries, includeEpisodeFile, includeEpisodeImages);
return resources.OrderBy(e => e.AirDateUtc).ToList();
return TypedResults.Ok(resources.OrderBy(e => e.AirDateUtc).ToList());
}
}
}

View file

@ -2,6 +2,8 @@
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
using Ical.Net.Serialization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Tags;
@ -25,7 +27,7 @@ public CalendarFeedController(IEpisodeService episodeService, ISeriesService ser
}
[HttpGet("Sonarr.ics")]
public IActionResult GetCalendarFeed(int pastDays = 7, int futureDays = 28, string tags = "", bool unmonitored = false, bool premieresOnly = false, bool asAllDay = false, bool includeSpecials = true)
public ContentHttpResult GetCalendarFeed(int pastDays = 7, int futureDays = 28, string tags = "", bool unmonitored = false, bool premieresOnly = false, bool asAllDay = false, bool includeSpecials = true)
{
var start = DateTime.Today.AddDays(-pastDays);
var end = DateTime.Today.AddDays(futureDays);
@ -96,6 +98,6 @@ public IActionResult GetCalendarFeed(int pastDays = 7, int futureDays = 28, stri
var serializer = (IStringSerializer)new SerializerFactory().Build(calendar.GetType(), new SerializationContext());
var icalendar = serializer.SerializeToString(calendar);
return Content(icalendar, "text/calendar");
return TypedResults.Content(icalendar, "text/calendar");
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Composition;
using NzbDrone.Common.Serializer;
@ -46,7 +48,7 @@ protected override CommandResource GetResourceById(int id)
[RestPostById]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<CommandResource> StartCommand([FromBody] CommandResource commandResource)
public Results<Created<CommandResource>, NotFound> StartCommand([FromBody] CommandResource commandResource)
{
var commandType =
_knownTypes.GetImplementations(typeof(Command))
@ -70,24 +72,26 @@ public ActionResult<CommandResource> StartCommand([FromBody] CommandResource com
var trackedCommand = _commandQueueManager.Push(command, commandResource.Priority, CommandTrigger.Manual);
return Created(trackedCommand.Id);
return TypedCreated(trackedCommand.Id);
}
}
[HttpGet]
[Produces("application/json")]
public List<CommandResource> GetStartedCommands()
public Ok<List<CommandResource>> GetStartedCommands()
{
return _commandQueueManager.All()
return TypedResults.Ok(_commandQueueManager.All()
.OrderBy(c => c.Status, _commandPriorityComparer)
.ThenByDescending(c => c.Priority)
.ToResource();
.ToResource());
}
[RestDeleteById]
public void CancelCommand(int id)
public NoContent CancelCommand(int id)
{
_commandQueueManager.Cancel(id);
return TypedResults.NoContent();
}
[NonAction]

View file

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Notifications;
using NzbDrone.SignalR;
@ -18,13 +19,13 @@ public ConnectionController(IBroadcastSignalRMessage signalRBroadcaster, Notific
}
[NonAction]
public override ActionResult<ConnectionResource> UpdateProvider([FromBody] ConnectionBulkResource providerResource)
public override Results<Ok<IEnumerable<ConnectionResource>>, BadRequest> UpdateProvider([FromBody] ConnectionBulkResource providerResource)
{
throw new NotImplementedException();
}
[NonAction]
public override ActionResult DeleteProviders([FromBody] ConnectionBulkResource resource)
public override NoContent DeleteProviders([FromBody] ConnectionBulkResource resource)
{
throw new NotImplementedException();
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFilters;
using Sonarr.Http;
@ -23,33 +25,33 @@ protected override CustomFilterResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<CustomFilterResource> GetCustomFilters()
public Ok<List<CustomFilterResource>> GetCustomFilters()
{
return _customFilterService.All().ToResource();
return TypedResults.Ok(_customFilterService.All().ToResource());
}
[RestPostById]
[Consumes("application/json")]
public ActionResult<CustomFilterResource> AddCustomFilter([FromBody] CustomFilterResource resource)
public Results<Created<CustomFilterResource>, NotFound> AddCustomFilter([FromBody] CustomFilterResource resource)
{
var customFilter = _customFilterService.Add(resource.ToModel());
return Created(customFilter.Id);
return TypedCreated(customFilter.Id);
}
[RestPutById]
[Consumes("application/json")]
public ActionResult<CustomFilterResource> UpdateCustomFilter([FromBody] CustomFilterResource resource)
public Results<Accepted<CustomFilterResource>, NotFound> UpdateCustomFilter([FromBody] CustomFilterResource resource)
{
_customFilterService.Update(resource.ToModel());
return Accepted(resource.Id);
return TypedAccepted(resource.Id);
}
[RestDeleteById]
public ActionResult DeleteCustomResource(int id)
public NoContent DeleteCustomResource(int id)
{
_customFilterService.Delete(id);
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.DiskSpace;
using Sonarr.Http;
@ -16,8 +18,8 @@ public DiskSpaceController(IDiskSpaceService diskSpaceService)
[HttpGet]
[Produces("application/json")]
public List<DiskSpaceResource> GetFreeSpace()
public Ok<List<DiskSpaceResource>> GetFreeSpace()
{
return _diskSpaceService.GetFreeSpace().ConvertAll(DiskSpaceResourceMapper.MapToResource);
return TypedResults.Ok(_diskSpaceService.GetFreeSpace().ConvertAll(DiskSpaceResourceMapper.MapToResource));
}
}

View file

@ -1,4 +1,6 @@
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore.Events;
@ -57,7 +59,7 @@ protected override EpisodeFileResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<EpisodeFileResource> GetEpisodeFiles(int? seriesId, [FromQuery] List<int>? episodeFileIds)
public Results<Ok<List<EpisodeFileResource>>, BadRequest> GetEpisodeFiles(int? seriesId, [FromQuery] List<int>? episodeFileIds)
{
if (!seriesId.HasValue && episodeFileIds?.Any() == false)
{
@ -71,25 +73,25 @@ public List<EpisodeFileResource> GetEpisodeFiles(int? seriesId, [FromQuery] List
if (files == null)
{
return new List<EpisodeFileResource>();
return TypedResults.Ok(new List<EpisodeFileResource>());
}
return files.ConvertAll(e => e.ToResource(series, _upgradableSpecification, _formatCalculator));
return TypedResults.Ok(files.ConvertAll(e => e.ToResource(series, _upgradableSpecification, _formatCalculator)));
}
else
{
var episodeFiles = _mediaFileService.Get(episodeFileIds);
return episodeFiles.GroupBy(e => e.SeriesId)
return TypedResults.Ok(episodeFiles.GroupBy(e => e.SeriesId)
.SelectMany(f => f.ToList()
.ConvertAll(e => e.ToResource(_seriesService.GetSeries(f.Key), _upgradableSpecification, _formatCalculator)))
.ToList();
.ToList());
}
}
[RestPutById]
[Consumes("application/json")]
public ActionResult<EpisodeFileResource> SetQuality([FromBody] EpisodeFileResource episodeFileResource)
public Results<Accepted<EpisodeFileResource>, NotFound> SetQuality([FromBody] EpisodeFileResource episodeFileResource)
{
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
episodeFile.Quality = episodeFileResource.Quality;
@ -105,11 +107,11 @@ public ActionResult<EpisodeFileResource> SetQuality([FromBody] EpisodeFileResour
}
_mediaFileService.Update(episodeFile);
return Accepted(episodeFile.Id);
return TypedAccepted(episodeFile.Id);
}
[RestDeleteById]
public void DeleteEpisodeFile(int id)
public Results<NoContent, NotFound> DeleteEpisodeFile(int id)
{
var episodeFile = _mediaFileService.Get(id);
@ -121,11 +123,13 @@ public void DeleteEpisodeFile(int id)
var series = _seriesService.GetSeries(episodeFile.SeriesId);
_mediaFileDeletionService.DeleteEpisodeFile(series, episodeFile);
return TypedResults.NoContent();
}
[HttpDelete("bulk")]
[Consumes("application/json")]
public object DeleteEpisodeFiles([FromBody] EpisodeFileListResource resource)
public NoContent DeleteEpisodeFiles([FromBody] EpisodeFileListResource resource)
{
var episodeFiles = _mediaFileService.GetFiles(resource.EpisodeFileIds);
var series = _seriesService.GetSeries(episodeFiles.First().SeriesId);
@ -135,12 +139,12 @@ public object DeleteEpisodeFiles([FromBody] EpisodeFileListResource resource)
_mediaFileDeletionService.DeleteEpisodeFile(series, episodeFile);
}
return NoContent();
return TypedResults.NoContent();
}
[HttpPut("bulk")]
[Consumes("application/json")]
public object SetPropertiesBulk([FromBody] List<EpisodeFileResource> resources)
public Ok<List<EpisodeFileResource>> SetPropertiesBulk([FromBody] List<EpisodeFileResource> resources)
{
var episodeFiles = _mediaFileService.GetFiles(resources.Select(r => r.Id));
@ -184,7 +188,7 @@ public object SetPropertiesBulk([FromBody] List<EpisodeFileResource> resources)
var series = _seriesService.GetSeries(episodeFiles.First().SeriesId);
return Accepted(episodeFiles.ConvertAll(f => f.ToResource(series, _upgradableSpecification, _formatCalculator)));
return TypedResults.Ok(episodeFiles.ConvertAll(f => f.ToResource(series, _upgradableSpecification, _formatCalculator)));
}
[NonAction]

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine.Specifications;
@ -23,7 +25,7 @@ public EpisodeController(ISeriesService seriesService,
[HttpGet]
[Produces("application/json")]
public List<EpisodeResource> GetEpisodes(int? seriesId, int? seasonNumber, [FromQuery]List<int> episodeIds, int? episodeFileId, [FromQuery] EpisodeSubresource[]? includeSubresources = null)
public Results<Ok<List<EpisodeResource>>, BadRequest> GetEpisodes(int? seriesId, int? seasonNumber, [FromQuery]List<int> episodeIds, int? episodeFileId, [FromQuery] EpisodeSubresource[]? includeSubresources = null)
{
var includeSeries = includeSubresources.Contains(EpisodeSubresource.Series);
var includeEpisodeFile = includeSubresources.Contains(EpisodeSubresource.EpisodeFile);
@ -33,18 +35,18 @@ public List<EpisodeResource> GetEpisodes(int? seriesId, int? seasonNumber, [From
{
if (seasonNumber.HasValue)
{
return MapToResource(_episodeService.GetEpisodesBySeason(seriesId.Value, seasonNumber.Value), includeSeries, includeEpisodeFile, includeImages);
return TypedResults.Ok(MapToResource(_episodeService.GetEpisodesBySeason(seriesId.Value, seasonNumber.Value), includeSeries, includeEpisodeFile, includeImages));
}
return MapToResource(_episodeService.GetEpisodeBySeries(seriesId.Value), includeSeries, includeEpisodeFile, includeImages);
return TypedResults.Ok(MapToResource(_episodeService.GetEpisodeBySeries(seriesId.Value), includeSeries, includeEpisodeFile, includeImages));
}
else if (episodeIds.Any())
{
return MapToResource(_episodeService.GetEpisodes(episodeIds), includeSeries, includeEpisodeFile, includeImages);
return TypedResults.Ok(MapToResource(_episodeService.GetEpisodes(episodeIds), includeSeries, includeEpisodeFile, includeImages));
}
else if (episodeFileId.HasValue)
{
return MapToResource(_episodeService.GetEpisodesByFileId(episodeFileId.Value), includeSeries, includeEpisodeFile, includeImages);
return TypedResults.Ok(MapToResource(_episodeService.GetEpisodesByFileId(episodeFileId.Value), includeSeries, includeEpisodeFile, includeImages));
}
throw new BadRequestException("seriesId or episodeIds must be provided");
@ -52,18 +54,18 @@ public List<EpisodeResource> GetEpisodes(int? seriesId, int? seasonNumber, [From
[RestPutById]
[Consumes("application/json")]
public ActionResult<EpisodeResource> SetEpisodeMonitored([FromRoute] int id, [FromBody] EpisodeResource resource)
public Ok<EpisodeResource> SetEpisodeMonitored([FromRoute] int id, [FromBody] EpisodeResource resource)
{
_episodeService.SetEpisodeMonitored(id, resource.Monitored);
resource = MapToResource(_episodeService.GetEpisode(id), false, false, false);
return Accepted(resource);
return TypedResults.Ok(resource);
}
[HttpPut("monitor")]
[Consumes("application/json")]
public IActionResult SetEpisodesMonitored([FromBody] EpisodesMonitoredResource resource, [FromQuery] EpisodeSubresource[]? includeSubresources = null)
public Ok<List<EpisodeResource>> SetEpisodesMonitored([FromBody] EpisodesMonitoredResource resource, [FromQuery] EpisodeSubresource[]? includeSubresources = null)
{
var includeImages = includeSubresources.Contains(EpisodeSubresource.Images);
@ -78,6 +80,6 @@ public IActionResult SetEpisodesMonitored([FromBody] EpisodesMonitoredResource r
var resources = MapToResource(_episodeService.GetEpisodes(resource.EpisodeIds), false, false, includeImages);
return Accepted(resources);
return TypedResults.Ok(resources);
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.MediaFiles;
using Sonarr.Http;
@ -17,19 +19,19 @@ public RenameEpisodeController(IRenameEpisodeFileService renameEpisodeFileServic
[HttpGet]
[Produces("application/json")]
public List<RenameEpisodeResource> GetEpisodes(int seriesId, int? seasonNumber)
public Ok<List<RenameEpisodeResource>> GetEpisodes(int seriesId, int? seasonNumber)
{
if (seasonNumber.HasValue)
{
return _renameEpisodeFileService.GetRenamePreviews(seriesId, seasonNumber.Value).ToResource();
return TypedResults.Ok(_renameEpisodeFileService.GetRenamePreviews(seriesId, seasonNumber.Value).ToResource());
}
return _renameEpisodeFileService.GetRenamePreviews(seriesId).ToResource();
return TypedResults.Ok(_renameEpisodeFileService.GetRenamePreviews(seriesId).ToResource());
}
[HttpGet("bulk")]
[Produces("application/json")]
public List<RenameEpisodeResource> GetEpisodes([FromQuery] List<int> seriesIds)
public Results<Ok<List<RenameEpisodeResource>>, BadRequest> GetEpisodes([FromQuery] List<int> seriesIds)
{
if (seriesIds is { Count: 0 })
{
@ -41,6 +43,6 @@ public List<RenameEpisodeResource> GetEpisodes([FromQuery] List<int> seriesIds)
throw new BadRequestException("seriesIds must be positive integers");
}
return _renameEpisodeFileService.GetRenamePreviews(seriesIds).ToResource();
return TypedResults.Ok(_renameEpisodeFileService.GetRenamePreviews(seriesIds).ToResource());
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
@ -24,38 +26,38 @@ public FileSystemController(IFileSystemLookupService fileSystemLookupService,
[HttpGet]
[Produces("application/json")]
public IActionResult GetContents(string? path, bool includeFiles = false, bool allowFoldersWithoutTrailingSlashes = false)
public Ok<FileSystemResult> GetContents(string? path, bool includeFiles = false, bool allowFoldersWithoutTrailingSlashes = false)
{
return Ok(_fileSystemLookupService.LookupContents(path, includeFiles, allowFoldersWithoutTrailingSlashes));
return TypedResults.Ok(_fileSystemLookupService.LookupContents(path, includeFiles, allowFoldersWithoutTrailingSlashes));
}
[HttpGet("type")]
[Produces("application/json")]
public object GetEntityType(string path)
public Ok<object> GetEntityType(string path)
{
if (_diskProvider.FileExists(path))
{
return new { type = "file" };
return TypedResults.Ok((object)new { type = "file" });
}
// Return folder even if it doesn't exist on disk to avoid leaking anything from the UI about the underlying system
return new { type = "folder" };
return TypedResults.Ok((object)new { type = "folder" });
}
[HttpGet("mediafiles")]
[Produces("application/json")]
public object GetMediaFiles(string path)
public Ok<IEnumerable<object>> GetMediaFiles(string path)
{
if (!_diskProvider.FolderExists(path))
{
return Array.Empty<string>();
return TypedResults.Ok(Enumerable.Empty<object>());
}
return _diskScanService.GetVideoFiles(path).Select(f => new
return TypedResults.Ok(_diskScanService.GetVideoFiles(path).Select(object (f) => new
{
Path = f,
RelativePath = path.GetRelativePath(f),
Name = Path.GetFileName(f)
});
}));
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.HealthCheck;
@ -21,7 +23,7 @@ public HealthController(IBroadcastSignalRMessage signalRBroadcaster, IHealthChec
}
[NonAction]
public override ActionResult<HealthResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<HealthResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}
@ -33,9 +35,9 @@ protected override HealthResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<HealthResource> GetHealth()
public Ok<List<HealthResource>> GetHealth()
{
return _healthCheckService.Results().ToResource();
return TypedResults.Ok(_healthCheckService.Results().ToResource());
}
[NonAction]

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.CustomFormats;
@ -62,7 +64,7 @@ protected HistoryResource MapToResource(EpisodeHistory model, bool includeSeries
[HttpGet]
[Produces("application/json")]
public PagingResource<HistoryResource> GetHistory([FromQuery] PagingRequestResource paging, [FromQuery(Name = "eventType")] int[]? eventTypes, int? episodeId, string? downloadId, [FromQuery] int[]? seriesIds = null, [FromQuery] int[]? languages = null, [FromQuery] int[]? quality = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
public Ok<PagingResource<HistoryResource>> GetHistory([FromQuery] PagingRequestResource paging, [FromQuery(Name = "eventType")] int[]? eventTypes, int? episodeId, string? downloadId, [FromQuery] int[]? seriesIds = null, [FromQuery] int[]? languages = null, [FromQuery] int[]? quality = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
{
var pagingResource = new PagingResource<HistoryResource>(paging);
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, EpisodeHistory>(
@ -97,74 +99,74 @@ public PagingResource<HistoryResource> GetHistory([FromQuery] PagingRequestResou
var includeSeries = includeSubresources.Contains(HistorySubresource.Series);
var includeEpisode = includeSubresources.Contains(HistorySubresource.Episode);
return pagingSpec.ApplyToPage(h => _historyService.Paged(pagingSpec, languages, quality), h => MapToResource(h, includeSeries, includeEpisode));
return TypedResults.Ok(pagingSpec.ApplyToPage(h => _historyService.Paged(pagingSpec, languages, quality), h => MapToResource(h, includeSeries, includeEpisode)));
}
[HttpGet("since")]
[Produces("application/json")]
public List<HistoryResource> GetHistorySince(DateTime date, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
public Ok<List<HistoryResource>> GetHistorySince(DateTime date, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
{
var includeSeries = includeSubresources.Contains(HistorySubresource.Series);
var includeEpisode = includeSubresources.Contains(HistorySubresource.Episode);
return _historyService.Since(date, eventType).Select(h => MapToResource(h, includeSeries, includeEpisode)).ToList();
return TypedResults.Ok(_historyService.Since(date, eventType).Select(h => MapToResource(h, includeSeries, includeEpisode)).ToList());
}
[HttpGet("series")]
[Produces("application/json")]
public List<HistoryResource> GetSeriesHistory(int seriesId, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
public Ok<List<HistoryResource>> GetSeriesHistory(int seriesId, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
{
var series = _seriesService.GetSeries(seriesId);
var includeSeries = includeSubresources.Contains(HistorySubresource.Series);
var includeEpisode = includeSubresources.Contains(HistorySubresource.Episode);
return _historyService.GetBySeries(seriesId, eventType).Select(h =>
return TypedResults.Ok(_historyService.GetBySeries(seriesId, eventType).Select(h =>
{
h.Series = series;
return MapToResource(h, includeSeries, includeEpisode);
}).ToList();
}).ToList());
}
[HttpGet("season")]
[Produces("application/json")]
public List<HistoryResource> GetSeasonHistory(int seriesId, int seasonNumber, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
public Ok<List<HistoryResource>> GetSeasonHistory(int seriesId, int seasonNumber, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
{
var series = _seriesService.GetSeries(seriesId);
var includeSeries = includeSubresources.Contains(HistorySubresource.Series);
var includeEpisode = includeSubresources.Contains(HistorySubresource.Episode);
return _historyService.GetBySeason(seriesId, seasonNumber, eventType).Select(h =>
return TypedResults.Ok(_historyService.GetBySeason(seriesId, seasonNumber, eventType).Select(h =>
{
h.Series = series;
return MapToResource(h, includeSeries, includeEpisode);
}).ToList();
}).ToList());
}
[HttpGet("episode")]
[Produces("application/json")]
public List<HistoryResource> GetEpisodeHistory(int episodeId, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
public Ok<List<HistoryResource>> GetEpisodeHistory(int episodeId, EpisodeHistoryEventType? eventType = null, [FromQuery] HistorySubresource[]? includeSubresources = null)
{
var episode = _episodeService.GetEpisode(episodeId);
var series = _seriesService.GetSeries(episode.SeriesId);
var includeSeries = includeSubresources.Contains(HistorySubresource.Series);
var includeEpisode = includeSubresources.Contains(HistorySubresource.Episode);
return _historyService.GetByEpisode(episodeId, eventType)
return TypedResults.Ok(_historyService.GetByEpisode(episodeId, eventType)
.Select(h =>
{
h.Series = series;
h.Episode = episode;
return MapToResource(h, includeSeries, includeEpisode);
}).ToList();
}).ToList());
}
[HttpPost("failed/{id}")]
public ActionResult MarkAsFailed([FromRoute] int id)
public NoContent MarkAsFailed([FromRoute] int id)
{
_failedDownloadService.MarkAsFailed(id);
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.ImportLists.Exclusions;
@ -33,7 +35,7 @@ protected override ImportListExclusionResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public PagingResource<ImportListExclusionResource> GetImportListExclusions([FromQuery] PagingRequestResource paging)
public Ok<PagingResource<ImportListExclusionResource>> GetImportListExclusions([FromQuery] PagingRequestResource paging)
{
var pagingResource = new PagingResource<ImportListExclusionResource>(paging);
var pageSpec = pagingResource.MapToPagingSpec<ImportListExclusionResource, ImportListExclusion>(
@ -46,41 +48,41 @@ public PagingResource<ImportListExclusionResource> GetImportListExclusions([From
"id",
SortDirection.Descending);
return pageSpec.ApplyToPage(_importListExclusionService.Paged, ImportListExclusionResourceMapper.ToResource);
return TypedResults.Ok(pageSpec.ApplyToPage(_importListExclusionService.Paged, ImportListExclusionResourceMapper.ToResource));
}
[RestPostById]
[Consumes("application/json")]
public ActionResult<ImportListExclusionResource> AddImportListExclusion([FromBody] ImportListExclusionResource resource)
public Results<Created<ImportListExclusionResource>, NotFound> AddImportListExclusion([FromBody] ImportListExclusionResource resource)
{
var importListExclusion = _importListExclusionService.Add(resource.ToModel());
return Created(importListExclusion.Id);
return TypedCreated(importListExclusion.Id);
}
[RestPutById]
[Consumes("application/json")]
public ActionResult<ImportListExclusionResource> UpdateImportListExclusion([FromBody] ImportListExclusionResource resource)
public Results<Accepted<ImportListExclusionResource>, NotFound> UpdateImportListExclusion([FromBody] ImportListExclusionResource resource)
{
_importListExclusionService.Update(resource.ToModel());
return Accepted(resource.Id);
return TypedAccepted(resource.Id);
}
[RestDeleteById]
public ActionResult DeleteImportListExclusion(int id)
public NoContent DeleteImportListExclusion(int id)
{
_importListExclusionService.Delete(id);
return NoContent();
return TypedResults.NoContent();
}
[HttpDelete("bulk")]
[Consumes("application/json")]
public ActionResult DeleteImportListExclusions([FromBody] ImportListExclusionBulkResource resource)
public NoContent DeleteImportListExclusions([FromBody] ImportListExclusionBulkResource resource)
{
_importListExclusionService.Delete(resource.Ids.ToList());
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Parser.Model;
using Sonarr.Http;
@ -8,12 +10,12 @@ namespace Sonarr.Api.V5.Indexers;
public class IndexerFlagController : Controller
{
[HttpGet]
public List<IndexerFlagResource> GetAll()
public Ok<List<IndexerFlagResource>> GetAll()
{
return Enum.GetValues(typeof(IndexerFlags)).Cast<IndexerFlags>().Select(f => new IndexerFlagResource
return TypedResults.Ok(Enum.GetValues(typeof(IndexerFlags)).Cast<IndexerFlags>().Select(f => new IndexerFlagResource
{
Id = (int)f,
Name = f.ToString()
}).ToList();
}).ToList());
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Languages;
using Sonarr.Http;
@ -20,7 +22,7 @@ protected override LanguageResource GetResourceById(int id)
}
[HttpGet]
public List<LanguageResource> GetAll()
public Ok<List<LanguageResource>> GetAll()
{
var languageResources = Language.All.Select(l => new LanguageResource
{
@ -30,6 +32,6 @@ public List<LanguageResource> GetAll()
.OrderBy(l => l.Id > 0).ThenBy(l => l.Name)
.ToList();
return languageResources;
return TypedResults.Ok(languageResources);
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Localization;
using Sonarr.Http;
@ -17,25 +19,25 @@ public LocalizationController(ILocalizationService localizationService)
protected override LocalizationResource GetResourceById(int id)
{
return GetLocalization();
return _localizationService.GetLocalizationDictionary().ToResource();
}
[HttpGet]
[Produces("application/json")]
public LocalizationResource GetLocalization()
public Ok<LocalizationResource> GetLocalization()
{
return _localizationService.GetLocalizationDictionary().ToResource();
return TypedResults.Ok(GetResourceById(1));
}
[HttpGet("language")]
[Produces("application/json")]
public LocalizationLanguageResource GetLanguage()
public Ok<LocalizationLanguageResource> GetLanguage()
{
var identifier = _localizationService.GetLanguageIdentifier();
return new LocalizationLanguageResource
return TypedResults.Ok(new LocalizationLanguageResource
{
Identifier = identifier
};
});
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
@ -21,11 +23,11 @@ public LogController(ILogService logService, IConfigFileProvider configFileProvi
[HttpGet]
[Produces("application/json")]
public PagingResource<LogResource> GetLogs([FromQuery] PagingRequestResource paging, string? level)
public Ok<PagingResource<LogResource>> GetLogs([FromQuery] PagingRequestResource paging, string? level)
{
if (!_configFileProvider.LogDbEnabled)
{
return new PagingResource<LogResource>();
return TypedResults.Ok(new PagingResource<LogResource>());
}
var pagingResource = new PagingResource<LogResource>(paging);
@ -72,7 +74,7 @@ public PagingResource<LogResource> GetLogs([FromQuery] PagingRequestResource pag
response.SortKey = "time";
}
return response;
return TypedResults.Ok(response);
}
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NLog;
using NzbDrone.Common.Disk;
@ -24,7 +26,7 @@ public LogFileControllerBase(IDiskProvider diskProvider,
[HttpGet]
[Produces("application/json")]
public List<LogFileResource> GetLogFilesResponse()
public Ok<List<LogFileResource>> GetLogFilesResponse()
{
var result = new List<LogFileResource>();
@ -45,12 +47,12 @@ public List<LogFileResource> GetLogFilesResponse()
});
}
return result.OrderByDescending(l => l.LastWriteTime).ToList();
return TypedResults.Ok(result.OrderByDescending(l => l.LastWriteTime).ToList());
}
[HttpGet(@"{filename:regex([[-.a-zA-Z0-9]]+?\.txt)}")]
[Produces("text/plain")]
public IActionResult GetLogFileResponse(string filename)
public Results<PhysicalFileHttpResult, NotFound> GetLogFileResponse(string filename)
{
LogManager.Flush();
@ -58,10 +60,10 @@ public IActionResult GetLogFileResponse(string filename)
if (!_diskProvider.FileExists(filePath))
{
return NotFound();
return TypedResults.NotFound();
}
return PhysicalFile(filePath, "text/plain");
return TypedResults.PhysicalFile(filePath, "text/plain");
}
protected abstract IEnumerable<string> GetLogFiles();

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Languages;
@ -20,14 +22,14 @@ public ManualImportController(IManualImportService manualImportService)
[HttpGet]
[Produces("application/json")]
public List<ManualImportResource> GetMediaFiles(string? folder, [FromQuery] string[]? downloadIds, int? seriesId, int? seasonNumber, bool filterExistingFiles = true)
public Ok<List<ManualImportResource>> GetMediaFiles(string? folder, [FromQuery] string[]? downloadIds, int? seriesId, int? seasonNumber, bool filterExistingFiles = true)
{
if (seriesId.HasValue && downloadIds == null)
{
return _manualImportService.GetMediaFiles(seriesId.Value, seasonNumber)
return TypedResults.Ok(_manualImportService.GetMediaFiles(seriesId.Value, seasonNumber)
.ToResource()
.Select(AddQualityWeight)
.ToList();
.ToList());
}
if (downloadIds != null && downloadIds.Any())
@ -39,20 +41,20 @@ public List<ManualImportResource> GetMediaFiles(string? folder, [FromQuery] stri
files.AddRange(_manualImportService.GetMediaFiles(null, downloadId, seriesId, filterExistingFiles));
}
return files.ToResource()
return TypedResults.Ok(files.ToResource()
.Select(AddQualityWeight)
.ToList();
.ToList());
}
return _manualImportService.GetMediaFiles(folder, null, seriesId, filterExistingFiles)
return TypedResults.Ok(_manualImportService.GetMediaFiles(folder, null, seriesId, filterExistingFiles)
.ToResource()
.Select(AddQualityWeight)
.ToList();
.ToList());
}
[HttpPost]
[Consumes("application/json")]
public List<ManualImportResource> ReprocessItems([FromBody] List<ManualImportReprocessResource> items)
public Results<Ok<List<ManualImportResource>>, BadRequest> ReprocessItems([FromBody] List<ManualImportReprocessResource> items)
{
if (items is { Count: 0 })
{
@ -95,7 +97,7 @@ public List<ManualImportResource> ReprocessItems([FromBody] List<ManualImportRep
updatedItems.Add(processedItem);
}
return updatedItems.ToResource();
return TypedResults.Ok(updatedItems.ToResource());
}
private ManualImportResource AddQualityWeight(ManualImportResource item)

View file

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Extras.Metadata;
using NzbDrone.SignalR;
@ -18,13 +19,13 @@ public MetadataController(IBroadcastSignalRMessage signalRBroadcaster, IMetadata
}
[NonAction]
public override ActionResult<MetadataResource> UpdateProvider([FromBody] MetadataBulkResource providerResource)
public override Results<Ok<IEnumerable<MetadataResource>>, BadRequest> UpdateProvider([FromBody] MetadataBulkResource providerResource)
{
throw new NotImplementedException();
}
[NonAction]
public override ActionResult DeleteProviders([FromBody] MetadataBulkResource resource)
public override NoContent DeleteProviders([FromBody] MetadataBulkResource resource)
{
throw new NotImplementedException();
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.CustomFormats;
@ -28,24 +30,24 @@ public ParseController(IParsingService parsingService,
[HttpGet]
[Produces("application/json")]
public ParseResource Parse(string? title, string? path)
public Ok<ParseResource> Parse(string? title, string? path)
{
if (title.IsNullOrWhiteSpace())
{
return new ParseResource
return TypedResults.Ok(new ParseResource
{
Title = title
};
});
}
var parsedEpisodeInfo = path.IsNotNullOrWhiteSpace() ? Parser.ParsePath(path) : Parser.ParseTitle(title);
if (parsedEpisodeInfo == null)
{
return new ParseResource
return TypedResults.Ok(new ParseResource
{
Title = title
};
});
}
var remoteEpisode = _parsingService.Map(parsedEpisodeInfo, 0, 0, null);
@ -57,7 +59,7 @@ public ParseResource Parse(string? title, string? path)
remoteEpisode.CustomFormats = _formatCalculator.ParseCustomFormat(remoteEpisode, 0);
remoteEpisode.CustomFormatScore = remoteEpisode.Series?.QualityProfile?.Value.CalculateCustomFormatScore(remoteEpisode.CustomFormats) ?? 0;
return new ParseResource
return TypedResults.Ok(new ParseResource
{
Title = title,
ParsedEpisodeInfo = remoteEpisode.ParsedEpisodeInfo,
@ -66,15 +68,15 @@ public ParseResource Parse(string? title, string? path)
Languages = remoteEpisode.Languages,
CustomFormats = remoteEpisode.CustomFormats?.ToResource(false),
CustomFormatScore = remoteEpisode.CustomFormatScore
};
});
}
else
{
return new ParseResource
return TypedResults.Ok(new ParseResource
{
Title = title,
ParsedEpisodeInfo = parsedEpisodeInfo
};
});
}
}
}

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.CustomFormats;
@ -46,30 +48,30 @@ public QualityProfileController(IQualityProfileService profileService, ICustomFo
[RestPostById]
[Consumes("application/json")]
public ActionResult<QualityProfileResource> Create([FromBody] QualityProfileResource resource)
public Results<Created<QualityProfileResource>, NotFound> Create([FromBody] QualityProfileResource resource)
{
var model = resource.ToModel();
model = _profileService.Add(model);
return Created(model.Id);
return TypedCreated(model.Id);
}
[RestDeleteById]
public ActionResult DeleteProfile(int id)
public NoContent DeleteProfile(int id)
{
_profileService.Delete(id);
return NoContent();
return TypedResults.NoContent();
}
[RestPutById]
[Consumes("application/json")]
public ActionResult<QualityProfileResource> Update([FromBody] QualityProfileResource resource)
public Results<Accepted<QualityProfileResource>, NotFound> Update([FromBody] QualityProfileResource resource)
{
var model = resource.ToModel();
_profileService.Update(model);
return Accepted(model.Id);
return TypedAccepted(model.Id);
}
protected override QualityProfileResource GetResourceById(int id)
@ -79,8 +81,8 @@ protected override QualityProfileResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<QualityProfileResource> GetAll()
public Ok<List<QualityProfileResource>> GetAll()
{
return _profileService.All().ToResource();
return TypedResults.Ok(_profileService.All().ToResource());
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Profiles.Qualities;
using Sonarr.Http;
@ -15,11 +17,11 @@ public QualityProfileSchemaController(IQualityProfileService profileService)
}
[HttpGet]
public QualityProfileResource GetSchema()
public Ok<QualityProfileResource> GetSchema()
{
var qualityProfile = _profileService.GetDefaultProfile(string.Empty);
return qualityProfile.ToResource();
return TypedResults.Ok(qualityProfile.ToResource());
}
}
}

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Indexers;
@ -52,29 +54,29 @@ public ReleaseProfileController(IReleaseProfileService releaseProfileService, II
}
[RestPostById]
public ActionResult<ReleaseProfileResource> Create([FromBody] ReleaseProfileResource resource)
public Results<Created<ReleaseProfileResource>, NotFound> Create([FromBody] ReleaseProfileResource resource)
{
var model = resource.ToModel();
model = _releaseProfileService.Add(model);
return Created(model.Id);
return TypedCreated(model.Id);
}
[RestDeleteById]
public ActionResult DeleteProfile(int id)
public NoContent DeleteProfile(int id)
{
_releaseProfileService.Delete(id);
return NoContent();
return TypedResults.NoContent();
}
[RestPutById]
public ActionResult<ReleaseProfileResource> Update([FromBody] ReleaseProfileResource resource)
public Results<Accepted<ReleaseProfileResource>, NotFound> Update([FromBody] ReleaseProfileResource resource)
{
var model = resource.ToModel();
_releaseProfileService.Update(model);
return Accepted(model.Id);
return TypedAccepted(model.Id);
}
protected override ReleaseProfileResource GetResourceById(int id)
@ -83,8 +85,8 @@ protected override ReleaseProfileResource GetResourceById(int id)
}
[HttpGet]
public List<ReleaseProfileResource> GetAll()
public Ok<List<ReleaseProfileResource>> GetAll()
{
return _releaseProfileService.All().ToResource();
return TypedResults.Ok(_releaseProfileService.All().ToResource());
}
}

View file

@ -1,5 +1,7 @@
using FluentValidation;
using FluentValidation.Results;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Serializer;
@ -57,7 +59,7 @@ protected override TProviderResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<TProviderResource> GetAll()
public Ok<List<TProviderResource>> GetAll()
{
var providerDefinitions = _providerFactory.All();
@ -70,13 +72,13 @@ public List<TProviderResource> GetAll()
result.Add(_resourceMapper.ToResource(definition));
}
return result.OrderBy(p => p.Name).ToList();
return TypedResults.Ok(result.OrderBy(p => p.Name).ToList());
}
[RestPostById]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<TProviderResource> CreateProvider([FromBody] TProviderResource providerResource, [FromQuery] bool skipTesting = false, [FromQuery] SkipValidation skipValidation = SkipValidation.None)
public Results<Created<TProviderResource>, NotFound> CreateProvider([FromBody] TProviderResource providerResource, [FromQuery] bool skipTesting = false, [FromQuery] SkipValidation skipValidation = SkipValidation.None)
{
var providerDefinition = GetDefinition(providerResource, null, skipValidation, false);
@ -87,20 +89,20 @@ public ActionResult<TProviderResource> CreateProvider([FromBody] TProviderResour
providerDefinition = _providerFactory.Create(providerDefinition);
return Created(providerDefinition.Id);
return TypedCreated(providerDefinition.Id);
}
[RestPutById]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<TProviderResource> UpdateProvider([FromRoute] int id, [FromBody] TProviderResource providerResource, [FromQuery] bool skipTesting = false, [FromQuery] SkipValidation skipValidation = SkipValidation.None)
public Results<Accepted<TProviderResource>, NotFound> UpdateProvider([FromRoute] int id, [FromBody] TProviderResource providerResource, [FromQuery] bool skipTesting = false, [FromQuery] SkipValidation skipValidation = SkipValidation.None)
{
// TODO: Remove fallback to Id from body in next API version bump
var existingDefinition = _providerFactory.Find(id) ?? _providerFactory.Find(providerResource.Id);
if (existingDefinition == null)
{
return NotFound();
return TypedResults.NotFound();
}
var providerDefinition = GetDefinition(providerResource, existingDefinition, skipValidation, false);
@ -119,13 +121,13 @@ public ActionResult<TProviderResource> UpdateProvider([FromRoute] int id, [FromB
_providerFactory.Update(providerDefinition);
}
return Accepted(existingDefinition.Id);
return TypedAccepted(existingDefinition.Id);
}
[HttpPut("bulk")]
[Consumes("application/json")]
[Produces("application/json")]
public virtual ActionResult<TProviderResource> UpdateProvider([FromBody] TBulkProviderResource providerResource)
public virtual Results<Ok<IEnumerable<TProviderResource>>, BadRequest> UpdateProvider([FromBody] TBulkProviderResource providerResource)
{
if (!providerResource.Ids.Any())
{
@ -160,7 +162,7 @@ public virtual ActionResult<TProviderResource> UpdateProvider([FromBody] TBulkPr
_bulkResourceMapper.UpdateModel(providerResource, definitionsToUpdate);
return Accepted(_providerFactory.Update(definitionsToUpdate).Select(x => _resourceMapper.ToResource(x)));
return TypedResults.Ok(_providerFactory.Update(definitionsToUpdate).Select(x => _resourceMapper.ToResource(x)));
}
private TProviderDefinition GetDefinition(TProviderResource providerResource, TProviderDefinition? existingDefinition, SkipValidation skipValidation, bool forceValidate)
@ -176,25 +178,25 @@ private TProviderDefinition GetDefinition(TProviderResource providerResource, TP
}
[RestDeleteById]
public ActionResult DeleteProvider(int id)
public NoContent DeleteProvider(int id)
{
_providerFactory.Delete(id);
return NoContent();
return TypedResults.NoContent();
}
[HttpDelete("bulk")]
[Consumes("application/json")]
public virtual ActionResult DeleteProviders([FromBody] TBulkProviderResource resource)
public virtual NoContent DeleteProviders([FromBody] TBulkProviderResource resource)
{
_providerFactory.Delete(resource.Ids);
return NoContent();
return TypedResults.NoContent();
}
[HttpGet("schema")]
[Produces("application/json")]
public List<TProviderResource> GetTemplates()
public Ok<List<TProviderResource>> GetTemplates()
{
var defaultDefinitions = _providerFactory.GetDefaultDefinitions().OrderBy(p => p.ImplementationName).ToList();
@ -212,25 +214,25 @@ public List<TProviderResource> GetTemplates()
result.Add(providerResource);
}
return result;
return TypedResults.Ok(result);
}
[SkipValidation(true, false)]
[HttpPost("test")]
[Consumes("application/json")]
public ActionResult Test([FromBody] TProviderResource providerResource, [FromQuery] SkipValidation skipValidation = SkipValidation.None)
public NoContent Test([FromBody] TProviderResource providerResource, [FromQuery] SkipValidation skipValidation = SkipValidation.None)
{
var existingDefinition = providerResource.Id > 0 ? _providerFactory.Find(providerResource.Id) : null;
var providerDefinition = GetDefinition(providerResource, existingDefinition, skipValidation, true);
Test(providerDefinition, skipValidation);
return NoContent();
return TypedResults.NoContent();
}
[HttpPost("testall")]
[Produces("application/json")]
public IActionResult TestAll()
public Results<Ok<List<ProviderTestAllResult>>, BadRequest<List<ProviderTestAllResult>>> TestAll()
{
var providerDefinitions = _providerFactory.All()
.Where(c => c.Settings.Validate().IsValid && c.Enable)
@ -251,14 +253,14 @@ public IActionResult TestAll()
});
}
return result.Any(c => !c.IsValid) ? BadRequest(result) : Ok(result);
return result.Any(c => !c.IsValid) ? TypedResults.BadRequest(result) : TypedResults.Ok(result);
}
[SkipValidation]
[HttpPost("action/{name}")]
[Consumes("application/json")]
[Produces("application/json")]
public IActionResult RequestAction([FromRoute] string name, [FromBody] TProviderResource providerResource)
public Results<ContentHttpResult, BadRequest> RequestAction([FromRoute] string name, [FromBody] TProviderResource providerResource)
{
var existingDefinition = providerResource.Id > 0 ? _providerFactory.Find(providerResource.Id) : null;
var providerDefinition = GetDefinition(providerResource, existingDefinition, SkipValidation.All, false);
@ -267,7 +269,7 @@ public IActionResult RequestAction([FromRoute] string name, [FromBody] TProvider
var data = _providerFactory.RequestAction(providerDefinition, name, query);
return Content(data.ToJson(), "application/json");
return TypedResults.Content(data.ToJson(), "application/json");
}
[NonAction]

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Messaging.Events;
@ -29,7 +31,7 @@ public QualityDefinitionController(
}
[RestPutById]
public ActionResult<QualityDefinitionResource> Update([FromBody] QualityDefinitionResource resource)
public Results<Accepted<QualityDefinitionResource>, NotFound> Update([FromBody] QualityDefinitionResource resource)
{
var model = resource.ToModel();
_qualityDefinitionService.Update(model);
@ -39,7 +41,7 @@ public ActionResult<QualityDefinitionResource> Update([FromBody] QualityDefiniti
_qualityProfileService.UpdateAllSizeLimits(new QualityProfileSizeLimit(model));
}
return Accepted(model.Id);
return TypedAccepted(model.Id);
}
protected override QualityDefinitionResource GetResourceById(int id)
@ -48,13 +50,13 @@ protected override QualityDefinitionResource GetResourceById(int id)
}
[HttpGet]
public List<QualityDefinitionResource> GetAll()
public Ok<List<QualityDefinitionResource>> GetAll()
{
return _qualityDefinitionService.All().ToResource();
return TypedResults.Ok(_qualityDefinitionService.All().ToResource());
}
[HttpPut]
public object UpdateMany([FromBody] List<QualityDefinitionResource> resource)
public Ok<List<QualityDefinitionResource>> UpdateMany([FromBody] List<QualityDefinitionResource> resource)
{
// Read from request
var qualityDefinitions = resource.ToModel().ToList();
@ -71,8 +73,7 @@ public object UpdateMany([FromBody] List<QualityDefinitionResource> resource)
_qualityProfileService.UpdateAllSizeLimits(toUpdate);
}
return Accepted(_qualityDefinitionService.All()
.ToResource());
return TypedResults.Ok(_qualityDefinitionService.All().ToResource());
}
[NonAction]

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Pending;
@ -20,7 +22,7 @@ public QueueActionController(IPendingReleaseService pendingReleaseService,
}
[HttpPost("grab/{id:int}")]
public async Task<object> Grab([FromRoute] int id)
public async Task<NoContent> Grab([FromRoute] int id)
{
var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id);
@ -31,12 +33,12 @@ public async Task<object> Grab([FromRoute] int id)
await _downloadService.DownloadReport(pendingRelease.RemoteEpisode, null);
return NoContent();
return TypedResults.NoContent();
}
[HttpPost("grab/bulk")]
[Consumes("application/json")]
public async Task<object> Grab([FromBody] QueueBulkResource resource)
public async Task<NoContent> Grab([FromBody] QueueBulkResource resource)
{
foreach (var id in resource.Ids)
{
@ -50,7 +52,7 @@ public async Task<object> Grab([FromBody] QueueBulkResource resource)
await _downloadService.DownloadReport(pendingRelease.RemoteEpisode, null);
}
return NoContent();
return TypedResults.NoContent();
}
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Blocklisting;
@ -57,7 +59,7 @@ public QueueController(IBroadcastSignalRMessage broadcastSignalRMessage,
}
[NonAction]
public override ActionResult<QueueResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<QueueResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}
@ -68,7 +70,7 @@ protected override QueueResource GetResourceById(int id)
}
[RestDeleteById]
public ActionResult RemoveAction(int id, string? message = null, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false, bool changeCategory = false)
public Results<NoContent, NotFound> RemoveAction(int id, string? message = null, bool removeFromClient = true, bool blocklist = false, bool skipRedownload = false, bool changeCategory = false)
{
var pendingRelease = _pendingReleaseService.FindPendingQueueItem(id);
@ -76,7 +78,7 @@ public ActionResult RemoveAction(int id, string? message = null, bool removeFrom
{
Remove(pendingRelease, message, blocklist);
return NoContent();
return TypedResults.NoContent();
}
var trackedDownload = GetTrackedDownload(id);
@ -89,11 +91,11 @@ public ActionResult RemoveAction(int id, string? message = null, bool removeFrom
Remove(trackedDownload, message, removeFromClient, blocklist, skipRedownload, changeCategory);
_trackedDownloadService.StopTracking(trackedDownload.DownloadItem.DownloadId);
return NoContent();
return TypedResults.NoContent();
}
[HttpDelete("bulk")]
public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] string? message, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false, [FromQuery] bool changeCategory = false)
public NoContent RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] string? message, [FromQuery] bool removeFromClient = true, [FromQuery] bool blocklist = false, [FromQuery] bool skipRedownload = false, [FromQuery] bool changeCategory = false)
{
var trackedDownloadIds = new List<string>();
var pendingToRemove = new List<NzbDrone.Core.Queue.Queue>();
@ -130,12 +132,12 @@ public object RemoveMany([FromBody] QueueBulkResource resource, [FromQuery] stri
_trackedDownloadService.StopTracking(trackedDownloadIds);
return NoContent();
return TypedResults.NoContent();
}
[HttpGet]
[Produces("application/json")]
public PagingResource<QueueResource> GetQueue([FromQuery] PagingRequestResource paging, bool includeUnknownSeriesItems = true, [FromQuery] int[]? seriesIds = null, DownloadProtocol? protocol = null, [FromQuery] int[]? languages = null, [FromQuery] int[]? quality = null, [FromQuery] QueueStatus[]? status = null, [FromQuery] QueueSubresource[]? includeSubresources = null)
public Ok<PagingResource<QueueResource>> GetQueue([FromQuery] PagingRequestResource paging, bool includeUnknownSeriesItems = true, [FromQuery] int[]? seriesIds = null, DownloadProtocol? protocol = null, [FromQuery] int[]? languages = null, [FromQuery] int[]? quality = null, [FromQuery] QueueStatus[]? status = null, [FromQuery] QueueSubresource[]? includeSubresources = null)
{
var pagingResource = new PagingResource<QueueResource>(paging);
var pagingSpec = pagingResource.MapToPagingSpec<QueueResource, NzbDrone.Core.Queue.Queue>(
@ -167,7 +169,7 @@ public PagingResource<QueueResource> GetQueue([FromQuery] PagingRequestResource
var includeSeries = includeSubresources.Contains(QueueSubresource.Series);
var includeEpisodes = includeSubresources.Contains(QueueSubresource.Episodes);
return pagingSpec.ApplyToPage((spec) => GetQueue(spec, seriesIds?.ToHashSet() ?? [], protocol, languages?.ToHashSet() ?? [], quality?.ToHashSet() ?? [], status?.ToHashSet() ?? [], includeUnknownSeriesItems), (q) => MapToResource(q, includeSeries, includeEpisodes));
return TypedResults.Ok(pagingSpec.ApplyToPage((spec) => GetQueue(spec, seriesIds?.ToHashSet() ?? [], protocol, languages?.ToHashSet() ?? [], quality?.ToHashSet() ?? [], status?.ToHashSet() ?? [], includeUnknownSeriesItems), (q) => MapToResource(q, includeSeries, includeEpisodes)));
}
private PagingSpec<NzbDrone.Core.Queue.Queue> GetQueue(PagingSpec<NzbDrone.Core.Queue.Queue> pagingSpec, HashSet<int> seriesIds, DownloadProtocol? protocol, HashSet<int> languages, HashSet<int> quality, HashSet<QueueStatus> status, bool includeUnknownSeriesItems)

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events;
@ -25,7 +27,7 @@ public QueueDetailsController(IBroadcastSignalRMessage broadcastSignalRMessage,
}
[NonAction]
public override ActionResult<QueueResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<QueueResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}
@ -37,7 +39,7 @@ protected override QueueResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<QueueResource> GetQueue(int? seriesId, [FromQuery]List<int> episodeIds, [FromQuery] QueueSubresource[]? includeSubresources = null)
public Ok<List<QueueResource>> GetQueue(int? seriesId, [FromQuery]List<int> episodeIds, [FromQuery] QueueSubresource[]? includeSubresources = null)
{
var queue = _queueService.GetQueue();
var pending = _pendingReleaseService.GetPendingQueue();
@ -47,17 +49,17 @@ public List<QueueResource> GetQueue(int? seriesId, [FromQuery]List<int> episodeI
if (seriesId.HasValue)
{
return fullQueue.Where(q => q.Series?.Id == seriesId).ToResource(includeSeries, includeEpisodes);
return TypedResults.Ok(fullQueue.Where(q => q.Series?.Id == seriesId).ToResource(includeSeries, includeEpisodes));
}
if (episodeIds.Any())
{
return fullQueue.Where(q => q.Episodes.Any() &&
return TypedResults.Ok(fullQueue.Where(q => q.Episodes.Any() &&
episodeIds.IntersectBy(e => e, q.Episodes, e => e.Id, null).Any())
.ToResource(includeSeries, includeEpisodes);
.ToResource(includeSeries, includeEpisodes));
}
return fullQueue.ToResource(includeSeries, includeEpisodes);
return TypedResults.Ok(fullQueue.ToResource(includeSeries, includeEpisodes));
}
[NonAction]

View file

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Download.Pending;
@ -29,7 +30,7 @@ public QueueStatusController(IBroadcastSignalRMessage broadcastSignalRMessage, I
}
[NonAction]
public override ActionResult<QueueStatusResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<QueueStatusResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NLog;
using NzbDrone.Common.Cache;
@ -71,7 +73,7 @@ public ReleaseController(IFetchAndParseRss rssFetcherAndParser,
}
[NonAction]
public override ActionResult<ReleaseResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<ReleaseResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}
@ -83,7 +85,7 @@ protected override ReleaseResource GetResourceById(int id)
[HttpPost]
[Consumes("application/json")]
public async Task<object> DownloadRelease([FromBody] ReleaseGrabResource release)
public async Task<Results<Ok<ReleaseGrabResource>, NotFound>> DownloadRelease([FromBody] ReleaseGrabResource release)
{
var remoteEpisode = _remoteEpisodeCache.Find(GetCacheKey(release));
@ -182,24 +184,24 @@ public async Task<object> DownloadRelease([FromBody] ReleaseGrabResource release
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
}
return release;
return TypedResults.Ok(release);
}
[HttpGet]
[Produces("application/json")]
public async Task<List<ReleaseResource>> GetReleases(int? seriesId, int? episodeId, int? seasonNumber)
public async Task<Results<Ok<List<ReleaseResource>>, BadRequest>> GetReleases(int? seriesId, int? episodeId, int? seasonNumber)
{
if (episodeId.HasValue)
{
return await GetEpisodeReleases(episodeId.Value);
return TypedResults.Ok(await GetEpisodeReleases(episodeId.Value));
}
if (seriesId.HasValue && seasonNumber.HasValue)
{
return await GetSeasonReleases(seriesId.Value, seasonNumber.Value);
return TypedResults.Ok(await GetSeasonReleases(seriesId.Value, seasonNumber.Value));
}
return await GetRss();
return TypedResults.Ok(await GetRss());
}
private async Task<List<ReleaseResource>> GetEpisodeReleases(int episodeId)

View file

@ -1,5 +1,7 @@
using FluentValidation;
using FluentValidation.Results;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NLog;
using NzbDrone.Common.Extensions;
@ -50,7 +52,7 @@ public ReleasePushController(IMakeDownloadDecision downloadDecisionMaker,
[HttpPost]
[Consumes("application/json")]
public ActionResult<ReleaseResource> Create([FromBody] ReleasePushResource release)
public Results<Ok<ReleaseResource>, BadRequest> Create([FromBody] ReleasePushResource release)
{
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl ?? release.MagnetUrl);
@ -80,7 +82,7 @@ public ActionResult<ReleaseResource> Create([FromBody] ReleasePushResource relea
throw new ValidationException(new List<ValidationFailure> { new("Title", "Unable to parse", release.Title) });
}
return decision.MapDecision(1, _qualityProfile);
return TypedResults.Ok(decision.MapDecision(1, _qualityProfile));
}
private void ResolveIndexer(ReleaseInfo release)

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.RemotePathMappings;
using NzbDrone.Core.Validation.Paths;
@ -47,33 +49,33 @@ protected override RemotePathMappingResource GetResourceById(int id)
[RestPostById]
[Consumes("application/json")]
public ActionResult<RemotePathMappingResource> CreateMapping([FromBody] RemotePathMappingResource resource)
public Results<Created<RemotePathMappingResource>, NotFound> CreateMapping([FromBody] RemotePathMappingResource resource)
{
var model = resource.ToModel();
return Created(_remotePathMappingService.Add(model).Id);
return TypedCreated(_remotePathMappingService.Add(model).Id);
}
[HttpGet]
[Produces("application/json")]
public List<RemotePathMappingResource> GetMappings()
public Ok<List<RemotePathMappingResource>> GetMappings()
{
return _remotePathMappingService.All().ToResource();
return TypedResults.Ok(_remotePathMappingService.All().ToResource());
}
[RestDeleteById]
public ActionResult DeleteMapping(int id)
public NoContent DeleteMapping(int id)
{
_remotePathMappingService.Remove(id);
return NoContent();
return TypedResults.NoContent();
}
[RestPutById]
public ActionResult<RemotePathMappingResource> UpdateMapping([FromBody] RemotePathMappingResource resource)
public Results<Ok<RemotePathMappingResource>, NotFound> UpdateMapping([FromBody] RemotePathMappingResource resource)
{
var mapping = resource.ToModel();
return Accepted(_remotePathMappingService.Update(mapping));
return TypedResults.Ok(_remotePathMappingService.Update(mapping).ToResource());
}
}

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Validation.Paths;
@ -49,25 +51,25 @@ protected override RootFolderResource GetResourceById(int id)
[RestPostById]
[Consumes("application/json")]
public ActionResult<RootFolderResource> CreateRootFolder([FromBody] RootFolderResource rootFolderResource)
public Results<Created<RootFolderResource>, NotFound> CreateRootFolder([FromBody] RootFolderResource rootFolderResource)
{
var model = rootFolderResource.ToModel();
return Created(_rootFolderService.Add(model).Id);
return TypedCreated(_rootFolderService.Add(model).Id);
}
[HttpGet]
[Produces("application/json")]
public List<RootFolderResource> GetRootFolders()
public Ok<List<RootFolderResource>> GetRootFolders()
{
return _rootFolderService.AllWithUnmappedFolders().ToResource();
return TypedResults.Ok(_rootFolderService.AllWithUnmappedFolders().ToResource());
}
[RestDeleteById]
public ActionResult DeleteFolder(int id)
public NoContent DeleteFolder(int id)
{
_rootFolderService.Remove(id);
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Tv;
using Sonarr.Http;
@ -18,7 +20,7 @@ public SeasonPassController(ISeriesService seriesService, IEpisodeMonitoredServi
[HttpPost]
[Consumes("application/json")]
public IActionResult UpdateAll([FromBody] SeasonPassResource resource)
public NoContent UpdateAll([FromBody] SeasonPassResource resource)
{
var seriesToUpdate = _seriesService.GetSeries(resource.Series.Select(s => s.Id));
@ -52,6 +54,6 @@ public IActionResult UpdateAll([FromBody] SeasonPassResource resource)
_episodeMonitoredService.SetEpisodeMonitoredStatus(series, resource.MonitoringOptions.ToModel());
}
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.TPL;
@ -107,7 +109,7 @@ public SeriesController(IBroadcastSignalRMessage signalRBroadcaster,
[HttpGet]
[Produces("application/json")]
public List<SeriesResource> AllSeries(int? tvdbId, [FromQuery] SeriesSubresource[]? includeSubresources = null)
public Ok<List<SeriesResource>> AllSeries(int? tvdbId, [FromQuery] SeriesSubresource[]? includeSubresources = null)
{
var seriesStats = _seriesStatisticsService.SeriesStatistics();
var seriesResources = new List<SeriesResource>();
@ -127,18 +129,18 @@ public List<SeriesResource> AllSeries(int? tvdbId, [FromQuery] SeriesSubresource
PopulateAlternateTitles(seriesResources);
seriesResources.ForEach(LinkRootFolderPath);
return seriesResources;
return TypedResults.Ok(seriesResources);
}
[NonAction]
public override ActionResult<SeriesResource> GetResourceByIdWithErrorHandler(int id)
public override Results<Ok<SeriesResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
return base.GetResourceByIdWithErrorHandler(id);
}
[RestGetById]
[Produces("application/json")]
public ActionResult<SeriesResource> GetResourceByIdWithErrorHandler(int id, [FromQuery] SeriesSubresource[]? includeSubresources = null)
public Results<Ok<SeriesResource>, NotFound> GetResourceByIdWithErrorHandler(int id, [FromQuery] SeriesSubresource[]? includeSubresources = null)
{
var includeSeasonImages = includeSubresources.Contains(SeriesSubresource.SeasonImages);
@ -146,11 +148,11 @@ public ActionResult<SeriesResource> GetResourceByIdWithErrorHandler(int id, [Fro
{
var series = GetSeriesResourceById(id, includeSeasonImages);
return series == null ? NotFound() : series;
return series == null ? TypedResults.NotFound() : TypedResults.Ok(series);
}
catch (ModelNotFoundException)
{
return NotFound();
return TypedResults.NotFound();
}
}
@ -181,17 +183,17 @@ public ActionResult<SeriesResource> GetResourceByIdWithErrorHandler(int id, [Fro
[RestPostById]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<SeriesResource> AddSeries([FromBody] SeriesResource seriesResource)
public Results<Created<SeriesResource>, NotFound> AddSeries([FromBody] SeriesResource seriesResource)
{
var series = _addSeriesService.AddSeries(seriesResource.ToModel());
return Created(series.Id);
return TypedCreated(series.Id);
}
[RestPutById]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<SeriesResource> UpdateSeries([FromBody] SeriesResource seriesResource, [FromQuery] bool moveFiles = false)
public Results<Accepted<SeriesResource>, NotFound> UpdateSeries([FromBody] SeriesResource seriesResource, [FromQuery] bool moveFiles = false)
{
var series = _seriesService.GetSeries(seriesResource.Id);
@ -215,13 +217,13 @@ public ActionResult<SeriesResource> UpdateSeries([FromBody] SeriesResource serie
BroadcastResourceChange(ModelAction.Updated, seriesResource);
return Accepted(seriesResource.Id);
return TypedAccepted(seriesResource.Id);
}
[HttpPut("{id}/season")]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<SeasonResource> UpdateSeasonMonitored([FromRoute] int id, [FromBody] SeasonResource seasonResource)
public Results<Ok<SeasonResource>, NotFound> UpdateSeasonMonitored([FromRoute] int id, [FromBody] SeasonResource seasonResource)
{
lock (_seriesLockPool.GetLock(id))
{
@ -230,7 +232,7 @@ public ActionResult<SeasonResource> UpdateSeasonMonitored([FromRoute] int id, [F
if (season == null)
{
return NotFound();
return TypedResults.NotFound();
}
season.Monitored = seasonResource.Monitored;
@ -239,16 +241,16 @@ public ActionResult<SeasonResource> UpdateSeasonMonitored([FromRoute] int id, [F
BroadcastResourceChange(ModelAction.Updated, series.ToResource());
return season.ToResource();
return TypedResults.Ok(season.ToResource());
}
}
[RestDeleteById]
public ActionResult DeleteSeries(int id, bool deleteFiles = false, bool addImportListExclusion = false)
public NoContent DeleteSeries(int id, bool deleteFiles = false, bool addImportListExclusion = false)
{
_seriesService.DeleteSeries(new List<int> { id }, deleteFiles, addImportListExclusion);
return NoContent();
return TypedResults.NoContent();
}
private SeriesResource? GetSeriesResource(NzbDrone.Core.Tv.Series? series, bool includeSeasonImages)

View file

@ -1,4 +1,6 @@
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Messaging.Commands;
@ -23,7 +25,7 @@ public SeriesEditorController(ISeriesService seriesService, IManageCommandQueue
}
[HttpPut]
public object SaveAll([FromBody] SeriesEditorResource resource)
public Results<Ok<List<SeriesResource>>, BadRequest> SaveAll([FromBody] SeriesEditorResource resource)
{
var seriesToUpdate = _seriesService.GetSeries(resource.SeriesIds);
var seriesToMove = new List<BulkMoveSeries>();
@ -101,14 +103,14 @@ public object SaveAll([FromBody] SeriesEditorResource resource)
});
}
return Accepted(_seriesService.UpdateSeries(seriesToUpdate, !resource.MoveFiles).ToResource());
return TypedResults.Ok(_seriesService.UpdateSeries(seriesToUpdate, !resource.MoveFiles).ToResource());
}
[HttpDelete]
public object DeleteSeries([FromBody] SeriesEditorResource resource)
public NoContent DeleteSeries([FromBody] SeriesEditorResource resource)
{
_seriesService.DeleteSeries(resource.SeriesIds, resource.DeleteFiles, resource.AddImportListExclusion);
return NoContent();
return TypedResults.NoContent();
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Tv;
@ -19,14 +21,14 @@ public SeriesFolderController(ISeriesService seriesService, IBuildFileNames file
[HttpGet("{id}/folder")]
[Produces("application/json")]
public object GetFolder([FromRoute] int id)
public Ok<object> GetFolder([FromRoute] int id)
{
var series = _seriesService.GetSeries(id);
var folder = _fileNameBuilder.GetSeriesFolder(series);
return new
return TypedResults.Ok((object)new
{
folder
};
});
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Tv;
using Sonarr.Http;
@ -15,11 +17,11 @@ public SeriesImportController(IAddSeriesService addSeriesService)
}
[HttpPost]
public object Import([FromBody] List<SeriesResource> resource)
public Ok<List<SeriesResource>> Import([FromBody] List<SeriesResource> resource)
{
var newSeries = resource.ToModel();
return _addSeriesService.AddSeries(newSeries).ToResource();
return TypedResults.Ok(_addSeriesService.AddSeries(newSeries).ToResource());
}
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.ImportLists.Exclusions;
using NzbDrone.Core.MediaCover;
@ -25,10 +27,10 @@ public SeriesLookupController(ISearchForNewSeries searchProxy, IBuildFileNames f
}
[HttpGet]
public IEnumerable<SeriesResource> Search([FromQuery] string term)
public Ok<IEnumerable<SeriesResource>> Search([FromQuery] string term)
{
var tvDbResults = _searchProxy.SearchForNewSeries(term);
return MapToResource(tvDbResults);
return TypedResults.Ok(MapToResource(tvDbResults));
}
private IEnumerable<SeriesResource> MapToResource(IEnumerable<NzbDrone.Core.Tv.Series> series)

View file

@ -1,5 +1,5 @@
using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http.HttpResults;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Authentication;
@ -102,7 +102,7 @@ protected override GeneralSettingsResource ToResource(IConfigFileProvider config
return resource;
}
public override ActionResult<GeneralSettingsResource> SaveSettings(GeneralSettingsResource resource)
public override Results<Accepted<GeneralSettingsResource>, NotFound> SaveSettings(GeneralSettingsResource resource)
{
if (resource.Username.IsNotNullOrWhiteSpace() && resource.Password.IsNotNullOrWhiteSpace())
{

View file

@ -1,5 +1,7 @@
using FluentValidation;
using FluentValidation.Results;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Organizer;
@ -36,27 +38,24 @@ public NamingSettingsController(INamingConfigService namingConfigService,
protected override NamingSettingsResource GetResourceById(int id)
{
return GetNamingConfig();
return _namingConfigService.GetConfig().ToResource();
}
[HttpGet]
public NamingSettingsResource GetNamingConfig()
public Ok<NamingSettingsResource> GetNamingConfig()
{
var nameSpec = _namingConfigService.GetConfig();
var resource = nameSpec.ToResource();
return resource;
return TypedResults.Ok(GetResourceById(1));
}
[RestPutById]
public ActionResult<NamingSettingsResource> UpdateNamingConfig([FromBody] NamingSettingsResource resource)
public Results<Accepted<NamingSettingsResource>, NotFound> UpdateNamingConfig([FromBody] NamingSettingsResource resource)
{
var nameSpec = resource.ToModel();
ValidateFormatResult(nameSpec);
_namingConfigService.Save(nameSpec);
return Accepted(resource.Id);
return TypedAccepted(resource.Id);
}
[HttpGet("examples")]
@ -64,7 +63,7 @@ public object GetExamples([FromQuery]NamingSettingsResource settings)
{
if (settings.Id == 0)
{
settings = GetNamingConfig();
settings = GetResourceById(1);
}
var nameSpec = settings.ToModel();

View file

@ -1,4 +1,6 @@
using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Configuration;
using Sonarr.Http.REST;
@ -19,23 +21,24 @@ protected SettingsController(IConfigFileProvider configFileProvider, IConfigServ
}
protected override TResource GetResourceById(int id)
{
return GetConfig();
}
[HttpGet]
[Produces("application/json")]
public TResource GetConfig()
{
var resource = ToResource(_configFileProvider, _configService);
resource.Id = 1;
resource.Id = id;
return resource;
}
[HttpGet]
[Produces("application/json")]
public Ok<TResource> GetConfig()
{
return TypedResults.Ok(GetResourceById(1));
}
[RestPutById]
[Consumes("application/json")]
public virtual ActionResult<TResource> SaveSettings([FromBody] TResource resource)
[Produces("application/json")]
public virtual Results<Accepted<TResource>, NotFound> SaveSettings([FromBody] TResource resource)
{
var dictionary = resource.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
@ -44,7 +47,7 @@ public virtual ActionResult<TResource> SaveSettings([FromBody] TResource resourc
_configFileProvider.SaveConfigDictionary(dictionary);
_configService.SaveConfigDictionary(dictionary);
return Accepted(resource.Id);
return TypedAccepted(resource.Id);
}
protected abstract TResource ToResource(IConfigFileProvider configFile, IConfigService model);

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Crypto;
using NzbDrone.Common.Disk;
@ -29,7 +31,7 @@ public BackupController(IBackupService backupService,
[HttpGet]
[Produces("application/json")]
public ActionResult<List<BackupResource>> GetAll()
public Ok<List<BackupResource>> GetAll()
{
var backups = _backupService.GetBackups();
@ -45,11 +47,11 @@ public ActionResult<List<BackupResource>> GetAll()
.OrderByDescending(b => b.Time)
.ToList();
return resources;
return TypedResults.Ok(resources);
}
[RestDeleteById]
public ActionResult Delete(int id)
public Results<NoContent, NotFound> Delete(int id)
{
var backup = GetBackupById(id);
@ -67,30 +69,30 @@ public ActionResult Delete(int id)
_diskProvider.DeleteFile(path);
return NoContent();
return TypedResults.NoContent();
}
[HttpPost("restore/{id:int}")]
[Produces("application/json")]
public ActionResult<object> Restore([FromRoute] int id)
public Results<Ok<object>, NotFound> Restore([FromRoute] int id)
{
var backup = GetBackupById(id);
if (backup == null)
{
return NotFound();
return TypedResults.NotFound();
}
var path = GetBackupPath(backup);
_backupService.Restore(path);
return new { RestartRequired = true };
return TypedResults.Ok((object)new { RestartRequired = true });
}
[HttpPost("restore/upload")]
[Produces("application/json")]
[RequestFormLimits(MultipartBodyLengthLimit = 5000000000)]
public ActionResult<object> RestoreUpload()
public Results<Ok<object>, BadRequest<object>> RestoreUpload()
{
var files = Request.Form.Files;
@ -104,7 +106,7 @@ public ActionResult<object> RestoreUpload()
if (!ValidExtensions.Contains(extension))
{
return BadRequest(new { error = $"Invalid extension, must be one of: {string.Join(", ", ValidExtensions)}" });
return TypedResults.BadRequest((object)new { error = $"Invalid extension, must be one of: {string.Join(", ", ValidExtensions)}" });
}
var path = Path.Combine(_appFolderInfo.TempFolder, $"sonarr_backup_restore{extension}");
@ -113,7 +115,7 @@ public ActionResult<object> RestoreUpload()
_backupService.Restore(path);
_diskProvider.DeleteFile(path);
return new { RestartRequired = true };
return TypedResults.Ok((object)new { RestartRequired = true });
}
private string GetBackupPath(NzbDrone.Core.Backup.Backup backup)

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Routing.Internal;
@ -53,9 +55,9 @@ public SystemController(IAppFolderInfo appFolderInfo,
[HttpGet("status")]
[Produces("application/json")]
public SystemResource GetStatus()
public Ok<SystemResource> GetStatus()
{
return new SystemResource
return TypedResults.Ok(new SystemResource
{
AppName = BuildInfo.AppName,
InstanceName = _configFileProvider.InstanceName,
@ -88,39 +90,39 @@ public SystemResource GetStatus()
PackageAuthor = _deploymentInfoProvider.PackageAuthor,
PackageUpdateMechanism = _deploymentInfoProvider.PackageUpdateMechanism,
PackageUpdateMechanismMessage = _deploymentInfoProvider.PackageUpdateMechanismMessage
};
});
}
[HttpGet("routes")]
[Produces("application/json")]
public IActionResult GetRoutes()
public ContentHttpResult GetRoutes()
{
using (var sw = new StringWriter())
{
_graphWriter.Write(_endpointData, sw);
var graph = sw.ToString();
return Content(graph, "text/plain");
return TypedResults.Content(graph, "text/plain");
}
}
[HttpGet("routes/duplicate")]
[Produces("application/json")]
public object DuplicateRoutes()
public Ok<Dictionary<string, List<string>>> DuplicateRoutes()
{
return _detector.GetDuplicateEndpoints(_endpointData);
return TypedResults.Ok(_detector.GetDuplicateEndpoints(_endpointData));
}
[HttpPost("shutdown")]
public object Shutdown()
public Ok<object> Shutdown()
{
Task.Factory.StartNew(() => _lifecycleService.Shutdown());
return new { ShuttingDown = true };
return TypedResults.Ok((object)new { ShuttingDown = true });
}
[HttpPost("restart")]
public object Restart()
public Ok<object> Restart()
{
Task.Factory.StartNew(() => _lifecycleService.Restart());
return new { Restarting = true };
return TypedResults.Ok((object)new { Restarting = true });
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events;
@ -22,12 +24,12 @@ public TaskController(ITaskManager taskManager, IBroadcastSignalRMessage broadca
[HttpGet]
[Produces("application/json")]
public ActionResult<List<TaskResource>> GetAll()
public Ok<List<TaskResource>> GetAll()
{
return _taskManager.GetAll()
return TypedResults.Ok(_taskManager.GetAll()
.Select(ConvertToResource)
.OrderBy(t => t.Name)
.ToList();
.ToList());
}
protected override TaskResource? GetResourceById(int id)

View file

@ -1,5 +1,7 @@
using System.Text.RegularExpressions;
using FluentValidation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.AutoTagging;
using NzbDrone.Core.Datastore.Events;
@ -38,30 +40,32 @@ protected override TagResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<TagResource> GetAll()
public Ok<List<TagResource>> GetAll()
{
return _tagService.All().ToResource();
return TypedResults.Ok(_tagService.All().ToResource());
}
[RestPostById]
[Consumes("application/json")]
public ActionResult<TagResource> Create([FromBody] TagResource resource)
public Results<Created<TagResource>, NotFound> Create([FromBody] TagResource resource)
{
return Created(_tagService.Add(resource.ToModel()).Id);
return TypedCreated(_tagService.Add(resource.ToModel()).Id);
}
[RestPutById]
[Consumes("application/json")]
public ActionResult<TagResource> Update([FromBody] TagResource resource)
public Results<Accepted<TagResource>, NotFound> Update([FromBody] TagResource resource)
{
_tagService.Update(resource.ToModel());
return Accepted(resource.Id);
return TypedAccepted(resource.Id);
}
[RestDeleteById]
public void DeleteTag(int id)
public NoContent DeleteTag(int id)
{
_tagService.Delete(id);
return TypedResults.NoContent();
}
[NonAction]

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.Tags;
using Sonarr.Http;
@ -22,8 +24,8 @@ protected override TagDetailsResource GetResourceById(int id)
[HttpGet]
[Produces("application/json")]
public List<TagDetailsResource> GetAll()
public Ok<List<TagDetailsResource>> GetAll()
{
return _tagService.Details().ToResource();
return TypedResults.Ok(_tagService.Details().ToResource());
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration;
@ -23,7 +25,7 @@ public UpdateController(IRecentUpdateProvider recentUpdateProvider, IUpdateHisto
[HttpGet]
[Produces("application/json")]
public List<UpdateResource> GetRecentUpdates()
public Ok<List<UpdateResource>> GetRecentUpdates()
{
var resources = _recentUpdateProvider.GetRecentUpdatePackages()
.OrderByDescending(u => u.Version)
@ -48,7 +50,7 @@ public List<UpdateResource> GetRecentUpdates()
if (!_configFileProvider.LogDbEnabled)
{
return resources;
return TypedResults.Ok(resources);
}
var updateHistory = _updateHistoryService.InstalledSince(resources.Last().ReleaseDate);
@ -65,7 +67,7 @@ public List<UpdateResource> GetRecentUpdates()
}
}
return resources;
return TypedResults.Ok(resources);
}
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore;
@ -28,7 +30,7 @@ public CutoffController(IEpisodeCutoffService episodeCutoffService,
[HttpGet]
[Produces("application/json")]
public PagingResource<EpisodeResource> GetCutoffUnmetEpisodes([FromQuery] PagingRequestResource paging, bool monitored = true, [FromQuery] CutoffSubresource[]? includeSubresources = null)
public Ok<PagingResource<EpisodeResource>> GetCutoffUnmetEpisodes([FromQuery] PagingRequestResource paging, bool monitored = true, [FromQuery] CutoffSubresource[]? includeSubresources = null)
{
var pagingResource = new PagingResource<EpisodeResource>(paging);
var pagingSpec = pagingResource.MapToPagingSpec<EpisodeResource, Episode>(
@ -56,6 +58,6 @@ public PagingResource<EpisodeResource> GetCutoffUnmetEpisodes([FromQuery] Paging
var resource = pagingSpec.ApplyToPage(_episodeCutoffService.EpisodesWhereCutoffUnmet, v => MapToResource(v, includeSeries, includeEpisodeFile, includeImages));
return resource;
return TypedResults.Ok(resource);
}
}

View file

@ -1,3 +1,5 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.Datastore;
@ -24,7 +26,7 @@ public MissingController(IEpisodeService episodeService,
[HttpGet]
[Produces("application/json")]
public PagingResource<EpisodeResource> GetMissingEpisodes([FromQuery] PagingRequestResource paging, bool monitored = true, bool includeSpecials = true, [FromQuery] MissingSubresource[]? includeSubresources = null)
public Ok<PagingResource<EpisodeResource>> GetMissingEpisodes([FromQuery] PagingRequestResource paging, bool monitored = true, bool includeSpecials = true, [FromQuery] MissingSubresource[]? includeSubresources = null)
{
var pagingResource = new PagingResource<EpisodeResource>(paging);
var pagingSpec = pagingResource.MapToPagingSpec<EpisodeResource, Episode>(
@ -51,6 +53,6 @@ public PagingResource<EpisodeResource> GetMissingEpisodes([FromQuery] PagingRequ
var resource = pagingSpec.ApplyToPage(spec => _episodeService.EpisodesWithoutFiles(spec, includeSpecials), v => MapToResource(v, includeSeries, false, includeImages));
return resource;
return TypedResults.Ok(resource);
}
}

View file

@ -4,6 +4,8 @@
using System.Reflection;
using FluentValidation;
using FluentValidation.Results;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
@ -50,15 +52,15 @@ protected RestController()
[RestGetById]
[Produces("application/json")]
public virtual ActionResult<TResource> GetResourceByIdWithErrorHandler(int id)
public virtual Results<Ok<TResource>, NotFound> GetResourceByIdWithErrorHandler(int id)
{
try
{
return GetResourceById(id);
return TypedResults.Ok(GetResourceById(id));
}
catch (ModelNotFoundException)
{
return NotFound();
return TypedResults.NotFound();
}
}
@ -156,6 +158,20 @@ protected void ValidateResource(TResource resource, bool validateId = false, boo
}
}
protected Results<Accepted<TResource>, NotFound> TypedAccepted(int id)
{
var result = GetResourceById(id);
return TypedResults.Accepted(Url.Action(nameof(GetResourceByIdWithErrorHandler), new { id }), result);
}
protected Results<Created<TResource>, NotFound> TypedCreated(int id)
{
var result = GetResourceById(id);
return TypedResults.Created(Url.Action(nameof(GetResourceByIdWithErrorHandler), new { id }), result);
}
protected ActionResult<TResource> Accepted(int id)
{
var result = GetResourceById(id);