private static bool HasInvalidParameters(SearchRequest request, string packageType)
 {
     // Requests with bad parameters yield no results. For the package type case, by specification a package type
     // valid characters are the same as a package ID.
     return(request.Skip > MaximumSkip ||
            (packageType != null && !PackageIdValidator.IsValidPackageId(packageType)));
 }
示例#2
0
        public Task <bool> CanInstallAsync(InstallRequest installationRequest, CancellationToken cancellationToken)
        {
            try
            {
                ReadPackageInformation(installationRequest.PackageIdentifier);
            }
            catch (Exception)
            {
                _logger.LogDebug($"{installationRequest.PackageIdentifier} is not a local NuGet package.");

                //check if identifier is a valid package ID
                bool validPackageId = PackageIdValidator.IsValidPackageId(installationRequest.PackageIdentifier);
                //check if version is specified it is correct version
                bool hasValidVersion = NuGetVersionHelper.IsSupportedVersionString(installationRequest.Version);
                if (!validPackageId)
                {
                    _logger.LogDebug($"{installationRequest.PackageIdentifier} is not a valid NuGet package ID.");
                }
                if (!hasValidVersion)
                {
                    _logger.LogDebug($"{installationRequest.Version} is not a valid NuGet package version.");
                }
                if (validPackageId && hasValidVersion)
                {
                    _logger.LogDebug($"{installationRequest.DisplayName} is identified as the downloadable NuGet package.");
                }

                //not a local package file
                return(Task.FromResult(validPackageId && hasValidVersion));
            }
            _logger.LogDebug($"{installationRequest.PackageIdentifier} is identified as the local NuGet package.");
            return(Task.FromResult(true));
        }
示例#3
0
        private string IsValid(string columnName)
        {
            if (columnName == "Id")
            {
                if (string.IsNullOrEmpty(Id))
                {
                    return(VersionSpec != null ? "Package id must not be empty." : null);
                }

                if (!PackageIdValidator.IsValidPackageId(Id))
                {
                    return("'" + Id + "' is an invalid package id.");
                }

                var activeDependencySet = _getActiveDependencySet();
                if (activeDependencySet != null)
                {
                    if (activeDependencySet.Dependencies.Any(p => p.Id.Equals(Id, StringComparison.OrdinalIgnoreCase)))
                    {
                        return("This id already exists in the same dependency group.");
                    }
                }
            }

            return(null);
        }
        public Task <bool> CanInstallAsync(InstallRequest installationRequest, CancellationToken cancellationToken)
        {
            try
            {
                ReadPackageInformation(installationRequest.PackageIdentifier);
            }
            catch (Exception)
            {
                _environmentSettings.Host.LogDiagnosticMessage($"{installationRequest.PackageIdentifier} is not a local NuGet package.", DebugLogCategory);

                //check if identifier is a valid package ID
                bool validPackageId = PackageIdValidator.IsValidPackageId(installationRequest.PackageIdentifier);
                //check if version is specified it is correct version
                bool hasValidVersion = string.IsNullOrWhiteSpace(installationRequest.Version) || NuGetVersion.TryParse(installationRequest.Version, out _);
                if (!validPackageId)
                {
                    _environmentSettings.Host.LogDiagnosticMessage($"{installationRequest.PackageIdentifier} is not a valid NuGet package ID.", DebugLogCategory);
                }
                if (!hasValidVersion)
                {
                    _environmentSettings.Host.LogDiagnosticMessage($"{installationRequest.Version} is not a valid NuGet package version.", DebugLogCategory);
                }
                if (validPackageId && hasValidVersion)
                {
                    _environmentSettings.Host.LogDiagnosticMessage($"{installationRequest.DisplayName} is identified as the downloadable NuGet package.", DebugLogCategory);
                }

                //not a local package file
                return(Task.FromResult(validPackageId && hasValidVersion));
            }
            _environmentSettings.Host.LogDiagnosticMessage($"{installationRequest.PackageIdentifier} is identified as the local NuGet package.", DebugLogCategory);
            return(Task.FromResult(true));
        }
