Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.
If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!
ProGet 2025.10: License Update API Issues
-
ProGet: 2025.10
Inedo.Proget: 2.0.5The Update License API does not update the database in all cases.
For example just updating the title via a partial object (which is supposed to be supported according to docs?) never seems to update the database, even though the call always succeeds.
await _progetClient.UpdateLicenseAsync(new LicenseInfo { Id = 59, Code = "CC-BY-1.0", Title = "Test" });
I've had some success with updating the
Urls
andPackageNames
properties, but even these calls are not always immediately reflected in the database or the UI. Sometimes it feels like the changes only get persisted after clicking around in the UI a bit, but that could just be coincidence. Rarely it is visible directly after the API call.I've also tried retrieving the full LicenseInfo object from the database, and using a modified clone of the object with the Update API, but this has also flaky behavior and the title update also never works.
Am I doing something wrong or is there a glitch in the update API?
-
It appears the
AddLicenseAsync()
API also has issues:- Spdx is sometimes modified, sometimes not set at all
- PUrl is not set
- PackageNames is not set
-
Hi @jw ,
I'm not able to reproduce any issues on my end; I'm not entirely sure how you're testing, but let me share with you the code on the server side in ProGet:
private static async Task UpdateLicenseAsync(AhHttpContext context, LoggedResponseStream output, WebApiContext apiContext) { EnsureMethod(context, "POST"); EnsureCanManageLicenses(apiContext); var input = await JsonSerializer.DeserializeAsync(context.Request.InputStream, LicenseApiJsonContext.Default.LicenseInfo, context.CancellationToken) ?? throw new HttpException(400, "Expected license object."); var license = await DB.Licenses_GetLicenseAsync(External_Id: input.Code) ?? throw new HttpException(404, "License not found."); List<int>? nameIds = null; if (input.PackageNames?.Count > 0) { nameIds = []; foreach (var n in input.PackageNames) { if (!PackageNameId.TryParse(n, out var nameId)) throw new HttpException(400, $"Invalid package name: {n}"); nameIds.Add((await nameId.EnsureDatabaseIdAsync()).Id!.Value); } } List<int>? versionIds = null; if (input.Purls?.Count > 0) { versionIds = []; foreach (var v in input.Purls) { if (!PUrl.TryParse(v, out var purl)) throw new HttpException(400, $"Invalid purl: {v}"); versionIds.Add((await ((PackageVersionId)purl).EnsureDatabaseIdAsync()).Id!.Value); } } await DB.Licenses_UpdateLicenseDataAsync( License_Id: license.License_Id, PackageVersionIds_Csv: versionIds?.Count > 0 ? string.Join(',', versionIds) : null, PackageNameIds_Csv: nameIds?.Count > 0 ? string.Join(',', nameIds) : null, SpdxIds_Csv: input.Spdx?.Count > 0 ? string.Join(',', input.Spdx) : null, Urls_Csv: input.Urls?.Count > 0 ? string.Join(',', input.Urls) : null ); }
I'm not sure if that's helpful, but if not... can you put a specific reproduction case?
Also note that the license data in the UI is cached, but it's invalidated when you visit the
/licenses
page and others.Thanks,
Steve
-
Hi @stevedennis
the code seems to explain at least half of the problems I ran into
- It is not possible to update the
Title
property ofLicenseInfo
, it is never passed to the DB - It is not possible to update the
Code
property ofLicenseInfo
, it is never passed to the DB - Partial updates might not be possible, that depends on how
DB.Licenses_UpdateLicenseDataAsync
handles null values
At least the code shown here does not differentiate between supplying null or an empty list.
True partial updates would be something like- Null => Do not change the db
- Empty list => Clear the field in the db
- Filled list => Overwrite the field in the db
Given that the properties in the
LicenseInfo
objects are nullable, the code shown here doesn't quite match the intention of partial updates. At least not how it is described in the docsThis endpoint supports partial updating by only updating the properties that are supplied in the request.
- It is not possible to update the