From f5aa2bad57de536068dd530de536117be4548d7a Mon Sep 17 00:00:00 2001
From: Joel Verhagen <jver@microsoft.com>
Date: Fri, 15 Dec 2017 10:50:35 -0800
Subject: [PATCH] Support projection on the Packages() endpoint ($select) (#46)

Fix https://github.com/NuGet/NuGetGallery/issues/5193
---
 .../Controllers/NuGetODataController.cs       |  3 --
 test/NuGet.Server.Tests/IntegrationTests.cs   | 34 +++++++++++++++++++
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/src/NuGet.Server.V2/Controllers/NuGetODataController.cs b/src/NuGet.Server.V2/Controllers/NuGetODataController.cs
index 61b74edc..f7ce0dbd 100644
--- a/src/NuGet.Server.V2/Controllers/NuGetODataController.cs
+++ b/src/NuGet.Server.V2/Controllers/NuGetODataController.cs
@@ -45,10 +45,7 @@ protected NuGetODataController(
         }
         
         // GET /Packages
-        // Never seen this invoked. NuGet.Exe and Visual Studio seems to use 'Search' for all package listing.
-        // Probably required to be OData compliant?
         [HttpGet]
-        [EnableQuery(PageSize = 100, HandleNullPropagation = HandleNullPropagationOption.False)]
         public virtual async Task<IHttpActionResult> Get(
             ODataQueryOptions<ODataPackage> options,
             [FromUri] string semVerLevel = "",
diff --git a/test/NuGet.Server.Tests/IntegrationTests.cs b/test/NuGet.Server.Tests/IntegrationTests.cs
index 477ce908..5297d021 100644
--- a/test/NuGet.Server.Tests/IntegrationTests.cs
+++ b/test/NuGet.Server.Tests/IntegrationTests.cs
@@ -98,6 +98,40 @@ public async Task PushPackageThenReadPackages()
             }
         }
 
+        [Theory]
+        [MemberData(nameof(EndpointsSupportingProjection))]
+        public async Task CanQueryUsingProjection(string endpoint)
+        {
+            // Arrange
+            using (var tc = new TestContext())
+            {
+                var packagePath = Path.Combine(tc.PackagesDirectory, "package.nupkg");
+                TestData.CopyResourceToPath(TestData.PackageResource, packagePath);
+
+                // Act
+                using (var request = new HttpRequestMessage(HttpMethod.Get, $"/nuget/{endpoint}$select=Id,Version"))
+                using (var response = await tc.Client.SendAsync(request))
+                {
+                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+                    var content = await response.Content.ReadAsStringAsync();
+
+                    // Assert
+                    Assert.Contains(TestData.PackageId, content);
+                    Assert.Contains(TestData.PackageVersionString, content);
+                }
+            }
+        }
+
+        public static IEnumerable<object[]> EndpointsSupportingProjection
+        {
+            get
+            {
+                yield return new object[] { "Packages()?" };
+                yield return new object[] { "Search()?searchTerm=''&targetFramework=''&includePrerelease=true&includeDelisted=true&" };
+                yield return new object[] { $"FindPackagesById()?id='{TestData.PackageId}'&" };
+            }
+        }
+
         private sealed class TestContext : IDisposable
         {
             private readonly HttpServer _server;