示例#5
0
 private void ValidateBundleId(string id)
 {
     if (string.IsNullOrWhiteSpace(id) || !PackageIdValidator.IsValidPackageId(id))
     {
         string message = string.Format(Resources.ExtensionBundleConfigMissingId, ScriptConstants.HostMetadataFileName);
         throw new ArgumentException(message);
     }
 }
示例#6
0
        public void NullThrowsException()
        {
            // Arrange
            string packageId = null;

            // Act & Assert
            ExceptionAssert.ThrowsArgNull(() => PackageIdValidator.IsValidPackageId(packageId), "packageId");
        }
        public void NullThrowsException()
        {
            // Arrange
            string packageId = null;

            // Act & Assert
            Assert.Throws <ArgumentNullException>(paramName: "packageId",
                                                  testCode: () => PackageIdValidator.IsValidPackageId(packageId));
        }
        public void AlphaNumericIsValid()
        {
            // Arrange
            string packageId = "42This1Is4You";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void EndingWithSeparatorsNotAllowed()
        {
            // Arrange
            string packageId = "StartWithSeparator.";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void UnderscoreDotAndDashSeparatorsAreValid()
        {
            // Arrange
            string packageId = "Nu_Get.Core-IsCool";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void EmptyIsNotValid()
        {
            // Arrange
            string packageId = "";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
示例#12
0
        public void IsValidPackageId_LongPackageIdWithUnMatchedCharAtTheEnd_Fails()
        {
            // Arrange
            string packageId = string.Concat(new string('_', 100), "!");

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
示例#13
0
        public void IsValidPackageId_PackageIdWithTwoUnderscores_Success()
        {
            // Arrange
            string packageId = "Hello__World";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void NonAlphaNumericUnderscoreDotDashIsInvalid()
        {
            // Arrange
            string packageId = "ILike*Asterisks";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void ConsecutiveSeparatorsNotAllowed()
        {
            // Arrange
            string packageId = "I_.Like.-Separators";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
        public void DotToolsIsNotAllowed()
        {
            // Arrange
            string packageId = ".tools";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.False(isValid);
        }
示例#17
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            // if version is non-null, check if it's semantically correct and normalize it.
            if (!String.IsNullOrEmpty(version))
            {
                NuGetVersion dummy;
                if (!NuGetVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
                // Normalize the version
                version = NuGetVersionNormalizer.Normalize(version);
            }
            else
            {
                // if version is null, get the latest version from the database.
                // This ensures that on package restore scenario where version will be non null, we don't hit the database.
                try
                {
                    var package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                    if (package == null)
                    {
                        return(new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                    }
                    version = package.NormalizedVersion;
                }
                catch (SqlException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
                catch (DataException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
            }

            return(await PackageFileService.CreateDownloadPackageActionResultAsync(
                       HttpContext.Request.Url,
                       id, version));
        }
        public void NumbersAndWordsDotSeparatedAllowd()
        {
            // Arrange
            string packageId = "1.2.3.4.Uno.Dos.Tres.Cuatro";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        public void MultipleDotSeparatorsAllowed()
        {
            // Arrange
            string packageId = "I.Like.Writing.Unit.Tests";

            // Act
            bool isValid = PackageIdValidator.IsValidPackageId(packageId);

            // Assert
            Assert.True(isValid);
        }
        private string IsValid(string columnName)
        {
            if (columnName == "Id")
            {
                if (String.IsNullOrEmpty(Id))
                {
                    return(null);
                }

                if (!PackageIdValidator.IsValidPackageId(Id))
                {
                    return("Value '" + Id + "' cannot be converted.");
                }
            }

            return(null);
        }
        public async Task <bool> DoesPackageIdExistAsync(
            string packageIdPattern,
            SearchScorerSettings settings)
        {
            Task <bool> controlExistsTask;
            Task <bool> treatmentExistsTask;

            if (PackageIdValidator.IsValidPackageId(packageIdPattern))
            {
                var query = $"packageid:{packageIdPattern}";
                controlExistsTask   = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.ControlBaseUrl, query, take: 1);
                treatmentExistsTask = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.TreatmentBaseUrl, query, take: 1);
            }
            else if (packageIdPattern.EndsWith("*"))
            {
                var prefix = packageIdPattern.Substring(0, packageIdPattern.Length - 1).TrimEnd(Separators);
                if (!PackageIdValidator.IsValidPackageId(prefix))
                {
                    throw new ArgumentException($"The package ID '{packageIdPattern}' looks like a pattern but the part before the wildcard is not a valid package ID.");
                }

                var pieces = prefix
                             .Split(Separators)
                             .Where(x => !string.IsNullOrWhiteSpace(x));
                var query = string.Join(" ", pieces);
                controlExistsTask   = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.ControlBaseUrl, query, take: 1000);
                treatmentExistsTask = DoesPackageIdExistInQueryAsync(packageIdPattern, settings.TreatmentBaseUrl, query, take: 1000);
            }
            else
            {
                throw new NotSupportedException();
            }

            await Task.WhenAll(controlExistsTask, treatmentExistsTask);

            if (controlExistsTask.Result != treatmentExistsTask.Result)
            {
                throw new ArgumentNullException(
                          $"The package ID '{packageIdPattern}' has inconsistent availability. " +
                          $"Exists in control: {controlExistsTask.Result}. " +
                          $"Exists in treatment: {treatmentExistsTask.Result}.");
            }

            return(controlExistsTask.Result);
        }
        private bool TryGetSinglePackageId(
            ParsedQuery parsed,
            out string packageId)
        {
            if (parsed.Grouping.TryGetValue(QueryField.PackageId, out var terms) &&
                terms.Count == 1)
            {
                packageId = terms.First();
                if (packageId.Length <= PackageIdValidator.MaxPackageIdLength &&
                    PackageIdValidator.IsValidPackageId(packageId))
                {
                    return(true);
                }
            }

            packageId = null;
            return(false);
        }
        bool IsValidId()
        {
            IdError = null;

            if (string.IsNullOrEmpty(id))
            {
                return(false);
            }
            else if (id.Length > NuGetPackageMetadata.MaxPackageIdLength)
            {
                IdError = GettextCatalog.GetString("The package id must not exceed 100 characters.");
                return(false);
            }
            else if (!PackageIdValidator.IsValidPackageId(id))
            {
                IdError = GettextCatalog.GetString("The package id contains invalid characters. Examples of valid package ids include 'MyPackage' and 'MyPackage.Sample'.");
                return(false);
            }

            return(true);
        }
        bool IsValidLibraryName()
        {
            LibraryNameError = null;

            if (string.IsNullOrEmpty(libraryName))
            {
                return(false);
            }
            else if (libraryName.Length > NuGetPackageMetadata.MaxPackageIdLength)
            {
                LibraryNameError = GettextCatalog.GetString("Library name must not exceed 100 characters.");
                return(false);
            }
            else if (!PackageIdValidator.IsValidPackageId(libraryName))
            {
                LibraryNameError = GettextCatalog.GetString("The library name contains invalid characters. Examples of valid library names include 'MyPackage' and 'MyPackage.Sample'.");
                return(false);
            }

            return(true);
        }
        private void ApplySearchIndexFilter(
            SearchParameters searchParameters,
            SearchRequest request,
            bool excludePackagesHiddenByDefault,
            string packageType)
        {
            var searchFilters = GetSearchFilters(request);

            var filterString = $"{IndexFields.Search.SearchFilters} eq '{DocumentUtilities.GetSearchFilterString(searchFilters)}'";

            if (excludePackagesHiddenByDefault)
            {
                filterString += $" and ({IndexFields.Search.IsExcludedByDefault} eq false or {IndexFields.Search.IsExcludedByDefault} eq null)";
            }

            // Verify that the package type only has valid package ID characters so we don't need to worry about
            // escaping quotes and such.
            if (packageType != null && PackageIdValidator.IsValidPackageId(packageType))
            {
                filterString += $" and {IndexFields.Search.FilterablePackageTypes}/any(p: p eq '{packageType.ToLowerInvariant()}')";
            }

            searchParameters.Filter = filterString;
        }
示例#26
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            if (!String.IsNullOrEmpty(version))
            {
                SemanticVersion dummy;
                if (!SemanticVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
            }

            // if the version is null, the user is asking for the latest version. Presumably they don't want includePrerelease release versions.
            // The allow prerelease flag is ignored if both partialId and version are specified.
            // In general we want to try to add download statistics for any package regardless of whether a version was specified.
            try
            {
                Package package = _packageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                if (package == null)
                {
                    return(new HttpStatusCodeWithBodyResult(
                               HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                }

                try
                {
                    _packageService.AddDownloadStatistics(
                        package,
                        Request.UserHostAddress,
                        Request.UserAgent,
                        Request.Headers["NuGet-Operation"]);
                }
                catch (ReadOnlyModeException)
                {
                    // *gulp* Swallowed. It's OK not to add statistics and ok to not log errors in read only mode.
                }
                catch (SqlException e)
                {
                    // Log the error and continue
                    QuietlyLogException(e);
                }
                catch (DataException e)
                {
                    // Log the error and continue
                    QuietlyLogException(e);
                }

                return(await _packageFileService.CreateDownloadPackageActionResultAsync(HttpContext.Request.Url, package));
            }
            catch (SqlException e)
            {
                QuietlyLogException(e);
            }
            catch (DataException e)
            {
                QuietlyLogException(e);
            }

            // Fall back to constructing the URL based on the package version and ID.

            return(await _packageFileService.CreateDownloadPackageActionResultAsync(HttpContext.Request.Url, id, version));
        }
示例#27
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            // if version is non-null, check if it's semantically correct and normalize it.
            if (!String.IsNullOrEmpty(version))
            {
                NuGetVersion dummy;
                if (!NuGetVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
                // Normalize the version
                version = NuGetVersionNormalizer.Normalize(version);
            }
            else
            {
                // if version is null, get the latest version from the database.
                // This ensures that on package restore scenario where version will be non null, we don't hit the database.
                try
                {
                    var package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                    if (package == null)
                    {
                        return(new HttpStatusCodeWithBodyResult(HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                    }
                    version = package.NormalizedVersion;
                }
                catch (SqlException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
                catch (DataException e)
                {
                    QuietLog.LogHandledException(e);

                    // Database was unavailable and we don't have a version, return a 503
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
                }
            }

            // If metrics service is specified we post the data to it asynchronously. Else we skip stats.
            if (_config != null && _config.MetricsServiceUri != null)
            {
                try
                {
                    var userHostAddress  = Request.UserHostAddress;
                    var userAgent        = Request.UserAgent;
                    var operation        = Request.Headers["NuGet-Operation"];
                    var dependentPackage = Request.Headers["NuGet-DependentPackage"];
                    var projectGuids     = Request.Headers["NuGet-ProjectGuids"];

                    HostingEnvironment.QueueBackgroundWorkItem(cancellationToken => PostDownloadStatistics(id, version, userHostAddress, userAgent, operation, dependentPackage, projectGuids, cancellationToken));
                }
                catch (Exception ex)
                {
                    QuietLog.LogHandledException(ex);
                }
            }

            return(await PackageFileService.CreateDownloadPackageActionResultAsync(
                       HttpContext.Request.Url,
                       id, version));
        }
示例#28
0
 private static bool IsId(string query)
 {
     return(query.Length <= PackageIdValidator.MaxPackageIdLength &&
            PackageIdValidator.IsValidPackageId(query));
 }
示例#29
0
        private void CleanDownloadData(DownloadData data)
        {
            var invalidIdCount            = 0;
            var invalidVersionCount       = 0;
            var nonNormalizedVersionCount = 0;

            foreach (var id in data.Keys.ToList())
            {
                var isValidId = id.Length <= PackageIdValidator.MaxPackageIdLength && PackageIdValidator.IsValidPackageId(id);
                if (!isValidId)
                {
                    invalidIdCount++;
                }

                foreach (var version in data[id].Keys.ToList())
                {
                    var isValidVersion = NuGetVersion.TryParse(version, out var parsedVersion);
                    if (!isValidVersion)
                    {
                        invalidVersionCount++;
                    }

                    if (!isValidId || !isValidVersion)
                    {
                        // Clear the download count if the ID or version is invalid.
                        data.SetDownloadCount(id, version, 0);
                        continue;
                    }

                    var normalizedVersion   = parsedVersion.ToNormalizedString();
                    var isNormalizedVersion = StringComparer.OrdinalIgnoreCase.Equals(version, normalizedVersion);

                    if (!isNormalizedVersion)
                    {
                        nonNormalizedVersionCount++;

                        // Use the normalized version string if the original was not normalized.
                        var downloads = data.GetDownloadCount(id, version);
                        data.SetDownloadCount(id, version, 0);
                        data.SetDownloadCount(id, normalizedVersion, downloads);
                    }
                }
            }

            _logger.LogInformation(
                "There were {InvalidIdCount} invalid IDs, {InvalidVersionCount} invalid versions, and " +
                "{NonNormalizedVersionCount} non-normalized IDs.",
                invalidIdCount,
                invalidVersionCount,
                nonNormalizedVersionCount);
        }
示例#30
0
        public virtual async Task <ActionResult> GetPackage(string id, string version)
        {
            // some security paranoia about URL hacking somehow creating e.g. open redirects
            // validate user input: explicit calls to the same validators used during Package Registrations
            // Ideally shouldn't be necessary?
            if (!PackageIdValidator.IsValidPackageId(id ?? ""))
            {
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The format of the package id is invalid"));
            }

            if (!String.IsNullOrEmpty(version))
            {
                SemanticVersion dummy;
                if (!SemanticVersion.TryParse(version, out dummy))
                {
                    return(new HttpStatusCodeWithBodyResult(HttpStatusCode.BadRequest, "The package version is not a valid semantic version"));
                }
            }

            // Normalize the version
            version = SemanticVersionExtensions.Normalize(version);

            // if the version is null, the user is asking for the latest version. Presumably they don't want includePrerelease release versions.
            // The allow prerelease flag is ignored if both partialId and version are specified.
            // In general we want to try to add download statistics for any package regardless of whether a version was specified.

            Package package = null;

            try
            {
                package = PackageService.FindPackageByIdAndVersion(id, version, allowPrerelease: false);
                if (package == null)
                {
                    return(new HttpStatusCodeWithBodyResult(
                               HttpStatusCode.NotFound, String.Format(CultureInfo.CurrentCulture, Strings.PackageWithIdAndVersionNotFound, id, version)));
                }

                try
                {
                    var stats = new PackageStatistics
                    {
                        // IMPORTANT: Timestamp is managed by the database.
                        IPAddress        = Request.UserHostAddress,
                        UserAgent        = Request.UserAgent,
                        Package          = package,
                        Operation        = Request.Headers["NuGet-Operation"],
                        DependentPackage = Request.Headers["NuGet-DependentPackage"],
                        ProjectGuids     = Request.Headers["NuGet-ProjectGuids"],
                    };

                    PackageService.AddDownloadStatistics(stats);
                }
                catch (ReadOnlyModeException)
                {
                    // *gulp* Swallowed. It's OK not to add statistics and ok to not log errors in read only mode.
                }
                catch (SqlException e)
                {
                    // Log the error and continue
                    QuietLog.LogHandledException(e);
                }
                catch (DataException e)
                {
                    // Log the error and continue
                    QuietLog.LogHandledException(e);
                }
            }
            catch (SqlException e)
            {
                QuietLog.LogHandledException(e);
            }
            catch (DataException e)
            {
                QuietLog.LogHandledException(e);
            }

            // Fall back to constructing the URL based on the package version and ID.
            if (String.IsNullOrEmpty(version) && package == null)
            {
                // Database was unavailable and we don't have a version, return a 503
                return(new HttpStatusCodeWithBodyResult(HttpStatusCode.ServiceUnavailable, Strings.DatabaseUnavailable_TrySpecificVersion));
            }
            return(await PackageFileService.CreateDownloadPackageActionResultAsync(
                       HttpContext.Request.Url,
                       id,
                       String.IsNullOrEmpty(version)?package.NormalizedVersion : version));
        }