From 309ad74ad29445a24a98b760e20274355cdbe5ae Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Thu, 23 Jun 2022 15:48:08 -0500 Subject: [PATCH 01/14] Added abiilty to checkout a component to an asset --- SnipeSharp/EndPoint/ComponentEndPoint.cs | 22 ++++++++++- SnipeSharp/Models/ComponentCheckOut.cs | 36 +++++++++++++++++ .../ComponentCheckOutRequest.cs | 39 +++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 SnipeSharp/Models/ComponentCheckOut.cs create mode 100644 SnipeSharp/Models/OnlySubmittable/ComponentCheckOutRequest.cs diff --git a/SnipeSharp/EndPoint/ComponentEndPoint.cs b/SnipeSharp/EndPoint/ComponentEndPoint.cs index 9661474..d523b1b 100644 --- a/SnipeSharp/EndPoint/ComponentEndPoint.cs +++ b/SnipeSharp/EndPoint/ComponentEndPoint.cs @@ -9,7 +9,7 @@ public sealed class ComponentEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal ComponentEndPoint(SnipeItApi api) : base(api) {} + internal ComponentEndPoint(SnipeItApi api) : base(api) { } /// /// Get the list of component assignees for a component. @@ -18,5 +18,25 @@ internal ComponentEndPoint(SnipeItApi api) : base(api) {} /// A ResponseCollection list of ComponentAssignees. public ResponseCollection GetAssignedAssets(Component component) => Api.RequestManager.GetAll($"{EndPointInfo.BaseUri}/{component.Id}/assets").RethrowExceptionIfAny().Value; + + /// + /// Check out an accessory. + /// + /// An accessory check-out request. + /// + public RequestResponse CheckOut(ComponentCheckOutRequest request) + => Api.RequestManager.Post($"{EndPointInfo.BaseUri}/{request.Component.Id}/checkout", request).RethrowExceptionIfAny().Value; + + + /// + /// Check out a component. + /// + /// The accessory to check out. + /// The user to check out to. + /// /// How many components should be assigned to the asset. + /// An optional note for the checkout log. + /// + public RequestResponse CheckOut(Component component, Asset assignedAsset, int quantity, string note = null) + => CheckOut(new ComponentCheckOutRequest(component, assignedAsset, quantity) { Note = note }); } } diff --git a/SnipeSharp/Models/ComponentCheckOut.cs b/SnipeSharp/Models/ComponentCheckOut.cs new file mode 100644 index 0000000..e808fb1 --- /dev/null +++ b/SnipeSharp/Models/ComponentCheckOut.cs @@ -0,0 +1,36 @@ +using SnipeSharp.Serialization; +using SnipeSharp.Models.Enumerations; + +namespace SnipeSharp.Models +{ + /// + /// A Componenet/Asset relation. + /// + public sealed class ComponentCheckOut : ApiObject, IAvailableActions + { + /// + /// The Id of the Component in Snipe-IT. + /// + [DeserializeAs("assigned_pivot_id")] + public int ComponentId { get; private set; } + + /// + /// The Id of the User in Snipe-IT. + /// + [DeserializeAs("id")] + public int AssetId { get; private set; } + + + /// + /// The assignee type of this particular check out. + /// + /// Currently, this field will always be Asset. + [DeserializeAs("type")] + public AssignedToType Type { get; private set; } + + /// + /// Currently, this will always be {CheckIn}. + [DeserializeAs("available_actions", DeserializeAs.AvailableActions)] + public AvailableAction AvailableActions { get; private set; } + } +} diff --git a/SnipeSharp/Models/OnlySubmittable/ComponentCheckOutRequest.cs b/SnipeSharp/Models/OnlySubmittable/ComponentCheckOutRequest.cs new file mode 100644 index 0000000..af64c11 --- /dev/null +++ b/SnipeSharp/Models/OnlySubmittable/ComponentCheckOutRequest.cs @@ -0,0 +1,39 @@ +using SnipeSharp.Serialization; + +namespace SnipeSharp.Models +{ + /// + /// A request to associate an Accessory with a User. + /// + public sealed class ComponentCheckOutRequest : ApiObject + { + /// The Accessory that will be checked out. + /// This property is not serialized, but instead used for its Id value. + public Component Component { get; private set; } + + /// The assigned user. + [SerializeAs("assigned_to", SerializeAs.IdValue)] + public Asset AssignedAsset { get; private set; } + + /// The note to put in the log for this check-out event. + [SerializeAs("note")] + public string Note { get; set; } + + ///How many to assign + [SerializeAs("assigned_qty")] + public int Quantity { get; set; } + + /// + /// Begins a new ComponentCheckOutRequest assigning the supplied component to the supplied asset. + /// + /// The accessory to assign. + /// The User to assign the accessory to. + /// How many components to assign to the asset + public ComponentCheckOutRequest(Component component, Asset asset, int quantity) + { + Component = component; + AssignedAsset = asset; + Quantity = quantity; + } + } +} From 5e6339a22eb761be9df02597c674936175d614db Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Wed, 15 Mar 2023 16:25:16 -0500 Subject: [PATCH 02/14] To many changes to count. Everything seems to be working though. Updates to database models Addition of Meraki searching - currently broken --- SnipeSharp/ApiOptionalMultiResponse.cs | 4 +- SnipeSharp/ApiOptionalResponse.cs | 4 +- .../Collections/CustomFieldDictionary.cs | 61 +++++++------- SnipeSharp/EndPoint/AccessoryEndPoint.cs | 6 +- SnipeSharp/EndPoint/AssetEndPoint.cs | 7 +- SnipeSharp/EndPoint/CustomFieldEndPoint.cs | 9 ++- SnipeSharp/EndPoint/EndPoint.cs | 24 +++--- SnipeSharp/EndPoint/FieldSetEndPoint.cs | 2 +- SnipeSharp/EndPoint/IEndPoint.cs | 6 +- SnipeSharp/EndPoint/LicenseEndPoint.cs | 6 +- SnipeSharp/EndPoint/StatusLabelEndPoint.cs | 10 +-- SnipeSharp/EndPoint/UserEndPoint.cs | 18 ++--- SnipeSharp/Exceptions/ApiErrorException.cs | 17 ++-- ...edInsufficientValuesForRequestException.cs | 2 +- .../MissingRequiredAttributeException.cs | 2 +- .../MissingRequiredFieldException.cs | 6 +- .../Exceptions/NullApiTokenException.cs | 2 +- SnipeSharp/Exceptions/NullApiUriException.cs | 2 +- .../Filters/AbstractAssetSearchFilter.cs | 2 +- SnipeSharp/Filters/AccessorySearchFilter.cs | 2 +- SnipeSharp/Filters/AssetSearchColumn.cs | 5 +- SnipeSharp/Filters/AssetSearchFilter.cs | 5 +- SnipeSharp/Filters/CustomAssetSearchFilter.cs | 4 +- SnipeSharp/Filters/ISortableSearchFilter.cs | 2 +- SnipeSharp/Filters/LicenseSeatSearchFilter.cs | 2 +- .../Filters/RequestableAssetSearchColumn.cs | 2 +- .../Filters/RequestableAssetSearchFilter.cs | 9 ++- SnipeSharp/Filters/SearchFilter.cs | 18 ++--- SnipeSharp/Filters/UserSearchFilter.cs | 2 +- SnipeSharp/Models/AbstractBaseModel.cs | 4 +- SnipeSharp/Models/AccessoryCheckOut.cs | 4 +- SnipeSharp/Models/AssetAssignedTo.cs | 16 ++-- SnipeSharp/Models/AssetCustomField.cs | 2 +- SnipeSharp/Models/AssetStatus.cs | 4 +- SnipeSharp/Models/ComponentAsset.cs | 4 +- SnipeSharp/Models/ComponentCheckOut.cs | 4 +- .../Models/Enumerations/MaintenanceType.cs | 2 +- SnipeSharp/Models/GenericEndPointModel.cs | 2 +- SnipeSharp/Models/IAvailableActions.cs | 1 - SnipeSharp/Models/LicenseSeat.cs | 2 +- .../OnlySubmittable/AssetCheckOutRequest.cs | 6 +- .../OnlySubmittable/CustomFieldAssociation.cs | 5 +- SnipeSharp/Models/Request.cs | 2 +- SnipeSharp/Models/RequestResponse.cs | 17 ++-- SnipeSharp/Models/RequestableAsset.cs | 2 +- SnipeSharp/Models/ResponseCollection.cs | 8 +- SnipeSharp/Models/SelfUser.cs | 2 +- SnipeSharp/Models/Stub.cs | 2 +- SnipeSharp/Models/Submittable/Accessory.cs | 4 +- SnipeSharp/Models/Submittable/Asset.cs | 30 +++---- SnipeSharp/Models/Submittable/AssetAudit.cs | 2 +- SnipeSharp/Models/Submittable/Category.cs | 6 +- SnipeSharp/Models/Submittable/Company.cs | 4 +- SnipeSharp/Models/Submittable/Component.cs | 4 +- SnipeSharp/Models/Submittable/Consumable.cs | 4 +- SnipeSharp/Models/Submittable/CustomField.cs | 8 +- SnipeSharp/Models/Submittable/Department.cs | 4 +- SnipeSharp/Models/Submittable/Depreciation.cs | 2 +- SnipeSharp/Models/Submittable/FieldSet.cs | 4 +- SnipeSharp/Models/Submittable/Group.cs | 4 +- SnipeSharp/Models/Submittable/License.cs | 4 +- SnipeSharp/Models/Submittable/Location.cs | 6 +- SnipeSharp/Models/Submittable/Maintenance.cs | 4 +- SnipeSharp/Models/Submittable/Manufacturer.cs | 4 +- SnipeSharp/Models/Submittable/Model.cs | 6 +- SnipeSharp/Models/Submittable/StatusLabel.cs | 8 +- SnipeSharp/Models/Submittable/Supplier.cs | 4 +- SnipeSharp/Models/Submittable/User.cs | 9 ++- SnipeSharp/Properties/AssemblyInfo.cs | 2 +- SnipeSharp/RestClientManager.cs | 81 ++++++++++--------- .../Converters/AvailableActionsConverter.cs | 10 +-- .../CustomFieldDictionaryConverter.cs | 13 +-- .../Converters/DateObjectConverter.cs | 14 +++- .../Converters/MaybeFalseUriConverter.cs | 6 +- .../Converters/MonthStringToIntConverter.cs | 4 +- .../Converters/NullableBooleanConverter.cs | 4 +- .../PermissionDictionaryConverter.cs | 6 +- .../ReadOnlyResponseCollectionConverter.cs | 6 +- .../Converters/SerializeToIdArrayConverter.cs | 8 +- .../Converters/SerializeToIdConverter.cs | 4 +- .../Converters/SimpleDateConverter.cs | 6 +- .../Converters/TimeSpanConverter.cs | 6 +- .../Converters/TimestampConverter.cs | 16 +++- .../DeserializationContractResolver.cs | 11 +-- .../Serialization/DeserializeAsAttribute.cs | 2 +- .../Serialization/NewtonsoftJsonSerializer.cs | 8 +- .../SerializationContractResolver.cs | 17 ++-- .../Serialization/SerializeAsAttribute.cs | 2 +- SnipeSharp/SnipeItApi.cs | 11 +-- SnipeSharp/SnipeSharp.csproj | 2 +- 90 files changed, 363 insertions(+), 327 deletions(-) diff --git a/SnipeSharp/ApiOptionalMultiResponse.cs b/SnipeSharp/ApiOptionalMultiResponse.cs index 8c69dca..d68818c 100644 --- a/SnipeSharp/ApiOptionalMultiResponse.cs +++ b/SnipeSharp/ApiOptionalMultiResponse.cs @@ -1,6 +1,6 @@ +using SnipeSharp.Models; using System; using System.Runtime.ExceptionServices; -using SnipeSharp.Models; namespace SnipeSharp { @@ -32,7 +32,7 @@ public bool HasValue /// This same response. public ApiOptionalMultiResponse RethrowExceptionIfAny() { - if(null != Exception) + if (null != Exception) ExceptionDispatchInfo.Capture(Exception).Throw(); return this; } diff --git a/SnipeSharp/ApiOptionalResponse.cs b/SnipeSharp/ApiOptionalResponse.cs index 7e5d60e..812d296 100644 --- a/SnipeSharp/ApiOptionalResponse.cs +++ b/SnipeSharp/ApiOptionalResponse.cs @@ -1,6 +1,6 @@ +using SnipeSharp.Models; using System; using System.Runtime.ExceptionServices; -using SnipeSharp.Models; namespace SnipeSharp { @@ -42,7 +42,7 @@ public bool HasValue /// This same response. public ApiOptionalResponse RethrowExceptionIfAny() { - if(null != Exception) + if (null != Exception) ExceptionDispatchInfo.Capture(Exception).Throw(); return this; } diff --git a/SnipeSharp/Collections/CustomFieldDictionary.cs b/SnipeSharp/Collections/CustomFieldDictionary.cs index 4b0f95f..eba543a 100644 --- a/SnipeSharp/Collections/CustomFieldDictionary.cs +++ b/SnipeSharp/Collections/CustomFieldDictionary.cs @@ -1,7 +1,7 @@ +using SnipeSharp.Models; using System; using System.Collections; using System.Collections.Generic; -using SnipeSharp.Models; namespace SnipeSharp.Collections { @@ -31,7 +31,7 @@ internal CustomFieldDictionary() public IEnumerable StringValues => GetValues(); private IEnumerable GetValues() { - foreach(var value in Values) + foreach (var value in Values) yield return value.Value; } @@ -40,14 +40,14 @@ internal bool IsModified { get { - foreach(var val in Values) - if(val.IsModified) + foreach (var val in Values) + if (val.IsModified) return true; return false; } set { - foreach(var val in Values) + foreach (var val in Values) val.IsModified = value; } } @@ -62,7 +62,7 @@ internal bool IsModified public int Count => BackingDictionary.Count; /// - public bool IsReadOnly => ((IDictionary)BackingDictionary).IsReadOnly; + public bool IsReadOnly => ((IDictionary)BackingDictionary).IsReadOnly; /// Get and set custom field values by SnipeIT database column name. /// The database column name @@ -71,11 +71,11 @@ public string this[string key] get => BackingDictionary[key].Value; set { - if(null == key) + if (null == key) throw new ArgumentNullException(paramName: nameof(key)); - if(null == value) + if (null == value) throw new ArgumentNullException(paramName: nameof(value)); - if(BackingDictionary.TryGetValue(key, out var model)) + if (BackingDictionary.TryGetValue(key, out var model)) model.Value = value; else { @@ -93,13 +93,13 @@ AssetCustomField IDictionary.this[string key] get => BackingDictionary[key]; set { - if(null == key) + if (null == key) throw new ArgumentNullException(paramName: nameof(key)); - if(null == value) + if (null == value) throw new ArgumentNullException(paramName: nameof(value)); - if(null != value.Field && key != value.Field) + if (null != value.Field && key != value.Field) throw new ArgumentException($"Field key \"{value.Field}\" is not null and does not match key \"{key}\"", paramName: nameof(value)); - if(null == value.Field || null == value.FriendlyName) + if (null == value.Field || null == value.FriendlyName) { value = new AssetCustomField { @@ -110,16 +110,17 @@ AssetCustomField IDictionary.this[string key] }; } var hasFriendlyName = FriendlyNames.TryGetValue(value.FriendlyName, out var existingKey); - if(hasFriendlyName && existingKey != value.Field) + if (hasFriendlyName && existingKey != value.Field) throw new ArgumentException($"The dictionary already contains a friendly name \"{value.FriendlyName}\""); value.IsModified = true; - if(!BackingDictionary.ContainsKey(key)) + if (!BackingDictionary.ContainsKey(key)) { Add(value); - } else + } + else { // remove the non-matching friendly name for the existing field. - if(!hasFriendlyName) + if (!hasFriendlyName) FriendlyNames.Remove(BackingDictionary[value.Field].FriendlyName); BackingDictionary[value.Field] = value; FriendlyNames[value.FriendlyName] = value.Field; @@ -133,7 +134,7 @@ AssetCustomField IDictionary.this[string key] /// True, if the field is present. public bool TryGetValue(string key, out string value) { - if(BackingDictionary.TryGetValue(key, out var model)) + if (BackingDictionary.TryGetValue(key, out var model)) { value = model.Value; return true; @@ -159,7 +160,7 @@ public void Add(string key, string value) /// If or its property are null. /// If the dictionary already contains the value's friendly name and the value is not being updated. public void Add(AssetCustomField value) - => ((IDictionary) this).Add(value?.Field, value); + => ((IDictionary)this).Add(value?.Field, value); /// void ICollection>.Add(KeyValuePair item) @@ -169,15 +170,15 @@ void ICollection>.Add(KeyValuePairIf or its property are null. /// If is null. /// If the dictionary already contains the value's friendly name and the value is not being updated. - void IDictionary.Add(string key, AssetCustomField value) + void IDictionary.Add(string key, AssetCustomField value) { - if(null == value) + if (null == value) throw new ArgumentNullException(paramName: nameof(value)); - if(null == key) + if (null == key) throw new ArgumentNullException(paramName: nameof(key)); - if(null != value.Field && key != value.Field) + if (null != value.Field && key != value.Field) throw new ArgumentException($"Field key \"{value.Field}\" is not null and does not match key \"{key}\"", paramName: nameof(value)); - if(null == value.Field || null == value.FriendlyName) + if (null == value.Field || null == value.FriendlyName) { value = new AssetCustomField { @@ -188,9 +189,9 @@ void IDictionary.Add(string key, AssetCustomField value }; } value.IsModified = true; - if(ContainsKey(value.Field)) + if (ContainsKey(value.Field)) throw new ArgumentException($"The dictionary already contains a key \"{value.Field}\""); - if(FriendlyNames.ContainsKey(value.FriendlyName)) + if (FriendlyNames.ContainsKey(value.FriendlyName)) throw new ArgumentException($"The dictionary already contains a friendly name \"{value.FriendlyName}\""); BackingDictionary.Add(value.Field, value); FriendlyNames.Add(value.FriendlyName, value.Field); @@ -202,7 +203,7 @@ public bool ContainsKey(string key) /// public bool Contains(KeyValuePair item) - => ((IDictionary)BackingDictionary).Contains(item); + => ((IDictionary)BackingDictionary).Contains(item); /// public void Clear() @@ -212,7 +213,7 @@ public void Clear() } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) - => ((IDictionary)BackingDictionary).CopyTo(array, arrayIndex); + => ((IDictionary)BackingDictionary).CopyTo(array, arrayIndex); /// It is not possible to remove fields from a CustomFieldDictionary. bool IDictionary.Remove(string key) @@ -231,7 +232,7 @@ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator> IEnumerable>.GetEnumerator() - => ((IDictionary)BackingDictionary).GetEnumerator(); + => ((IDictionary)BackingDictionary).GetEnumerator(); /// /// A dictionary mapping from friendly names to values, wrapping a . @@ -267,7 +268,7 @@ public bool ContainsKey(string key) /// public IEnumerator> GetEnumerator() { - foreach(var key in Keys) + foreach (var key in Keys) yield return new KeyValuePair(key, CustomFields[CustomFields.FriendlyNames[key]]); } diff --git a/SnipeSharp/EndPoint/AccessoryEndPoint.cs b/SnipeSharp/EndPoint/AccessoryEndPoint.cs index 4a285ee..99202d3 100644 --- a/SnipeSharp/EndPoint/AccessoryEndPoint.cs +++ b/SnipeSharp/EndPoint/AccessoryEndPoint.cs @@ -9,7 +9,7 @@ public sealed class AccessoryEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal AccessoryEndPoint(SnipeItApi api) : base(api) {} + internal AccessoryEndPoint(SnipeItApi api) : base(api) { } /// /// Get the list of accessory check outs for an accessory. @@ -27,7 +27,7 @@ public ResponseCollection GetCheckedOut(Accessory accessory) /// An optional note for the checkout log. /// public RequestResponse CheckOut(Accessory accessory, User assignedUser, string note = null) - => CheckOut(new AccessoryCheckOutRequest(accessory, assignedUser){ Note = note }); + => CheckOut(new AccessoryCheckOutRequest(accessory, assignedUser) { Note = note }); /// /// Check out an accessory. @@ -44,7 +44,7 @@ public RequestResponse CheckOut(AccessoryCheckOutRequest request) /// An optional note for the checkin log. /// public RequestResponse CheckIn(Accessory accessory, string note = null) - => CheckIn(new AccessoryCheckInRequest(accessory){ Note = note }); + => CheckIn(new AccessoryCheckInRequest(accessory) { Note = note }); /// /// Check in an accessory. diff --git a/SnipeSharp/EndPoint/AssetEndPoint.cs b/SnipeSharp/EndPoint/AssetEndPoint.cs index c736d96..b378176 100644 --- a/SnipeSharp/EndPoint/AssetEndPoint.cs +++ b/SnipeSharp/EndPoint/AssetEndPoint.cs @@ -1,5 +1,5 @@ -using System; using SnipeSharp.Models; +using System; namespace SnipeSharp.EndPoint { @@ -10,7 +10,7 @@ public sealed class AssetEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal AssetEndPoint(SnipeItApi api) : base(api) {} + internal AssetEndPoint(SnipeItApi api) : base(api) { } /// /// Check out an asset. @@ -27,7 +27,8 @@ public RequestResponse CheckOut(AssetCheckOutRequest request) /// An optional message for the check-in log. /// public RequestResponse CheckIn(Asset asset, string note = null) - => CheckIn(new AssetCheckInRequest(asset){ + => CheckIn(new AssetCheckInRequest(asset) + { Note = note }); diff --git a/SnipeSharp/EndPoint/CustomFieldEndPoint.cs b/SnipeSharp/EndPoint/CustomFieldEndPoint.cs index 82796e0..be4c889 100644 --- a/SnipeSharp/EndPoint/CustomFieldEndPoint.cs +++ b/SnipeSharp/EndPoint/CustomFieldEndPoint.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; using SnipeSharp.Models; +using System.Collections.Generic; namespace SnipeSharp.EndPoint { @@ -10,7 +10,7 @@ public sealed class CustomFieldEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal CustomFieldEndPoint(SnipeItApi api) : base(api) {} + internal CustomFieldEndPoint(SnipeItApi api) : base(api) { } /// /// Associates a custom field with a custom field set. @@ -22,11 +22,12 @@ internal CustomFieldEndPoint(SnipeItApi api) : base(api) {} /// The request status. public RequestResponse
Associate(CustomField field, FieldSet fieldSet, bool required = false, int? order = null) { - var obj = new CustomFieldAssociation { + var obj = new CustomFieldAssociation + { FieldSet = fieldSet, IsRequired = required }; - if(null != order) + if (null != order) obj.Order = order.Value; return Api.RequestManager.Post($"{EndPointInfo.BaseUri}/{field.Id}/associate", obj).RethrowExceptionIfAny().Value; } diff --git a/SnipeSharp/EndPoint/EndPoint.cs b/SnipeSharp/EndPoint/EndPoint.cs index c0dca52..d3d8174 100644 --- a/SnipeSharp/EndPoint/EndPoint.cs +++ b/SnipeSharp/EndPoint/EndPoint.cs @@ -1,10 +1,10 @@ -using System; -using System.Linq; -using System.Reflection; +using SnipeSharp.Exceptions; using SnipeSharp.Filters; using SnipeSharp.Models; using SnipeSharp.Serialization; -using SnipeSharp.Exceptions; +using System; +using System.Linq; +using System.Reflection; namespace SnipeSharp.EndPoint { @@ -13,7 +13,7 @@ namespace SnipeSharp.EndPoint ///
/// A AbstractBaseModel with the PathSegmentAttribute attribute. public class EndPoint : IEndPoint - where T: AbstractBaseModel + where T : AbstractBaseModel { /// The API instance this endpoint is a part of. protected readonly SnipeItApi Api; @@ -27,7 +27,7 @@ internal EndPoint(SnipeItApi api) { Api = api; EndPointInfo = typeof(T).GetCustomAttribute(); - if(null == EndPointInfo) + if (null == EndPointInfo) throw new MissingRequiredAttributeException(nameof(PathSegmentAttribute), typeof(T).Name); } @@ -50,11 +50,11 @@ public ResponseCollection FindAll(string search) /// public ApiOptionalResponse FindOneOptional(ISearchFilter filter = null) { - if(null == filter) + if (null == filter) filter = new SearchFilter(); filter.Limit = 1; var response = Api.RequestManager.Get>(EndPointInfo.BaseUri, filter); - if(!response.HasValue) + if (!response.HasValue) return new ApiOptionalResponse { Exception = response.Exception }; return new ApiOptionalResponse { Value = response.Value.FirstOrDefault() }; } @@ -90,7 +90,7 @@ public ApiOptionalResponse GetOptional(string name, bool caseSensitive = fals filter.Search = name; var comparer = caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase; var result = FindAllOptional(filter); - if(!result.HasValue) + if (!result.HasValue) return new ApiOptionalResponse { Exception = result.Exception }; return new ApiOptionalResponse { Value = result.Value.Where(i => comparer.Equals(i.Name, name)).FirstOrDefault() }; } @@ -119,7 +119,7 @@ public T Update(T toUpdate) public T Set(T toSet) { var patchable = toSet as IPatchable; - if(null != patchable) + if (null != patchable) patchable.SetAllModifiedState(true); return Api.RequestManager.Put($"{EndPointInfo.BaseUri}/{toSet.Id}", CheckRequiredFields(toSet)).RethrowExceptionIfAny().Value.Payload; } @@ -134,8 +134,8 @@ public T this[int id] private T CheckRequiredFields(T @object) { - foreach(var property in typeof(T).GetProperties()) - if(property.GetCustomAttribute() is SerializeAsAttribute attribute && attribute.IsRequired && null == property.GetValue(@object)) + foreach (var property in typeof(T).GetProperties()) + if (property.GetCustomAttribute() is SerializeAsAttribute attribute && attribute.IsRequired && null == property.GetValue(@object)) throw new MissingRequiredFieldException(property.Name); return @object; } diff --git a/SnipeSharp/EndPoint/FieldSetEndPoint.cs b/SnipeSharp/EndPoint/FieldSetEndPoint.cs index 71bac92..ba27e3a 100644 --- a/SnipeSharp/EndPoint/FieldSetEndPoint.cs +++ b/SnipeSharp/EndPoint/FieldSetEndPoint.cs @@ -9,7 +9,7 @@ public sealed class FieldSetEndPoint : EndPoint
{ /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal FieldSetEndPoint(SnipeItApi api) : base(api) {} + internal FieldSetEndPoint(SnipeItApi api) : base(api) { } /// /// Retrieve the fields of a fieldset. diff --git a/SnipeSharp/EndPoint/IEndPoint.cs b/SnipeSharp/EndPoint/IEndPoint.cs index 0a18526..66080ae 100644 --- a/SnipeSharp/EndPoint/IEndPoint.cs +++ b/SnipeSharp/EndPoint/IEndPoint.cs @@ -1,7 +1,7 @@ -using SnipeSharp.Models; +using SnipeSharp.Exceptions; using SnipeSharp.Filters; +using SnipeSharp.Models; using SnipeSharp.Serialization; -using SnipeSharp.Exceptions; namespace SnipeSharp.EndPoint { @@ -9,7 +9,7 @@ namespace SnipeSharp.EndPoint /// A contract all EndPoints must follow. /// /// - public interface IEndPoint where T: ApiObject + public interface IEndPoint where T : ApiObject { /// /// Create a new object of the generic type. diff --git a/SnipeSharp/EndPoint/LicenseEndPoint.cs b/SnipeSharp/EndPoint/LicenseEndPoint.cs index 4addc5b..27c79da 100644 --- a/SnipeSharp/EndPoint/LicenseEndPoint.cs +++ b/SnipeSharp/EndPoint/LicenseEndPoint.cs @@ -1,6 +1,6 @@ -using System; using SnipeSharp.Filters; using SnipeSharp.Models; +using System; namespace SnipeSharp.EndPoint { @@ -11,7 +11,7 @@ public sealed class LicenseEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal LicenseEndPoint(SnipeItApi api) : base(api) {} + internal LicenseEndPoint(SnipeItApi api) : base(api) { } /// /// Get details for the license seats of a license. @@ -23,7 +23,7 @@ internal LicenseEndPoint(SnipeItApi api) : base(api) {} /// If there was an error accessing the API, or the license does not exist. public ResponseCollection GetSeats(License license, LicenseSeatSearchFilter filter = null) { - if(null == license) + if (null == license) throw new ArgumentNullException(paramName: nameof(license)); return Api.RequestManager.GetAll($"{EndPointInfo.BaseUri}/{license.Id}/seats", filter).RethrowExceptionIfAny().Value; } diff --git a/SnipeSharp/EndPoint/StatusLabelEndPoint.cs b/SnipeSharp/EndPoint/StatusLabelEndPoint.cs index 7d9c90c..bac6ca5 100644 --- a/SnipeSharp/EndPoint/StatusLabelEndPoint.cs +++ b/SnipeSharp/EndPoint/StatusLabelEndPoint.cs @@ -1,5 +1,5 @@ -using System; using SnipeSharp.Models; +using System; namespace SnipeSharp.EndPoint { @@ -10,7 +10,7 @@ public sealed class StatusLabelEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal StatusLabelEndPoint(SnipeItApi api) : base(api) {} + internal StatusLabelEndPoint(SnipeItApi api) : base(api) { } /// /// Get the list of assets with a certain status label. @@ -21,7 +21,7 @@ internal StatusLabelEndPoint(SnipeItApi api) : base(api) {} /// If is null. public ResponseCollection GetAssets(StatusLabel label) { - if(null == label) + if (null == label) throw new ArgumentNullException(paramName: nameof(label)); return Api.RequestManager.GetAll($"{EndPointInfo.BaseUri}/{label.Id}/assetlist").RethrowExceptionIfAny().Value; } @@ -35,7 +35,7 @@ public ResponseCollection GetAssets(StatusLabel label) /// If is null. public bool IsDeployable(StatusLabel label) { - if(null == label) + if (null == label) throw new ArgumentNullException(paramName: nameof(label)); return Api.RequestManager.GetRaw($"{EndPointInfo.BaseUri}/{label.Id}/deployable").Trim() == "1"; } @@ -49,7 +49,7 @@ public bool IsDeployable(StatusLabel label) /// If is null. public StatusLabel FromAssetStatus(AssetStatus status) { - if(null == status) + if (null == status) throw new ArgumentNullException(paramName: nameof(status)); return Get(status.StatusId); } diff --git a/SnipeSharp/EndPoint/UserEndPoint.cs b/SnipeSharp/EndPoint/UserEndPoint.cs index 1506458..6179b11 100644 --- a/SnipeSharp/EndPoint/UserEndPoint.cs +++ b/SnipeSharp/EndPoint/UserEndPoint.cs @@ -1,6 +1,6 @@ -using SnipeSharp.Models; -using SnipeSharp.Filters; using SnipeSharp.Exceptions; +using SnipeSharp.Filters; +using SnipeSharp.Models; namespace SnipeSharp.EndPoint { @@ -11,7 +11,7 @@ public sealed class UserEndPoint : EndPoint { /// The Api to grab the RequestManager from. /// When the type parameter does not have the PathSegmentAttribute attribute. - internal UserEndPoint(SnipeItApi api) : base(api) {} + internal UserEndPoint(SnipeItApi api) : base(api) { } /// /// Get the assets assigned to a user. @@ -68,10 +68,10 @@ public ApiOptionalResponse GetByUserNameOptional(string username, UserSear filter = filter ?? new UserSearchFilter(); filter.Search = username; var results = FindAllOptional(filter); - if(!results.HasValue) + if (!results.HasValue) return new ApiOptionalResponse { Exception = results.Exception }; - foreach(var user in results.Value) - if(user.UserName == username) + foreach (var user in results.Value) + if (user.UserName == username) return new ApiOptionalResponse { Value = user }; return new ApiOptionalResponse { Exception = new ApiErrorException($"No user was found by the username \"{username}\".") }; } @@ -87,10 +87,10 @@ public ApiOptionalResponse GetByEmailAddressOptional(string email, UserSea filter = filter ?? new UserSearchFilter(); filter.Search = email; var results = FindAllOptional(filter); - if(!results.HasValue) + if (!results.HasValue) return new ApiOptionalResponse { Exception = results.Exception }; - foreach(var user in results.Value) - if(user.EmailAddress == email) + foreach (var user in results.Value) + if (user.EmailAddress == email) return new ApiOptionalResponse { Value = user }; return new ApiOptionalResponse { Exception = new ApiErrorException($"No user was found by the email address \"{email}\".") }; } diff --git a/SnipeSharp/Exceptions/ApiErrorException.cs b/SnipeSharp/Exceptions/ApiErrorException.cs index 055e5bf..898ea7d 100644 --- a/SnipeSharp/Exceptions/ApiErrorException.cs +++ b/SnipeSharp/Exceptions/ApiErrorException.cs @@ -1,14 +1,14 @@ +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Net; -using Newtonsoft.Json; namespace SnipeSharp.Exceptions { /// /// The exception that is thrown when the SnipeIT Api returns a non-success HttpStatusCode or a successful HTTP status, but an API error status. /// - public sealed class ApiErrorException: Exception + public sealed class ApiErrorException : Exception { /// /// If the HTTP request was not successful, then true, else false. @@ -30,7 +30,7 @@ public sealed class ApiErrorException: Exception /// /// The HttpStatusCode of the failed request /// The response content or other message, if any. - public ApiErrorException(HttpStatusCode errorCode, string message): base(message ?? errorCode.ToString()) + public ApiErrorException(HttpStatusCode errorCode, string message) : base(message ?? errorCode.ToString()) { IsHttpError = true; HttpStatusCode = errorCode; @@ -40,7 +40,7 @@ public ApiErrorException(HttpStatusCode errorCode, string message): base(message /// Initializes a new instance of the ApiErrorException class with a specified message. /// /// The message, if any. - public ApiErrorException(string message): base(message) + public ApiErrorException(string message) : base(message) { IsHttpError = false; } @@ -57,13 +57,14 @@ public ApiErrorException(IReadOnlyDictionary messages) : this(Js /// public override string ToString() { - if(IsHttpError) + if (IsHttpError) { var message = Message; - if(message.Length > 80) - message = $"{message.Substring(0,77)}..."; + if (message.Length > 80) + message = $"{message.Substring(0, 77)}..."; return $"{HttpStatusCode}: {message}"; - } else + } + else { return base.ToString(); } diff --git a/SnipeSharp/Exceptions/ApiReturnedInsufficientValuesForRequestException.cs b/SnipeSharp/Exceptions/ApiReturnedInsufficientValuesForRequestException.cs index 665a45a..2e4eb69 100644 --- a/SnipeSharp/Exceptions/ApiReturnedInsufficientValuesForRequestException.cs +++ b/SnipeSharp/Exceptions/ApiReturnedInsufficientValuesForRequestException.cs @@ -8,7 +8,7 @@ namespace SnipeSharp.Exceptions /// nor the total have been reached. /// /// - public sealed class ApiReturnedInsufficientValuesForRequestException: Exception + public sealed class ApiReturnedInsufficientValuesForRequestException : Exception { } } diff --git a/SnipeSharp/Exceptions/MissingRequiredAttributeException.cs b/SnipeSharp/Exceptions/MissingRequiredAttributeException.cs index 32ffc8d..797b610 100644 --- a/SnipeSharp/Exceptions/MissingRequiredAttributeException.cs +++ b/SnipeSharp/Exceptions/MissingRequiredAttributeException.cs @@ -12,7 +12,7 @@ public sealed class MissingRequiredAttributeException : Exception /// /// The name of the required attribute class. /// The name of the class that is missing the required attribute. - public MissingRequiredAttributeException(string attributeName, string className): base($"Missing required attribute \"{attributeName}\" on class \"{className}\".") + public MissingRequiredAttributeException(string attributeName, string className) : base($"Missing required attribute \"{attributeName}\" on class \"{className}\".") { } } diff --git a/SnipeSharp/Exceptions/MissingRequiredFieldException.cs b/SnipeSharp/Exceptions/MissingRequiredFieldException.cs index 2dd1b0a..714aab4 100644 --- a/SnipeSharp/Exceptions/MissingRequiredFieldException.cs +++ b/SnipeSharp/Exceptions/MissingRequiredFieldException.cs @@ -7,13 +7,13 @@ namespace SnipeSharp.Exceptions /// /// A class that could be missing a required field. /// - public sealed class MissingRequiredFieldException: Exception + public sealed class MissingRequiredFieldException : Exception { /// /// Initializes a new instance of the MissingRequiredFieldException class with a specified field name. /// /// The name of the field or property that is missing. - public MissingRequiredFieldException(string fieldName): base($"Missing required field \"{fieldName}\" in object of type \"{typeof(T).FullName}\"") + public MissingRequiredFieldException(string fieldName) : base($"Missing required field \"{fieldName}\" in object of type \"{typeof(T).FullName}\"") { } @@ -22,7 +22,7 @@ public MissingRequiredFieldException(string fieldName): base($"Missing required ///
/// The name of the type. /// The name of the field or property that is missing. - internal MissingRequiredFieldException(string typeName, string fieldName): base($"Missing required field \"{fieldName}\" in object of type \"{typeName}\"") + internal MissingRequiredFieldException(string typeName, string fieldName) : base($"Missing required field \"{fieldName}\" in object of type \"{typeName}\"") { } } diff --git a/SnipeSharp/Exceptions/NullApiTokenException.cs b/SnipeSharp/Exceptions/NullApiTokenException.cs index a535683..1e0c7ae 100644 --- a/SnipeSharp/Exceptions/NullApiTokenException.cs +++ b/SnipeSharp/Exceptions/NullApiTokenException.cs @@ -11,7 +11,7 @@ public sealed class NullApiTokenException : Exception /// /// Initializes a new instance of the MissingRequiredAttributeException class. /// - public NullApiTokenException(): base("No API Token set.") + public NullApiTokenException() : base("No API Token set.") { } } diff --git a/SnipeSharp/Exceptions/NullApiUriException.cs b/SnipeSharp/Exceptions/NullApiUriException.cs index 39dc036..da02618 100644 --- a/SnipeSharp/Exceptions/NullApiUriException.cs +++ b/SnipeSharp/Exceptions/NullApiUriException.cs @@ -11,7 +11,7 @@ public sealed class NullApiUriException : Exception /// /// Initializes a new instance of the NullApiUriException class. /// - public NullApiUriException(): base("No API Uri set.") + public NullApiUriException() : base("No API Uri set.") { } } diff --git a/SnipeSharp/Filters/AbstractAssetSearchFilter.cs b/SnipeSharp/Filters/AbstractAssetSearchFilter.cs index 7db2102..406598e 100644 --- a/SnipeSharp/Filters/AbstractAssetSearchFilter.cs +++ b/SnipeSharp/Filters/AbstractAssetSearchFilter.cs @@ -1,6 +1,6 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; using System.Collections.Generic; namespace SnipeSharp.Filters diff --git a/SnipeSharp/Filters/AccessorySearchFilter.cs b/SnipeSharp/Filters/AccessorySearchFilter.cs index 3118cb6..609c44e 100644 --- a/SnipeSharp/Filters/AccessorySearchFilter.cs +++ b/SnipeSharp/Filters/AccessorySearchFilter.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models; +using SnipeSharp.Serialization; namespace SnipeSharp.Filters { diff --git a/SnipeSharp/Filters/AssetSearchColumn.cs b/SnipeSharp/Filters/AssetSearchColumn.cs index fcb2acf..eedc9d8 100644 --- a/SnipeSharp/Filters/AssetSearchColumn.cs +++ b/SnipeSharp/Filters/AssetSearchColumn.cs @@ -71,6 +71,9 @@ public enum AssetSearchColumn CheckInCounter, /// The number of times the asset has been requested. [EnumMember(Value = "requests_counter")] - RequestsCounter + RequestsCounter, + /// The status of the asset in inventory (Deployed, Ready to deploy, Recycle. + [EnumMember(Value = "status")] + Status } } diff --git a/SnipeSharp/Filters/AssetSearchFilter.cs b/SnipeSharp/Filters/AssetSearchFilter.cs index 49646da..b0c8b31 100644 --- a/SnipeSharp/Filters/AssetSearchFilter.cs +++ b/SnipeSharp/Filters/AssetSearchFilter.cs @@ -1,6 +1,5 @@ -using System.Collections.Generic; -using System.Runtime.Serialization; using SnipeSharp.Serialization; +using System.Runtime.Serialization; namespace SnipeSharp.Filters { @@ -60,7 +59,7 @@ public AssetSearchFilter AddField(string name, string value) [OnSerializing] private void OnSerializing(StreamingContext context) { - if(null != CustomFields && CustomFields.Count > 0) + if (null != CustomFields && CustomFields.Count > 0) _customFields = CustomFields; } } diff --git a/SnipeSharp/Filters/CustomAssetSearchFilter.cs b/SnipeSharp/Filters/CustomAssetSearchFilter.cs index 17fa35f..21ea976 100644 --- a/SnipeSharp/Filters/CustomAssetSearchFilter.cs +++ b/SnipeSharp/Filters/CustomAssetSearchFilter.cs @@ -1,5 +1,5 @@ -using System.Runtime.Serialization; using SnipeSharp.Serialization; +using System.Runtime.Serialization; namespace SnipeSharp.Filters { @@ -46,7 +46,7 @@ public CustomAssetSearchFilter(string searchString) [OnSerializing] private void OnSerializing(StreamingContext context) { - if(null != CustomFields && CustomFields.Count > 0) + if (null != CustomFields && CustomFields.Count > 0) _customFields = CustomFields; } } diff --git a/SnipeSharp/Filters/ISortableSearchFilter.cs b/SnipeSharp/Filters/ISortableSearchFilter.cs index 39d2732..f6fa8dd 100644 --- a/SnipeSharp/Filters/ISortableSearchFilter.cs +++ b/SnipeSharp/Filters/ISortableSearchFilter.cs @@ -4,7 +4,7 @@ namespace SnipeSharp.Filters /// The typed search filter interface, for filtering collections in the API and sorting the based on a column. ///
/// The sort column type; for example, an enumeration, or a string. - public interface ISortableSearchFilter: ISearchFilter + public interface ISortableSearchFilter : ISearchFilter { /// /// The column to sort on. diff --git a/SnipeSharp/Filters/LicenseSeatSearchFilter.cs b/SnipeSharp/Filters/LicenseSeatSearchFilter.cs index 9de01e0..539053a 100644 --- a/SnipeSharp/Filters/LicenseSeatSearchFilter.cs +++ b/SnipeSharp/Filters/LicenseSeatSearchFilter.cs @@ -1,5 +1,5 @@ -using System; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Filters { diff --git a/SnipeSharp/Filters/RequestableAssetSearchColumn.cs b/SnipeSharp/Filters/RequestableAssetSearchColumn.cs index ad27d70..a1ce0f7 100644 --- a/SnipeSharp/Filters/RequestableAssetSearchColumn.cs +++ b/SnipeSharp/Filters/RequestableAssetSearchColumn.cs @@ -13,7 +13,7 @@ namespace SnipeSharp.Filters public enum RequestableAssetSearchColumn { /// The creation time. - [EnumMember(Value="created_at")] // value is not valid, but defaults to valid in API controller + [EnumMember(Value = "created_at")] // value is not valid, but defaults to valid in API controller CreationTime = 0, /// The asset model. [EnumMember(Value = "model")] diff --git a/SnipeSharp/Filters/RequestableAssetSearchFilter.cs b/SnipeSharp/Filters/RequestableAssetSearchFilter.cs index 95b01f4..e3d4509 100644 --- a/SnipeSharp/Filters/RequestableAssetSearchFilter.cs +++ b/SnipeSharp/Filters/RequestableAssetSearchFilter.cs @@ -1,5 +1,5 @@ -using System; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Filters { @@ -22,11 +22,12 @@ public sealed class RequestableAssetSearchFilter : ISortableSearchFilter /// If attempting to set a null value. [SerializeAs("search")] - public string Search { + public string Search + { get => _SearchString; set { - if(null == value) + if (null == value) throw new ArgumentNullException(paramName: nameof(value)); _SearchString = value; } @@ -54,7 +55,7 @@ public RequestableAssetSearchFilter() /// If is null. public RequestableAssetSearchFilter(string searchString) { - if(null == searchString) + if (null == searchString) throw new ArgumentNullException(paramName: nameof(searchString)); Search = searchString; } diff --git a/SnipeSharp/Filters/SearchFilter.cs b/SnipeSharp/Filters/SearchFilter.cs index 2c739b5..5811250 100644 --- a/SnipeSharp/Filters/SearchFilter.cs +++ b/SnipeSharp/Filters/SearchFilter.cs @@ -1,10 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using SnipeSharp.Models; using SnipeSharp.Serialization; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; namespace SnipeSharp.Filters { @@ -26,11 +25,12 @@ public sealed class SearchFilter : ISortableSearchFilter /// /// If attempting to set a null value. [SerializeAs("search")] - public string Search { + public string Search + { get => _SearchString; set { - if(null == value) + if (null == value) throw new ArgumentNullException(paramName: nameof(value)); _SearchString = value; } @@ -64,7 +64,7 @@ public SearchFilter() /// If is null. public SearchFilter(string searchString) { - if(null == searchString) + if (null == searchString) throw new ArgumentNullException(paramName: nameof(searchString)); Search = searchString; } @@ -85,8 +85,8 @@ public SearchFilter AddField(string name, string value) private void OnSerializing(StreamingContext context) { _customFields = new Dictionary(); - if(null != CustomFields) - foreach(var pair in CustomFields) + if (null != CustomFields) + foreach (var pair in CustomFields) _customFields[pair.Key] = pair.Value; } } diff --git a/SnipeSharp/Filters/UserSearchFilter.cs b/SnipeSharp/Filters/UserSearchFilter.cs index 4fee5c8..fc6d1d3 100644 --- a/SnipeSharp/Filters/UserSearchFilter.cs +++ b/SnipeSharp/Filters/UserSearchFilter.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models; +using SnipeSharp.Serialization; namespace SnipeSharp.Filters { diff --git a/SnipeSharp/Models/AbstractBaseModel.cs b/SnipeSharp/Models/AbstractBaseModel.cs index 0680ad5..d090b9a 100644 --- a/SnipeSharp/Models/AbstractBaseModel.cs +++ b/SnipeSharp/Models/AbstractBaseModel.cs @@ -1,12 +1,12 @@ -using System; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Models { /// /// AbstractBaseModel is an ApiObject associated with an Api EndPoint. /// - public abstract class AbstractBaseModel: ApiObject, IObjectWithId + public abstract class AbstractBaseModel : ApiObject, IObjectWithId { /// The internal Id of the object. [DeserializeAs("id")] diff --git a/SnipeSharp/Models/AccessoryCheckOut.cs b/SnipeSharp/Models/AccessoryCheckOut.cs index 33e080c..091ebd0 100644 --- a/SnipeSharp/Models/AccessoryCheckOut.cs +++ b/SnipeSharp/Models/AccessoryCheckOut.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; namespace SnipeSharp.Models { @@ -18,7 +18,7 @@ public sealed class AccessoryCheckOut : ApiObject, IAvailableActions /// The Id of the User in Snipe-IT. /// [DeserializeAs("id")] - public int UserId { get; private set; } + public int UserId { get; private set; } /// /// The user's username. diff --git a/SnipeSharp/Models/AssetAssignedTo.cs b/SnipeSharp/Models/AssetAssignedTo.cs index fcb2bdd..b7fa1ba 100644 --- a/SnipeSharp/Models/AssetAssignedTo.cs +++ b/SnipeSharp/Models/AssetAssignedTo.cs @@ -1,10 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SnipeSharp.Models.Enumerations; using SnipeSharp.Serialization; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; namespace SnipeSharp.Models { @@ -63,10 +63,10 @@ public override string ToString() [OnDeserialized] private void OnDeserialized(StreamingContext context) { - if(null == _extensionData) + if (null == _extensionData) return; var dict = new Dictionary(); - foreach(var pair in _extensionData) + foreach (var pair in _extensionData) dict[pair.Key] = pair.Value.ToObject(); ExtensionData = dict; _extensionData = null; @@ -78,7 +78,7 @@ private void OnDeserialized(StreamingContext context) /// A stub user object, with only the ID field populated. public StubUser AsUser() { - if(Type != AssignedToType.User) + if (Type != AssignedToType.User) throw new InvalidOperationException($"Object {Id} is a \"{Type}\", not a User."); return new StubUser( id: Id, @@ -96,7 +96,7 @@ public StubUser AsUser() /// A stub location object. public Stub AsLocation() { - if(Type != AssignedToType.Location) + if (Type != AssignedToType.Location) throw new InvalidOperationException($"Object {Id} is a \"{Type}\", not a Location."); // location assignments have no extension data to copy return new Stub(Id, Name); @@ -108,7 +108,7 @@ public Stub AsLocation() /// A stub asset object. public Stub AsAsset() { - if(Type != AssignedToType.Asset) + if (Type != AssignedToType.Asset) throw new InvalidOperationException($"Object {Id} is a \"{Type}\", not a Asset."); // asset assignments have no extension data to copy return new Stub(Id, Name); diff --git a/SnipeSharp/Models/AssetCustomField.cs b/SnipeSharp/Models/AssetCustomField.cs index 1425eca..4090481 100644 --- a/SnipeSharp/Models/AssetCustomField.cs +++ b/SnipeSharp/Models/AssetCustomField.cs @@ -52,7 +52,7 @@ public string Value /// public override string ToString() { - if(null != FriendlyName) + if (null != FriendlyName) return $"{FriendlyName}: {Value ?? ""}"; else return Value ?? base.ToString(); diff --git a/SnipeSharp/Models/AssetStatus.cs b/SnipeSharp/Models/AssetStatus.cs index 955c3df..398c551 100644 --- a/SnipeSharp/Models/AssetStatus.cs +++ b/SnipeSharp/Models/AssetStatus.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; namespace SnipeSharp.Models { @@ -41,7 +41,7 @@ public sealed class AssetStatus : IObjectWithId /// public override string ToString() { - if(null == StatusMeta) + if (null == StatusMeta) return Name ?? StatusId.ToString(); return $"{Name ?? StatusId.ToString()}: {StatusMeta}"; } diff --git a/SnipeSharp/Models/ComponentAsset.cs b/SnipeSharp/Models/ComponentAsset.cs index e45a0dd..9ad1894 100644 --- a/SnipeSharp/Models/ComponentAsset.cs +++ b/SnipeSharp/Models/ComponentAsset.cs @@ -1,6 +1,6 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/ComponentCheckOut.cs b/SnipeSharp/Models/ComponentCheckOut.cs index e808fb1..6e22158 100644 --- a/SnipeSharp/Models/ComponentCheckOut.cs +++ b/SnipeSharp/Models/ComponentCheckOut.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; namespace SnipeSharp.Models { @@ -18,7 +18,7 @@ public sealed class ComponentCheckOut : ApiObject, IAvailableActions /// The Id of the User in Snipe-IT. /// [DeserializeAs("id")] - public int AssetId { get; private set; } + public int AssetId { get; private set; } /// diff --git a/SnipeSharp/Models/Enumerations/MaintenanceType.cs b/SnipeSharp/Models/Enumerations/MaintenanceType.cs index ee144cf..0ed39dc 100644 --- a/SnipeSharp/Models/Enumerations/MaintenanceType.cs +++ b/SnipeSharp/Models/Enumerations/MaintenanceType.cs @@ -1,7 +1,7 @@ -using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using SnipeSharp.Serialization; +using System.Runtime.Serialization; namespace SnipeSharp.Models.Enumerations { diff --git a/SnipeSharp/Models/GenericEndPointModel.cs b/SnipeSharp/Models/GenericEndPointModel.cs index 16e243f..7a7be73 100644 --- a/SnipeSharp/Models/GenericEndPointModel.cs +++ b/SnipeSharp/Models/GenericEndPointModel.cs @@ -4,7 +4,7 @@ namespace SnipeSharp.Models /// GenericEndPointModel is a constructable implementation of AbstractBaseModel. /// It is used for deserialization only. /// - public sealed class GenericEndPointModel: AbstractBaseModel + public sealed class GenericEndPointModel : AbstractBaseModel { } } diff --git a/SnipeSharp/Models/IAvailableActions.cs b/SnipeSharp/Models/IAvailableActions.cs index e4a854e..f5debd4 100644 --- a/SnipeSharp/Models/IAvailableActions.cs +++ b/SnipeSharp/Models/IAvailableActions.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using SnipeSharp.Models.Enumerations; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/LicenseSeat.cs b/SnipeSharp/Models/LicenseSeat.cs index 83c438b..ec17000 100644 --- a/SnipeSharp/Models/LicenseSeat.cs +++ b/SnipeSharp/Models/LicenseSeat.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/OnlySubmittable/AssetCheckOutRequest.cs b/SnipeSharp/Models/OnlySubmittable/AssetCheckOutRequest.cs index 1340e5a..99a1419 100644 --- a/SnipeSharp/Models/OnlySubmittable/AssetCheckOutRequest.cs +++ b/SnipeSharp/Models/OnlySubmittable/AssetCheckOutRequest.cs @@ -1,6 +1,6 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Models { @@ -79,7 +79,7 @@ public AssetCheckOutRequest(Asset asset, Asset assignedAsset) { Asset = asset; AssignedAsset = assignedAsset; - if(assignedAsset.IsDeleted) + if (assignedAsset.IsDeleted) throw new ArgumentException("Cannot check out to a deleted asset.", paramName: nameof(assignedAsset)); AssignedToType = AssignedToType.Asset; } diff --git a/SnipeSharp/Models/OnlySubmittable/CustomFieldAssociation.cs b/SnipeSharp/Models/OnlySubmittable/CustomFieldAssociation.cs index 9de683a..81fa553 100644 --- a/SnipeSharp/Models/OnlySubmittable/CustomFieldAssociation.cs +++ b/SnipeSharp/Models/OnlySubmittable/CustomFieldAssociation.cs @@ -25,7 +25,8 @@ internal sealed class CustomFieldAssociation : ApiObject ///
[DeserializeAs("required")] [SerializeAs("required")] - public bool IsRequired { + public bool IsRequired + { get => _isRequired == IsRequiredType.On; set => _isRequired = value ? IsRequiredType.On : IsRequiredType.Off; } @@ -34,6 +35,6 @@ public bool IsRequired { /// The order of the field in the fieldset. ///
[SerializeAs("order")] - public int Order { get; set ;} + public int Order { get; set; } } } diff --git a/SnipeSharp/Models/Request.cs b/SnipeSharp/Models/Request.cs index 34b2ec2..e115537 100644 --- a/SnipeSharp/Models/Request.cs +++ b/SnipeSharp/Models/Request.cs @@ -1,6 +1,6 @@ -using System; using SnipeSharp.Models.Enumerations; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/RequestResponse.cs b/SnipeSharp/Models/RequestResponse.cs index d0c92c6..62b06fc 100644 --- a/SnipeSharp/Models/RequestResponse.cs +++ b/SnipeSharp/Models/RequestResponse.cs @@ -1,8 +1,8 @@ -using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using SnipeSharp.Serialization; +using System.Collections.Generic; using System.Linq; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json; using System.Runtime.Serialization; namespace SnipeSharp.Models @@ -11,7 +11,7 @@ namespace SnipeSharp.Models /// A response from the API, which may indicate success or error, have messages, and possibly have a payload. ///
/// The payload type. - public sealed class RequestResponse: ApiObject where T: ApiObject + public sealed class RequestResponse : ApiObject where T : ApiObject { /// Any messages returned by the API; the default key is "general". //[DeserializeAs("messages", DeserializeAs.MessageDictionary)] @@ -31,15 +31,16 @@ public sealed class RequestResponse: ApiObject where T: ApiObject [OnDeserialized] private void OnDeserialized(StreamingContext context) { - if(null == extensionData) + if (null == extensionData) return; - if(extensionData.TryGetValue("messages", out var token)) + if (extensionData.TryGetValue("messages", out var token)) { - if(JTokenType.String == token.Type) + if (JTokenType.String == token.Type) Messages = new Dictionary { ["general"] = token.ToObject() }; else Messages = token.ToObject>(); - } else + } + else { Messages = new Dictionary(); } diff --git a/SnipeSharp/Models/RequestableAsset.cs b/SnipeSharp/Models/RequestableAsset.cs index f7b56ce..9afc8ca 100644 --- a/SnipeSharp/Models/RequestableAsset.cs +++ b/SnipeSharp/Models/RequestableAsset.cs @@ -1,6 +1,6 @@ -using System; using SnipeSharp.Models.Enumerations; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/ResponseCollection.cs b/SnipeSharp/Models/ResponseCollection.cs index b84510b..43d4cbd 100644 --- a/SnipeSharp/Models/ResponseCollection.cs +++ b/SnipeSharp/Models/ResponseCollection.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using Newtonsoft.Json; using SnipeSharp.Serialization; using System.Collections; -using Newtonsoft.Json; +using System.Collections.Generic; namespace SnipeSharp.Models { @@ -11,7 +11,7 @@ namespace SnipeSharp.Models /// The type of elements in this collection. [JsonObject] public sealed class ResponseCollection : ApiObject, IList, IReadOnlyList, ICollection, IReadOnlyCollection - where T: ApiObject + where T : ApiObject { /// The total number of objects available from the endpoint for whatever filters were applied. /// This value may not be the same as . @@ -33,7 +33,7 @@ public T this[int index] public int Count => Rows?.Count ?? 0; /// - public bool IsReadOnly => ((IList) Rows).IsReadOnly; + public bool IsReadOnly => ((IList)Rows).IsReadOnly; /// public void Add(T item) diff --git a/SnipeSharp/Models/SelfUser.cs b/SnipeSharp/Models/SelfUser.cs index 954385c..9ee93bf 100644 --- a/SnipeSharp/Models/SelfUser.cs +++ b/SnipeSharp/Models/SelfUser.cs @@ -1,5 +1,5 @@ -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; +using SnipeSharp.Serialization; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/Stub.cs b/SnipeSharp/Models/Stub.cs index 25b5ad4..26effcc 100644 --- a/SnipeSharp/Models/Stub.cs +++ b/SnipeSharp/Models/Stub.cs @@ -7,7 +7,7 @@ namespace SnipeSharp.Models /// Represents a stub object of a certain type, with only the Id and Name filled by the API. ///
public class Stub : ApiObject, IObjectWithId - where T: AbstractBaseModel, new() + where T : AbstractBaseModel, new() { /// The Id of the object. [DeserializeAs("id")] diff --git a/SnipeSharp/Models/Submittable/Accessory.cs b/SnipeSharp/Models/Submittable/Accessory.cs index 824e2a0..70b5d1b 100644 --- a/SnipeSharp/Models/Submittable/Accessory.cs +++ b/SnipeSharp/Models/Submittable/Accessory.cs @@ -1,7 +1,7 @@ -using System; using SnipeSharp.EndPoint; -using SnipeSharp.Serialization; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Asset.cs b/SnipeSharp/Models/Submittable/Asset.cs index 4701f58..ae9dba4 100644 --- a/SnipeSharp/Models/Submittable/Asset.cs +++ b/SnipeSharp/Models/Submittable/Asset.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; -using SnipeSharp.Serialization; -using SnipeSharp.EndPoint; -using SnipeSharp.Models.Enumerations; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System.Runtime.Serialization; using SnipeSharp.Collections; +using SnipeSharp.EndPoint; +using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; namespace SnipeSharp.Models { @@ -485,7 +485,7 @@ private bool isCustomFieldsModified get => CustomFields?.IsModified ?? false; set { - if(null != CustomFields) + if (null != CustomFields) CustomFields.IsModified = value; } } @@ -497,15 +497,15 @@ private bool isCustomFieldsModified private void OnSerializing(StreamingContext context) { _customFields = new Dictionary(); - if(null != CustomFields) - foreach(var pair in CustomFields) + if (null != CustomFields) + foreach (var pair in CustomFields) // only serialize modified custom fields // Value cannot be null, because we check that in CustomFieldDictionary - if(pair.Value!.IsModified) + if (pair.Value!.IsModified) _customFields[pair.Value!.Field ?? pair.Key] = pair.Value!.Value; - if(null != AssignedTo && isAssignedToModified) // TODO: is it possible to un-assign with this method? + if (null != AssignedTo && isAssignedToModified) // TODO: is it possible to un-assign with this method? { - switch(AssignedTo.Type) + switch (AssignedTo.Type) { case AssignedToType.Asset: _customFields["assigned_asset"] = AssignedTo.Id; @@ -530,11 +530,11 @@ private void OnSerialized(StreamingContext context) [OnDeserialized] private void OnDeserialized(StreamingContext context) { - if(null != _customFields) + if (null != _customFields) { - foreach(var pair in _customFields) + foreach (var pair in _customFields) { - if(!pair.Key.StartsWith("_snipeit_")) // custom fields start with _snipeit_ + if (!pair.Key.StartsWith("_snipeit_")) // custom fields start with _snipeit_ continue; CustomFields.Add(new AssetCustomField { diff --git a/SnipeSharp/Models/Submittable/AssetAudit.cs b/SnipeSharp/Models/Submittable/AssetAudit.cs index 9a8d921..b331bdc 100644 --- a/SnipeSharp/Models/Submittable/AssetAudit.cs +++ b/SnipeSharp/Models/Submittable/AssetAudit.cs @@ -1,6 +1,6 @@ -using System; using SnipeSharp.EndPoint; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/Submittable/Category.cs b/SnipeSharp/Models/Submittable/Category.cs index 09abe78..4fd5eb2 100644 --- a/SnipeSharp/Models/Submittable/Category.cs +++ b/SnipeSharp/Models/Submittable/Category.cs @@ -1,8 +1,8 @@ -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; -using System.Runtime.Serialization; +using SnipeSharp.Serialization; using System; +using System.Runtime.Serialization; namespace SnipeSharp.Models { @@ -172,7 +172,7 @@ public int? ItemCount { get { - switch(CategoryType) + switch (CategoryType) { case Enumerations.CategoryType.Accessory: return AccessoriesCount; diff --git a/SnipeSharp/Models/Submittable/Company.cs b/SnipeSharp/Models/Submittable/Company.cs index f4e2d7d..9754527 100644 --- a/SnipeSharp/Models/Submittable/Company.cs +++ b/SnipeSharp/Models/Submittable/Company.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Component.cs b/SnipeSharp/Models/Submittable/Component.cs index 5c6d7ac..b92f4e3 100644 --- a/SnipeSharp/Models/Submittable/Component.cs +++ b/SnipeSharp/Models/Submittable/Component.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Consumable.cs b/SnipeSharp/Models/Submittable/Consumable.cs index 28c97ab..3daf4c1 100644 --- a/SnipeSharp/Models/Submittable/Consumable.cs +++ b/SnipeSharp/Models/Submittable/Consumable.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/CustomField.cs b/SnipeSharp/Models/Submittable/CustomField.cs index 69393be..42540d3 100644 --- a/SnipeSharp/Models/Submittable/CustomField.cs +++ b/SnipeSharp/Models/Submittable/CustomField.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models @@ -116,7 +116,7 @@ public string Format private bool isFormatModified = false; private string format; - private readonly static string[] EndOfLines = new string[]{ "\n", "\r\n" }; + private readonly static string[] EndOfLines = new string[] { "\n", "\r\n" }; /// Gets/sets the raw value of any list type, separated by newlines. [DeserializeAs("field_values")] @@ -129,7 +129,7 @@ public string FieldValuesRaw { isFieldValuesRawModified = true; fieldValuesRaw = value; - if(null == value) + if (null == value) FieldValues = new string[0]; else FieldValues = value.Split(EndOfLines, StringSplitOptions.None); diff --git a/SnipeSharp/Models/Submittable/Department.cs b/SnipeSharp/Models/Submittable/Department.cs index 23491a8..38c09e3 100644 --- a/SnipeSharp/Models/Submittable/Department.cs +++ b/SnipeSharp/Models/Submittable/Department.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Depreciation.cs b/SnipeSharp/Models/Submittable/Depreciation.cs index a4b726c..6791e51 100644 --- a/SnipeSharp/Models/Submittable/Depreciation.cs +++ b/SnipeSharp/Models/Submittable/Depreciation.cs @@ -1,6 +1,6 @@ -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/FieldSet.cs b/SnipeSharp/Models/Submittable/FieldSet.cs index ee3a8b8..6077f0e 100644 --- a/SnipeSharp/Models/Submittable/FieldSet.cs +++ b/SnipeSharp/Models/Submittable/FieldSet.cs @@ -1,7 +1,7 @@ -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; -using System.Runtime.Serialization; +using SnipeSharp.Serialization; using System.Collections.Generic; +using System.Runtime.Serialization; namespace SnipeSharp.Models { diff --git a/SnipeSharp/Models/Submittable/Group.cs b/SnipeSharp/Models/Submittable/Group.cs index d44cf52..f6d8e93 100644 --- a/SnipeSharp/Models/Submittable/Group.cs +++ b/SnipeSharp/Models/Submittable/Group.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System.Collections.Generic; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/License.cs b/SnipeSharp/Models/Submittable/License.cs index 0b73493..d82e577 100644 --- a/SnipeSharp/Models/Submittable/License.cs +++ b/SnipeSharp/Models/Submittable/License.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Location.cs b/SnipeSharp/Models/Submittable/Location.cs index fa360c0..be5e343 100644 --- a/SnipeSharp/Models/Submittable/Location.cs +++ b/SnipeSharp/Models/Submittable/Location.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; +using System.Collections.Generic; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Maintenance.cs b/SnipeSharp/Models/Submittable/Maintenance.cs index 1f52614..607d645 100644 --- a/SnipeSharp/Models/Submittable/Maintenance.cs +++ b/SnipeSharp/Models/Submittable/Maintenance.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Manufacturer.cs b/SnipeSharp/Models/Submittable/Manufacturer.cs index aa27653..52fd150 100644 --- a/SnipeSharp/Models/Submittable/Manufacturer.cs +++ b/SnipeSharp/Models/Submittable/Manufacturer.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/Model.cs b/SnipeSharp/Models/Submittable/Model.cs index e9e44ec..98c3ae8 100644 --- a/SnipeSharp/Models/Submittable/Model.cs +++ b/SnipeSharp/Models/Submittable/Model.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models @@ -174,7 +174,7 @@ public string Notes /// The date this object was soft-deleted in Snipe-IT, or null if it has not been deleted. [DeserializeAs("deleted_at", DeserializeAs.Timestamp)] - public DateTime? DeletedAt { get ;set; } + public DateTime? DeletedAt { get; set; } /// [DeserializeAs("available_actions", DeserializeAs.AvailableActions)] diff --git a/SnipeSharp/Models/Submittable/StatusLabel.cs b/SnipeSharp/Models/Submittable/StatusLabel.cs index b7d64fd..bf6715b 100644 --- a/SnipeSharp/Models/Submittable/StatusLabel.cs +++ b/SnipeSharp/Models/Submittable/StatusLabel.cs @@ -1,6 +1,7 @@ -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models @@ -115,5 +116,10 @@ private void OnDeserialized(StreamingContext context) { ((IPatchable)this).SetAllModifiedState(false); } + + public static implicit operator StatusLabel(string v) + { + throw new NotImplementedException(); + } } } diff --git a/SnipeSharp/Models/Submittable/Supplier.cs b/SnipeSharp/Models/Submittable/Supplier.cs index 6c2726b..b63c3a0 100644 --- a/SnipeSharp/Models/Submittable/Supplier.cs +++ b/SnipeSharp/Models/Submittable/Supplier.cs @@ -1,7 +1,7 @@ -using System; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; using System.Runtime.Serialization; namespace SnipeSharp.Models diff --git a/SnipeSharp/Models/Submittable/User.cs b/SnipeSharp/Models/Submittable/User.cs index 99f825e..b3dbedc 100644 --- a/SnipeSharp/Models/Submittable/User.cs +++ b/SnipeSharp/Models/Submittable/User.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; -using SnipeSharp.Serialization; using SnipeSharp.EndPoint; using SnipeSharp.Models.Enumerations; +using SnipeSharp.Serialization; +using System; +using System.Collections.Generic; using System.Runtime.Serialization; namespace SnipeSharp.Models @@ -40,7 +40,8 @@ public Uri AvatarUrl /// Gets the user's name. /// This field cannot be used to set a user's name; it is constructed from the and by the API. [DeserializeAs("name")] - public override string Name { + public override string Name + { get => base.Name; set => base.Name = value; } diff --git a/SnipeSharp/Properties/AssemblyInfo.cs b/SnipeSharp/Properties/AssemblyInfo.cs index 9b583ff..a684a30 100644 --- a/SnipeSharp/Properties/AssemblyInfo.cs +++ b/SnipeSharp/Properties/AssemblyInfo.cs @@ -1,5 +1,5 @@ -using System.Resources; using System.Reflection; +using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/SnipeSharp/RestClientManager.cs b/SnipeSharp/RestClientManager.cs index 0955fff..6b7af9d 100644 --- a/SnipeSharp/RestClientManager.cs +++ b/SnipeSharp/RestClientManager.cs @@ -1,15 +1,15 @@ +using Newtonsoft.Json; using RestSharp; using RestSharp.Authenticators; +using SnipeSharp.Exceptions; using SnipeSharp.Filters; using SnipeSharp.Models; -using SnipeSharp.Exceptions; using SnipeSharp.Serialization; -using Newtonsoft.Json; using System.IO; -using System.Reflection; -using System.Text; using System.Linq; +using System.Reflection; using System.Runtime.Serialization; +using System.Text; namespace SnipeSharp { @@ -32,13 +32,13 @@ internal RestClientManager(SnipeItApi api, IRestClient client) internal void SetTokenAndUri() { - if(null == Api.Uri) + if (null == Api.Uri) throw new NullApiUriException(); - if(null == Api.Token) + if (null == Api.Token) throw new NullApiTokenException(); - if(null == Client.BaseUrl) + if (null == Client.BaseUrl) Client.BaseUrl = Api.Uri; - if(null == Client.Authenticator) + if (null == Client.Authenticator) Client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(Api.Token, "Bearer"); } @@ -50,13 +50,13 @@ internal void ResetUri() internal string GetRaw(string path) { var response = Client.Execute(new RestRequest(path)); - if(!response.IsSuccessful) + if (!response.IsSuccessful) throw new ApiErrorException(response.StatusCode, response.Content); return response.Content; } internal ApiOptionalResponse Get(string path, ISearchFilter filter = null) - where R: ApiObject + where R : ApiObject { var request = CreateRequest(path, Method.GET, filter); SetTokenAndUri(); @@ -65,14 +65,14 @@ internal ApiOptionalResponse Get(string path, ISearchFilter filter = null) Api.DebugList.Add(uri.ToString()); #endif var response = Client.Execute(request); - if(!response.IsSuccessful) + if (!response.IsSuccessful) throw new ApiErrorException(response.StatusCode, response.Content); #if DEBUG Api.DebugResponseList.Add(response); #endif var asRequestResponse = serializerDeserializer.Deserialize>(response); - if("error" == asRequestResponse.Status) + if ("error" == asRequestResponse.Status) { return new ApiOptionalResponse { @@ -85,26 +85,26 @@ internal ApiOptionalResponse Get(string path, ISearchFilter filter = null) return new ApiOptionalResponse { Value = serializerDeserializer.Deserialize(response) }; } - internal ApiOptionalMultiResponse GetAll(string path, ISearchFilter filter = null) where R: ApiObject + internal ApiOptionalMultiResponse GetAll(string path, ISearchFilter filter = null) where R : ApiObject { var result = Get>(path, filter); // if we couldn't find a result, don't try to get more. - if(!result.HasValue) + if (!result.HasValue) return result; var offset = filter?.Offset ?? 0; - if((null == filter?.Limit) && offset + result.Value.Count < result.Value.Total) + if ((null == filter?.Limit) && offset + result.Value.Count < result.Value.Total) { - if(null == filter) + if (null == filter) filter = new SearchFilter(); filter.Limit = 1000; filter.Offset = offset + result.Value.Count; - while(offset + result.Value.Count < result.Value.Total) + while (offset + result.Value.Count < result.Value.Total) { var batch = Get>(path, filter); - if(!batch.HasValue) + if (!batch.HasValue) return batch; - if(0 == batch.Value.Count) + if (0 == batch.Value.Count) throw new ApiReturnedInsufficientValuesForRequestException(); result.Value.AddRange(batch.Value.Rows); filter.Offset += batch.Value.Count; @@ -114,28 +114,28 @@ internal ApiOptionalMultiResponse GetAll(string path, ISearchFilter filter } internal ApiOptionalResponse> Post(string path, R obj) - where R: ApiObject + where R : ApiObject => ExecuteRequest(Method.POST, path, obj); internal ApiOptionalResponse> Post(string path, T obj) - where T: ApiObject - where R: ApiObject + where T : ApiObject + where R : ApiObject => ExecuteRequest(Method.POST, path, obj); internal ApiOptionalResponse> Put(string path, R obj) - where R: ApiObject + where R : ApiObject => ExecuteRequest(Method.PUT, path, obj); internal ApiOptionalResponse> Patch(string path, R obj) - where R: ApiObject + where R : ApiObject => ExecuteRequest(Method.PATCH, path, obj); internal ApiOptionalResponse> Delete(string path) - where R: ApiObject + where R : ApiObject => ExecuteRequest(Method.DELETE, path); private ApiOptionalResponse> ExecuteRequest(Method method, string path, ApiObject obj = null) - where R: ApiObject + where R : ApiObject { var request = CreateRequest(path, method, obj); SetTokenAndUri(); @@ -144,14 +144,14 @@ private ApiOptionalResponse> ExecuteRequest(Method method, Api.DebugList.Add(uri.ToString()); #endif var response = Client.Execute(request); - if(!response.IsSuccessful) + if (!response.IsSuccessful) throw new ApiErrorException(response.StatusCode, response.Content); #if DEBUG Api.DebugResponseList.Add(response); #endif var asRequestResponse = serializerDeserializer.Deserialize>(response); - if("error" == asRequestResponse.Status) + if ("error" == asRequestResponse.Status) { return new ApiOptionalResponse> { @@ -171,37 +171,38 @@ internal RestRequest CreateRequest(string path, Method method, object obj) JsonSerializer = serializerDeserializer }; - if(null == obj) + if (null == obj) return request; - if(Method.GET != method) + if (Method.GET != method) { request.AddJsonBody(obj); - #if DEBUG +#if DEBUG Api.DebugRequestList.Add(serializerDeserializer.Serialize(obj)); - #endif +#endif return request; } var type = obj.GetType(); - foreach(var property in type.GetProperties()) + foreach (var property in type.GetProperties()) { var attribute = property.GetCustomAttribute(inherit: false); - if(null == attribute) + if (null == attribute) continue; // don't need to bother with PatchAttribute because it only applies to Post and Put (this is Get). var value = property.GetValue(obj); - if(attribute.IsRequired && null == value) + if (attribute.IsRequired && null == value) throw new MissingRequiredFieldException(type.Name, property.Name); - if(null == value) + if (null == value) // early-out, don't try to use converter, don't add parameter continue; - if(SerializationContractResolver.TryGetConverter(property, attribute, out var converter)) + if (SerializationContractResolver.TryGetConverter(property, attribute, out var converter)) { var stringBuilder = new StringBuilder(); - using(var stringWriter = new StringWriter(stringBuilder)) - using(var jsonWriter = new JsonTextWriter(stringWriter)) + using (var stringWriter = new StringWriter(stringBuilder)) + using (var jsonWriter = new JsonTextWriter(stringWriter)) converter.WriteJson(jsonWriter, value, NewtonsoftJsonSerializer.Serializer); value = stringBuilder.ToString(); - } else if(value.GetType().IsEnum && null != value.GetType().GetCustomAttribute()) + } + else if (value.GetType().IsEnum && null != value.GetType().GetCustomAttribute()) { value = value.GetType().GetMember(value.ToString(), BindingFlags.Static | BindingFlags.Public).FirstOrDefault() ?.GetCustomAttribute()?.Value diff --git a/SnipeSharp/Serialization/Converters/AvailableActionsConverter.cs b/SnipeSharp/Serialization/Converters/AvailableActionsConverter.cs index 2fccc6a..5036343 100644 --- a/SnipeSharp/Serialization/Converters/AvailableActionsConverter.cs +++ b/SnipeSharp/Serialization/Converters/AvailableActionsConverter.cs @@ -1,7 +1,7 @@ +using Newtonsoft.Json; +using SnipeSharp.Models.Enumerations; using System; using System.Collections.Generic; -using SnipeSharp.Models.Enumerations; -using Newtonsoft.Json; namespace SnipeSharp.Serialization.Converters { @@ -12,9 +12,9 @@ public override AvailableAction ReadJson(JsonReader reader, Type objectType, Ava { var dictionary = serializer.Deserialize>(reader); var set = AvailableAction.None; - if(null != dictionary) - foreach(var pair in dictionary) - if(pair.Value) + if (null != dictionary) + foreach (var pair in dictionary) + if (pair.Value) set |= pair.Key; return set; } diff --git a/SnipeSharp/Serialization/Converters/CustomFieldDictionaryConverter.cs b/SnipeSharp/Serialization/Converters/CustomFieldDictionaryConverter.cs index bb71784..54fa09a 100644 --- a/SnipeSharp/Serialization/Converters/CustomFieldDictionaryConverter.cs +++ b/SnipeSharp/Serialization/Converters/CustomFieldDictionaryConverter.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; using Newtonsoft.Json; using SnipeSharp.Collections; using SnipeSharp.Models; +using System; +using System.Collections.Generic; namespace SnipeSharp.Serialization.Converters { @@ -12,17 +12,18 @@ internal sealed class CustomFieldDictionaryConverter : JsonConverter>(reader); - if(null == values) + if (null == values) throw new NullReferenceException("Failed to deserialize AssetCustomField dictionary"); var dictionary = new CustomFieldDictionary(); - foreach(var pair in values) + foreach (var pair in values) { pair.Value.FriendlyName = pair.Key; dictionary.Add(pair.Value); diff --git a/SnipeSharp/Serialization/Converters/DateObjectConverter.cs b/SnipeSharp/Serialization/Converters/DateObjectConverter.cs index 4b47c0d..a85f1c0 100644 --- a/SnipeSharp/Serialization/Converters/DateObjectConverter.cs +++ b/SnipeSharp/Serialization/Converters/DateObjectConverter.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json; +using System; namespace SnipeSharp.Serialization.Converters { @@ -9,13 +9,19 @@ internal sealed class DateObjectConverter : JsonConverter public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer) { - if(reader.TokenType == JsonToken.String) + if (reader.TokenType == JsonToken.String) { // This is probably one of the broken API endpoints that returns the model directly // instead of properly transforming it. - if(serializer.Deserialize(reader) is string response && DateTime.TryParse(response, out var datetime)) + if (serializer.Deserialize(reader) is string response && DateTime.TryParse(response, out var datetime)) + return datetime; + } + else if (reader.TokenType == JsonToken.Date) + { + if (serializer.Deserialize(reader) is DateTime response && DateTime.TryParse(response.ToString(), out var datetime)) return datetime; - } else if(serializer.Deserialize(reader) is DateObjectResponse response && DateTime.TryParse(response.DateTime, out var datetime)) + } + else if (serializer.Deserialize(reader) is DateObjectResponse response && DateTime.TryParse(response.DateTime, out var datetime)) return datetime; return null; } diff --git a/SnipeSharp/Serialization/Converters/MaybeFalseUriConverter.cs b/SnipeSharp/Serialization/Converters/MaybeFalseUriConverter.cs index 933bea2..e968238 100644 --- a/SnipeSharp/Serialization/Converters/MaybeFalseUriConverter.cs +++ b/SnipeSharp/Serialization/Converters/MaybeFalseUriConverter.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json; +using System; namespace SnipeSharp.Serialization.Converters { @@ -9,12 +9,12 @@ internal sealed class MaybeFalseUriConverter : JsonConverter public override Uri ReadJson(JsonReader reader, Type objectType, Uri existingValue, bool hasExistingValue, JsonSerializer serializer) { var obj = serializer.Deserialize(reader) as string; - if(null == obj) + if (null == obj) return null; return new Uri(obj); } - public override void WriteJson(JsonWriter writer, Uri value, JsonSerializer serializer) + public override void WriteJson(JsonWriter writer, Uri value, JsonSerializer serializer) => throw new NotImplementedException(); } } diff --git a/SnipeSharp/Serialization/Converters/MonthStringToIntConverter.cs b/SnipeSharp/Serialization/Converters/MonthStringToIntConverter.cs index 1b36101..8dac093 100644 --- a/SnipeSharp/Serialization/Converters/MonthStringToIntConverter.cs +++ b/SnipeSharp/Serialization/Converters/MonthStringToIntConverter.cs @@ -11,10 +11,10 @@ internal sealed class MonthStringToIntConverter : JsonConverter { // from DepreciationsTransformer.php, month strings are created in the form $"{monthInteger} {translate("general.months")}" var str = serializer.Deserialize(reader); - if(null == str || str == "None") + if (null == str || str == "None") // in AssetModelsTransformer.php, if there is no eol, the string "None" is returned rather than null. return null; - if(int.TryParse(str.Split(' ')[0], out var asInt)) + if (int.TryParse(str.Split(' ')[0], out var asInt)) return asInt; return null; } diff --git a/SnipeSharp/Serialization/Converters/NullableBooleanConverter.cs b/SnipeSharp/Serialization/Converters/NullableBooleanConverter.cs index a845c49..86e757c 100644 --- a/SnipeSharp/Serialization/Converters/NullableBooleanConverter.cs +++ b/SnipeSharp/Serialization/Converters/NullableBooleanConverter.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json; +using System; namespace SnipeSharp.Serialization.Converters { @@ -11,7 +11,7 @@ internal sealed class NullableBooleanConverter : JsonConverter public override void WriteJson(JsonWriter writer, bool? value, JsonSerializer serializer) { - if(null == value) + if (null == value) writer.WriteNull(); else writer.WriteRawValue((bool)value ? "true" : "false"); diff --git a/SnipeSharp/Serialization/Converters/PermissionDictionaryConverter.cs b/SnipeSharp/Serialization/Converters/PermissionDictionaryConverter.cs index 796ab39..05f908d 100644 --- a/SnipeSharp/Serialization/Converters/PermissionDictionaryConverter.cs +++ b/SnipeSharp/Serialization/Converters/PermissionDictionaryConverter.cs @@ -1,6 +1,6 @@ +using Newtonsoft.Json; using System; using System.Collections.Generic; -using Newtonsoft.Json; namespace SnipeSharp.Serialization { @@ -11,9 +11,9 @@ public override Dictionary ReadJson(JsonReader reader, Type object { var rawDictionary = serializer.Deserialize>(reader); var newDictionary = new Dictionary(); - if(null != rawDictionary) + if (null != rawDictionary) { - foreach(var pair in rawDictionary) + foreach (var pair in rawDictionary) { newDictionary[pair.Key] = pair.Value != 0; } diff --git a/SnipeSharp/Serialization/Converters/ReadOnlyResponseCollectionConverter.cs b/SnipeSharp/Serialization/Converters/ReadOnlyResponseCollectionConverter.cs index 8eb2114..de770a5 100644 --- a/SnipeSharp/Serialization/Converters/ReadOnlyResponseCollectionConverter.cs +++ b/SnipeSharp/Serialization/Converters/ReadOnlyResponseCollectionConverter.cs @@ -11,10 +11,10 @@ internal sealed class ReadOnlyResponseCollectionConverter : JsonConverter public override bool CanConvert(Type objectType) { - if(objectType.IsGenericType && typeof(IReadOnlyCollection<>) == objectType.GetGenericTypeDefinition()) + if (objectType.IsGenericType && typeof(IReadOnlyCollection<>) == objectType.GetGenericTypeDefinition()) return true; - foreach(var a in objectType.GetInterfaces()) - if(a.IsGenericType && typeof(IReadOnlyCollection<>) == a.GetGenericTypeDefinition()) + foreach (var a in objectType.GetInterfaces()) + if (a.IsGenericType && typeof(IReadOnlyCollection<>) == a.GetGenericTypeDefinition()) return true; return false; } diff --git a/SnipeSharp/Serialization/Converters/SerializeToIdArrayConverter.cs b/SnipeSharp/Serialization/Converters/SerializeToIdArrayConverter.cs index 7259b6e..7487cfa 100644 --- a/SnipeSharp/Serialization/Converters/SerializeToIdArrayConverter.cs +++ b/SnipeSharp/Serialization/Converters/SerializeToIdArrayConverter.cs @@ -1,6 +1,6 @@ -using System; using Newtonsoft.Json; using SnipeSharp.Models; +using System; namespace SnipeSharp.Serialization.Converters { @@ -8,13 +8,13 @@ internal sealed class SerializeToIdArrayConverter : JsonConverter (AbstractBaseModel[]) serializer.Deserialize(reader); + => (AbstractBaseModel[])serializer.Deserialize(reader); public override void WriteJson(JsonWriter writer, AbstractBaseModel[] value, JsonSerializer serializer) { writer.WriteStartArray(); - if(null != value) - foreach(var item in value) + if (null != value) + foreach (var item in value) writer.WriteValue(item.Id); writer.WriteEndArray(); } diff --git a/SnipeSharp/Serialization/Converters/SerializeToIdConverter.cs b/SnipeSharp/Serialization/Converters/SerializeToIdConverter.cs index 025a75f..8fb1914 100644 --- a/SnipeSharp/Serialization/Converters/SerializeToIdConverter.cs +++ b/SnipeSharp/Serialization/Converters/SerializeToIdConverter.cs @@ -1,6 +1,6 @@ -using System; using Newtonsoft.Json; using SnipeSharp.Models; +using System; namespace SnipeSharp.Serialization.Converters { @@ -11,7 +11,7 @@ public override IObjectWithId ReadJson(JsonReader reader, Type objectType, IObje => throw new NotImplementedException(); public override void WriteJson(JsonWriter writer, IObjectWithId value, JsonSerializer serializer) { - if(null == value) + if (null == value) writer.WriteNull(); else writer.WriteValue(value.Id); diff --git a/SnipeSharp/Serialization/Converters/SimpleDateConverter.cs b/SnipeSharp/Serialization/Converters/SimpleDateConverter.cs index fe022fa..6e2641d 100644 --- a/SnipeSharp/Serialization/Converters/SimpleDateConverter.cs +++ b/SnipeSharp/Serialization/Converters/SimpleDateConverter.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json; +using System; namespace SnipeSharp.Serialization.Converters { @@ -10,14 +10,14 @@ internal sealed class SimpleDateConverter : JsonConverter public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer) { var str = serializer.Deserialize(reader); - if(!string.IsNullOrWhiteSpace(str) && DateTime.TryParse(str, out var datetime)) + if (!string.IsNullOrWhiteSpace(str) && DateTime.TryParse(str, out var datetime)) return datetime; return null; } public override void WriteJson(JsonWriter writer, DateTime? value, JsonSerializer serializer) { - if(null == value) + if (null == value) writer.WriteNull(); else // value used for checkout_at in app/Http/Controllers/Api/AssetsController.php#checkout(AssetCheckoutRequest,int) diff --git a/SnipeSharp/Serialization/Converters/TimeSpanConverter.cs b/SnipeSharp/Serialization/Converters/TimeSpanConverter.cs index e55254b..d2e64e9 100644 --- a/SnipeSharp/Serialization/Converters/TimeSpanConverter.cs +++ b/SnipeSharp/Serialization/Converters/TimeSpanConverter.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json; +using System; namespace SnipeSharp.Serialization.Converters { @@ -10,14 +10,14 @@ internal sealed class TimeSpanConverter : JsonConverter public override TimeSpan? ReadJson(JsonReader reader, Type objectType, TimeSpan? existingValue, bool hasExistingValue, JsonSerializer serializer) { var days = serializer.Deserialize(reader); - if(null == days) + if (null == days) return null; return new TimeSpan(days.Value, 0, 0, 0); } public override void WriteJson(JsonWriter writer, TimeSpan? value, JsonSerializer serializer) { - if(null == value) + if (null == value) writer.WriteNull(); else writer.WriteValue(value.Value.Days); diff --git a/SnipeSharp/Serialization/Converters/TimestampConverter.cs b/SnipeSharp/Serialization/Converters/TimestampConverter.cs index d93517b..c042dff 100644 --- a/SnipeSharp/Serialization/Converters/TimestampConverter.cs +++ b/SnipeSharp/Serialization/Converters/TimestampConverter.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json; +using System; namespace SnipeSharp.Serialization.Converters { @@ -9,14 +9,22 @@ internal sealed class TimestampConverter : JsonConverter public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer) { - if(reader.TokenType == JsonToken.String) + if (reader.TokenType == JsonToken.String) { // This is probably one of the broken API endpoints that returns the model directly // instead of properly transforming it. - if(serializer.Deserialize(reader) is string response && DateTime.TryParse(response, out var datetime)) + if (serializer.Deserialize(reader) is string response && DateTime.TryParse(response, out var datetime)) + return datetime; + } + else if (reader.TokenType == JsonToken.Date) + { + if (serializer.Deserialize(reader) is DateTime response && DateTime.TryParse(response.ToString(), out var datetime)) return datetime; - } else if(serializer.Deserialize(reader) is TimestampResponse response && DateTime.TryParse(response.DateTime, out var datetime)) + } + else if (serializer.Deserialize(reader) is TimestampResponse response && DateTime.TryParse(response.DateTime, out var datetime)) return datetime; + + return null; } diff --git a/SnipeSharp/Serialization/DeserializationContractResolver.cs b/SnipeSharp/Serialization/DeserializationContractResolver.cs index 3e18e85..05d994a 100644 --- a/SnipeSharp/Serialization/DeserializationContractResolver.cs +++ b/SnipeSharp/Serialization/DeserializationContractResolver.cs @@ -13,11 +13,11 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ { var property = base.CreateProperty(member, memberSerialization); var attribute = member.GetCustomAttribute(inherit: false); - if(null != attribute) + if (null != attribute) { property.PropertyName = attribute.Key; property.Writable = true; - switch(attribute.DeserializeAs) + switch (attribute.DeserializeAs) { case DeserializeAs.Default: break; @@ -52,7 +52,8 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ property.Converter = PermissionDictionaryConverter.Instance; break; } - } else + } + else { property.Ignored = true; } @@ -64,8 +65,8 @@ protected override List GetSerializableMembers(Type objectType) // start with the defaults var list = base.GetSerializableMembers(objectType); // add non-public, readable, serializable properties - foreach(var member in objectType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)) - if(member.CanWrite) + foreach (var member in objectType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)) + if (member.CanWrite) list.Add(member); return list; } diff --git a/SnipeSharp/Serialization/DeserializeAsAttribute.cs b/SnipeSharp/Serialization/DeserializeAsAttribute.cs index e82aa65..c20ee28 100644 --- a/SnipeSharp/Serialization/DeserializeAsAttribute.cs +++ b/SnipeSharp/Serialization/DeserializeAsAttribute.cs @@ -10,7 +10,7 @@ internal sealed class DeserializeAsAttribute : Attribute internal DeserializeAsAttribute(string key, DeserializeAs deserializationType = DeserializeAs.Default) { - if(string.IsNullOrEmpty(key)) + if (string.IsNullOrEmpty(key)) throw new ArgumentException("Key cannot be null or empty.", paramName: nameof(key)); Key = key; DeserializeAs = deserializationType; diff --git a/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs b/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs index 9836b6a..410ce78 100644 --- a/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs +++ b/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs @@ -1,7 +1,7 @@ using Newtonsoft.Json; using RestSharp; -using RestSharp.Serializers; using RestSharp.Deserializers; +using RestSharp.Serializers; namespace SnipeSharp.Serialization { @@ -13,13 +13,15 @@ internal sealed class NewtonsoftJsonSerializer : ISerializer, IDeserializer public string Namespace { get; set; } public static JsonSerializerSettings SerializerSettings { get; } = - new JsonSerializerSettings { + new JsonSerializerSettings + { ContractResolver = new SerializationContractResolver(), NullValueHandling = NullValueHandling.Ignore }; public static JsonSerializerSettings DeserializerSettings { get; } = - new JsonSerializerSettings { + new JsonSerializerSettings + { ContractResolver = new DeserializationContractResolver() }; diff --git a/SnipeSharp/Serialization/SerializationContractResolver.cs b/SnipeSharp/Serialization/SerializationContractResolver.cs index 96f6e7b..8180017 100644 --- a/SnipeSharp/Serialization/SerializationContractResolver.cs +++ b/SnipeSharp/Serialization/SerializationContractResolver.cs @@ -9,15 +9,15 @@ internal sealed class SerializationContractResolver : DefaultContractResolver { public static bool TryGetConverter(PropertyInfo property, SerializeAsAttribute fieldConverter, out JsonConverter converter) { - switch(fieldConverter.SerializeAs) + switch (fieldConverter.SerializeAs) { case SerializeAs.Default: - if(null == property) + if (null == property) { converter = null; return false; } - if(property.PropertyType.IsAssignableFrom(typeof(bool?))) + if (property.PropertyType.IsAssignableFrom(typeof(bool?))) { converter = NullableBooleanConverter.Instance; return true; @@ -46,15 +46,15 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ { var property = base.CreateProperty(member, memberSerialization); var attribute = member.GetCustomAttribute(inherit: false); - if((null != attribute && !string.IsNullOrEmpty(attribute.Key))) + if ((null != attribute && !string.IsNullOrEmpty(attribute.Key))) { property.PropertyName = attribute.Key; property.Readable = true; var patch = member.GetCustomAttribute(true); - if(null != patch) + if (null != patch) { var targetField = member.DeclaringType.GetField(patch.IndicatorFieldName, BindingFlags.Instance | BindingFlags.NonPublic); - if(null != targetField) + if (null != targetField) property.ShouldSerialize = (instance) => (bool)targetField.GetValue(instance); else { @@ -62,9 +62,10 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ property.ShouldSerialize = (instance) => (bool)targetProperty.GetValue(instance); } } - if(TryGetConverter(member as PropertyInfo, attribute, out var converter)) + if (TryGetConverter(member as PropertyInfo, attribute, out var converter)) property.Converter = converter; - } else + } + else { property.Ignored = true; } diff --git a/SnipeSharp/Serialization/SerializeAsAttribute.cs b/SnipeSharp/Serialization/SerializeAsAttribute.cs index 94dfa50..80696cb 100644 --- a/SnipeSharp/Serialization/SerializeAsAttribute.cs +++ b/SnipeSharp/Serialization/SerializeAsAttribute.cs @@ -12,7 +12,7 @@ internal sealed class SerializeAsAttribute : Attribute internal SerializeAsAttribute(string key, SerializeAs serializationType = SerializeAs.Default) { - if(string.IsNullOrEmpty(key)) + if (string.IsNullOrEmpty(key)) throw new ArgumentException("Key cannot be null or empty.", paramName: nameof(key)); Key = key; SerializeAs = serializationType; diff --git a/SnipeSharp/SnipeItApi.cs b/SnipeSharp/SnipeItApi.cs index e6a5e9c..b6cc094 100644 --- a/SnipeSharp/SnipeItApi.cs +++ b/SnipeSharp/SnipeItApi.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; using RestSharp; using SnipeSharp.EndPoint; using SnipeSharp.Models; +using System; +using System.Collections.Generic; namespace SnipeSharp { @@ -74,7 +74,8 @@ public bool TestConnection() { RequestManager.SetTokenAndUri(); Users.Me(); - } catch + } + catch { // any other error return false return false; @@ -92,9 +93,9 @@ public bool TestConnection() /// /// A AbstractBaseModel with the attribute PathSegmentAttribute. /// An EndPoint for the provided type. - public EndPoint GetEndPoint() where T: AbstractBaseModel + public EndPoint GetEndPoint() where T : AbstractBaseModel { - if(_typeEndPointObjectMap.TryGetValue(typeof(T), out var endpoint)) + if (_typeEndPointObjectMap.TryGetValue(typeof(T), out var endpoint)) return (EndPoint)endpoint; throw new ArgumentException("Unrecognized end point type", nameof(T), null); } diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index a42ad14..5a8a873 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -10,6 +10,6 @@ - + From 6e9a052257588dd27a6318d6b667c740b5229f26 Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Thu, 27 Apr 2023 13:52:02 -0500 Subject: [PATCH 03/14] Add ability to filter GetAllOptional --- SnipeSharp/EndPoint/EndPoint.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SnipeSharp/EndPoint/EndPoint.cs b/SnipeSharp/EndPoint/EndPoint.cs index d3d8174..e50b694 100644 --- a/SnipeSharp/EndPoint/EndPoint.cs +++ b/SnipeSharp/EndPoint/EndPoint.cs @@ -103,6 +103,10 @@ public ResponseCollection GetAll() public ApiOptionalMultiResponse GetAllOptional() => FindAllOptional(); + /// + public ApiOptionalMultiResponse GetAllOptional(ISearchFilter filter = null) + => FindAllOptional(filter); + /// public T Create(T toCreate) => Api.RequestManager.Post(EndPointInfo.BaseUri, CheckRequiredFields(toCreate)).RethrowExceptionIfAny().Value.Payload; From 30694df4ccbdec1dacf4230fda40f05f844ef0c7 Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Thu, 27 Apr 2023 13:52:39 -0500 Subject: [PATCH 04/14] Changed Email filter to filter based on email rather than the fuzzy search --- SnipeSharp/EndPoint/UserEndPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnipeSharp/EndPoint/UserEndPoint.cs b/SnipeSharp/EndPoint/UserEndPoint.cs index 6179b11..aeda252 100644 --- a/SnipeSharp/EndPoint/UserEndPoint.cs +++ b/SnipeSharp/EndPoint/UserEndPoint.cs @@ -85,7 +85,7 @@ public ApiOptionalResponse GetByUserNameOptional(string username, UserSear public ApiOptionalResponse GetByEmailAddressOptional(string email, UserSearchFilter filter = null) { filter = filter ?? new UserSearchFilter(); - filter.Search = email; + filter.Email = email; var results = FindAllOptional(filter); if (!results.HasValue) return new ApiOptionalResponse { Exception = results.Exception }; From 395425db454446bc5db98f055d196cf8cb60b27c Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Thu, 27 Apr 2023 13:53:04 -0500 Subject: [PATCH 05/14] Added additional filter columns to the User filter --- SnipeSharp/Filters/UserSearchFilter.cs | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/SnipeSharp/Filters/UserSearchFilter.cs b/SnipeSharp/Filters/UserSearchFilter.cs index fc6d1d3..7b50745 100644 --- a/SnipeSharp/Filters/UserSearchFilter.cs +++ b/SnipeSharp/Filters/UserSearchFilter.cs @@ -1,5 +1,6 @@ using SnipeSharp.Models; using SnipeSharp.Serialization; +using System; namespace SnipeSharp.Filters { @@ -20,6 +21,14 @@ public sealed class UserSearchFilter : ISortableSearchFilter [SerializeAs("search")] public string Search { get; set; } + /// + [SerializeAs("username")] + public string Username { get; set; } + + /// + [SerializeAs("email")] + public string Email { get; set; } + /// [SerializeAs("sort")] public UserSearchColumn? SortColumn { get; set; } @@ -58,6 +67,24 @@ public sealed class UserSearchFilter : ISortableSearchFilter [SerializeAs("department_id", SerializeAs.IdValue)] public Department Department { get; set; } + /// + /// Only search for users with the ldap_import + /// + public bool LdapImport { private get; set; } + + /// + /// Only search for users with the ldap_import + /// + [SerializeAs("ldap_import")] + public int _ldapImport + { + get + { + return Convert.ToInt32(LdapImport); + } + } + + /// /// Initialize a new instance of the UserSearchFilter class. /// From b7bf34a5c97909e0a86e8f1a13125c3a878a8bc1 Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Thu, 31 Aug 2023 11:51:47 -0500 Subject: [PATCH 06/14] All updates - this is a mess! --- SnipeSharp/Filters/UserSearchFilter.cs | 10 +++++++--- .../Serialization/Converters/DateObjectConverter.cs | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/SnipeSharp/Filters/UserSearchFilter.cs b/SnipeSharp/Filters/UserSearchFilter.cs index 7b50745..449dbca 100644 --- a/SnipeSharp/Filters/UserSearchFilter.cs +++ b/SnipeSharp/Filters/UserSearchFilter.cs @@ -70,17 +70,21 @@ public sealed class UserSearchFilter : ISortableSearchFilter /// /// Only search for users with the ldap_import /// - public bool LdapImport { private get; set; } + public bool? LdapImport { private get; set; } = null; /// /// Only search for users with the ldap_import /// [SerializeAs("ldap_import")] - public int _ldapImport + public int? _ldapImport { get { - return Convert.ToInt32(LdapImport); + int? returnVal = null; + if (LdapImport != null) + returnVal = Convert.ToInt32(LdapImport); + + return returnVal; } } diff --git a/SnipeSharp/Serialization/Converters/DateObjectConverter.cs b/SnipeSharp/Serialization/Converters/DateObjectConverter.cs index a85f1c0..c360b23 100644 --- a/SnipeSharp/Serialization/Converters/DateObjectConverter.cs +++ b/SnipeSharp/Serialization/Converters/DateObjectConverter.cs @@ -21,6 +21,10 @@ internal sealed class DateObjectConverter : JsonConverter if (serializer.Deserialize(reader) is DateTime response && DateTime.TryParse(response.ToString(), out var datetime)) return datetime; } + else if (reader.TokenType == JsonToken.Integer) + { + return null; + } else if (serializer.Deserialize(reader) is DateObjectResponse response && DateTime.TryParse(response.DateTime, out var datetime)) return datetime; return null; From 76d4ea99aca6ca1da1eddbbb2bb90202cd240deb Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Wed, 24 Apr 2024 10:15:31 -0500 Subject: [PATCH 07/14] Issue-2: Added a date only export option to handle insert --- SnipeSharp/Models/Submittable/Maintenance.cs | 4 +-- .../Converters/SimpleDateOnlyConverter.cs | 28 +++++++++++++++++++ .../SerializationContractResolver.cs | 3 ++ .../Serialization/SerializeAsAttribute.cs | 2 ++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 SnipeSharp/Serialization/Converters/SimpleDateOnlyConverter.cs diff --git a/SnipeSharp/Models/Submittable/Maintenance.cs b/SnipeSharp/Models/Submittable/Maintenance.cs index 607d645..132c66d 100644 --- a/SnipeSharp/Models/Submittable/Maintenance.cs +++ b/SnipeSharp/Models/Submittable/Maintenance.cs @@ -145,7 +145,7 @@ public bool? IsWarranty /// Gets/sets the date the maintenance begins. [DeserializeAs("start_date", DeserializeAs.DateObject)] - [SerializeAs("start_date", SerializeAs.SimpleDate, IsRequired = true)] + [SerializeAs("start_date", SerializeAs.SimpleDateOnly, IsRequired = true)] [Patch(nameof(isStartDateModified))] public DateTime? StartDate { @@ -165,7 +165,7 @@ public DateTime? StartDate /// Gets/sets the date the maintenance ends. [DeserializeAs("completion_date", DeserializeAs.DateObject)] - [SerializeAs("completion_date", SerializeAs.SimpleDate)] + [SerializeAs("completion_date", SerializeAs.SimpleDateOnly)] [Patch(nameof(isCompletionDateModified))] public DateTime? CompletionDate { diff --git a/SnipeSharp/Serialization/Converters/SimpleDateOnlyConverter.cs b/SnipeSharp/Serialization/Converters/SimpleDateOnlyConverter.cs new file mode 100644 index 0000000..cf2a3ad --- /dev/null +++ b/SnipeSharp/Serialization/Converters/SimpleDateOnlyConverter.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; +using System; + +namespace SnipeSharp.Serialization.Converters +{ + internal sealed class SimpleDateOnlyConverter : JsonConverter + { + public static readonly SimpleDateOnlyConverter Instance = new SimpleDateOnlyConverter(); + + public override DateTime? ReadJson(JsonReader reader, Type objectType, DateTime? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var str = serializer.Deserialize(reader); + if (!string.IsNullOrWhiteSpace(str) && DateTime.TryParse(str, out var datetime)) + return datetime; + return null; + } + + public override void WriteJson(JsonWriter writer, DateTime? value, JsonSerializer serializer) + { + if (null == value) + writer.WriteNull(); + else + // value used for checkout_at in app/Http/Controllers/Api/AssetsController.php#checkout(AssetCheckoutRequest,int) + // is of the form 'Y-m-d H:i:s'; I assume expected_checkin is the same, so we'll use this for it -- @cofl + writer.WriteValue(value.Value.ToString("yyyy-MM-dd")); + } + } +} diff --git a/SnipeSharp/Serialization/SerializationContractResolver.cs b/SnipeSharp/Serialization/SerializationContractResolver.cs index 8180017..7d823ba 100644 --- a/SnipeSharp/Serialization/SerializationContractResolver.cs +++ b/SnipeSharp/Serialization/SerializationContractResolver.cs @@ -28,6 +28,9 @@ public static bool TryGetConverter(PropertyInfo property, SerializeAsAttribute f case SerializeAs.SimpleDate: converter = SimpleDateConverter.Instance; return true; + case SerializeAs.SimpleDateOnly: + converter = SimpleDateOnlyConverter.Instance; + return true; case SerializeAs.Timespan: converter = TimeSpanConverter.Instance; return true; diff --git a/SnipeSharp/Serialization/SerializeAsAttribute.cs b/SnipeSharp/Serialization/SerializeAsAttribute.cs index 80696cb..5a6cd8a 100644 --- a/SnipeSharp/Serialization/SerializeAsAttribute.cs +++ b/SnipeSharp/Serialization/SerializeAsAttribute.cs @@ -28,6 +28,8 @@ internal enum SerializeAs SimpleDate, + SimpleDateOnly, + Timespan, IdValue, From 1c7e6c3b8e38dc4a23f6f45a62be6935e9ce65e9 Mon Sep 17 00:00:00 2001 From: rlouch2 Date: Wed, 24 Apr 2024 10:16:48 -0500 Subject: [PATCH 08/14] Issue-1: Update to dotnet 8.0 Upgrade of RestSharp to new version Change of class calls to accomdate breaking call changes in RestSharp and how things are setup. --- .../SnipeSharp.PowerShell.csproj | 4 +- SnipeSharp.Tests/MockClient.cs | 103 +++++++++--------- SnipeSharp.Tests/SnipeSharp.Tests.csproj | 3 +- SnipeSharp.Tests/Utility.cs | 2 +- SnipeSharp/RestClientManager.cs | 64 ++++++----- .../Serialization/NewtonsoftJsonSerializer.cs | 8 +- SnipeSharp/SnipeItApi.cs | 25 ++--- SnipeSharp/SnipeSharp.csproj | 6 +- test/SnipeSharp.Test/SnipeSharp.Test.csproj | 2 +- 9 files changed, 117 insertions(+), 100 deletions(-) diff --git a/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj b/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj index 96e1d2d..eadaaeb 100644 --- a/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj +++ b/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj @@ -2,7 +2,7 @@ - netstandard2.0 + netstandard2.1 library SnipeSharp.PowerShell false @@ -12,7 +12,7 @@ - + diff --git a/SnipeSharp.Tests/MockClient.cs b/SnipeSharp.Tests/MockClient.cs index 7e47f88..ee10c08 100644 --- a/SnipeSharp.Tests/MockClient.cs +++ b/SnipeSharp.Tests/MockClient.cs @@ -10,12 +10,13 @@ using System.Threading.Tasks; using RestSharp; using RestSharp.Authenticators; -using RestSharp.Deserializers; -using RestSharp.Serialization; +using RestSharp.Serializers; +//using RestSharp.Deserializers; +//using RestSharp.Serialization; namespace SnipeSharp.Tests { - internal sealed class FakeResponse : IRestResponse + internal sealed class FakeResponse : RestResponse { internal static FakeResponse FromFile(string path, bool isSuccessful = true, HttpStatusCode? statusCode = null) => new FakeResponse(null == path ? string.Empty : File.ReadAllText(path), isSuccessful, statusCode); @@ -27,7 +28,7 @@ public FakeResponse(string content, bool isSuccessful = true, HttpStatusCode? st if(statusCode.HasValue) StatusCode = statusCode.Value; } - public IRestRequest Request { get; set; } + public RestRequest Request { get; set; } public string ContentType { get; set; } public long ContentLength { get; set; } public string ContentEncoding { get; set; } @@ -38,7 +39,7 @@ public FakeResponse(string content, bool isSuccessful = true, HttpStatusCode? st public byte[] RawBytes { get; set; } public Uri ResponseUri { get; set; } public string Server { get; set; } - public IList Cookies => throw new NotImplementedException(); + //public IList Cookies => throw new NotImplementedException(); public IList Headers => throw new NotImplementedException(); public ResponseStatus ResponseStatus { get; set; } public string ErrorMessage { get; set; } @@ -48,20 +49,22 @@ public FakeResponse(string content, bool isSuccessful = true, HttpStatusCode? st internal sealed class FakeRequest { - internal IRestRequest Request; + internal RestRequest Request; internal string Body; internal Method Method; internal Dictionary Headers = new Dictionary(); } - internal sealed class FakeRestClient : IRestClient + internal sealed class FakeRestClient : RestClient { - internal readonly Queue Responses = new Queue(); + internal readonly Queue Responses = new Queue(); internal readonly LinkedList Requests = new LinkedList(); - public IRestResponse Response { get => Responses.Dequeue(); set {} } + private IAuthenticator authenticator; + + public RestResponse Response { get => Responses.Dequeue(); set {} } public string UserAgent { get; set; } = "StubRestClient"; - public IRestResponse Execute(IRestRequest request) => Execute(request, request.Method); - public IRestResponse Execute(IRestRequest request, Method httpMethod) + public RestResponse Execute(RestRequest request) => Execute(request, request.Method); + public RestResponse Execute(RestRequest request, Method httpMethod) { var fakeRequest = new FakeRequest { Request = request, @@ -80,7 +83,7 @@ public IRestResponse Execute(IRestRequest request, Method httpMethod) Requests.AddFirst(fakeRequest); return Response; } - public Uri BuildUri(IRestRequest request) => Utility.TEST_URI; + public Uri BuildUri(RestRequest request) => Utility.TEST_URI; public CookieContainer CookieContainer { get; set; } = new CookieContainer(); public bool AutomaticDecompression { get; set; } = false; @@ -88,14 +91,14 @@ public IRestResponse Execute(IRestRequest request, Method httpMethod) public int Timeout { get; set; } = int.MaxValue; public int ReadWriteTimeout { get; set; } = int.MaxValue; public bool UseSynchronizationContext { get; set; } = false; - public IAuthenticator Authenticator { get; set; } + public new IAuthenticator Authenticator { get => authenticator; set => authenticator = value; } public Uri BaseUrl { get; set; } public Encoding Encoding { get; set; } = Encoding.UTF8; public bool FailOnDeserializationError { get; set; } = true; public string ConnectionGroupName { get; set; } public bool PreAuthenticate { get; set; } = false; public bool UnsafeAuthenticatedConnectionSharing { get; set; } = false; - public IList DefaultParameters { get; set; } = new List(); + public new IList DefaultParameters { get; set; } = new List(); public string BaseHost { get; set; } public bool AllowMultipleDefaultParametersWithSameName { get; set; } = false; @@ -106,110 +109,110 @@ public IRestResponse Execute(IRestRequest request, Method httpMethod) public bool FollowRedirects { get; set; } = false; public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } - public void AddHandler(string contentType, IDeserializer deserializer) - => throw new NotImplementedException(); + //public void AddHandler(string contentType, R deserializer) + // => throw new NotImplementedException(); - public void AddHandler(string contentType, Func deserializerFactory) - => throw new NotImplementedException(); + //public void AddHandler(string contentType, Func deserializerFactory) + // => throw new NotImplementedException(); - public string BuildUriWithoutQueryParameters(IRestRequest request) + public string BuildUriWithoutQueryParameters(RestRequest request) => throw new NotImplementedException(); public void ClearHandlers(){} public void ConfigureWebRequest(Action configurator){} - public IRestResponse Deserialize(IRestResponse response) + public RestResponse Deserialize(RestResponse response) => throw new NotImplementedException(); - public byte[] DownloadData(IRestRequest request) + public byte[] DownloadData(RestRequest request) => throw new NotImplementedException(); - public byte[] DownloadData(IRestRequest request, bool throwOnError) + public byte[] DownloadData(RestRequest request, bool throwOnError) => throw new NotImplementedException(); - public IRestResponse Execute(IRestRequest request) where T : new() + public RestResponse Execute(RestRequest request) where T : new() => throw new NotImplementedException(); - public IRestResponse Execute(IRestRequest request, Method httpMethod) where T : new() + public RestResponse Execute(RestRequest request, Method httpMethod) where T : new() => throw new NotImplementedException(); - public IRestResponse ExecuteAsGet(IRestRequest request, string httpMethod) + public RestResponse ExecuteAsGet(RestRequest request, string httpMethod) => throw new NotImplementedException(); - public IRestResponse ExecuteAsGet(IRestRequest request, string httpMethod) where T : new() + public RestResponse ExecuteAsGet(RestRequest request, string httpMethod) where T : new() => throw new NotImplementedException(); - public IRestResponse ExecuteAsPost(IRestRequest request, string httpMethod) + public RestResponse ExecuteAsPost(RestRequest request, string httpMethod) => throw new NotImplementedException(); - public IRestResponse ExecuteAsPost(IRestRequest request, string httpMethod) where T : new() + public RestResponse ExecuteAsPost(RestRequest request, string httpMethod) where T : new() => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action callback) + public RestRequestAsyncHandle ExecuteAsync(RestRequest request, Action callback) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action, RestRequestAsyncHandle> callback) + public RestRequestAsyncHandle ExecuteAsync(RestRequest request, Action, RestRequestAsyncHandle> callback) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action callback, Method httpMethod) + public RestRequestAsyncHandle ExecuteAsync(RestRequest request, Action callback, Method httpMethod) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsync(IRestRequest request, Action, RestRequestAsyncHandle> callback, Method httpMethod) + public RestRequestAsyncHandle ExecuteAsync(RestRequest request, Action, RestRequestAsyncHandle> callback, Method httpMethod) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsyncGet(IRestRequest request, Action callback, string httpMethod) + public RestRequestAsyncHandle ExecuteAsyncGet(RestRequest request, Action callback, string httpMethod) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsyncGet(IRestRequest request, Action, RestRequestAsyncHandle> callback, string httpMethod) + public RestRequestAsyncHandle ExecuteAsyncGet(RestRequest request, Action, RestRequestAsyncHandle> callback, string httpMethod) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsyncPost(IRestRequest request, Action callback, string httpMethod) + public RestRequestAsyncHandle ExecuteAsyncPost(RestRequest request, Action callback, string httpMethod) => throw new NotImplementedException(); - public RestRequestAsyncHandle ExecuteAsyncPost(IRestRequest request, Action, RestRequestAsyncHandle> callback, string httpMethod) + public RestRequestAsyncHandle ExecuteAsyncPost(RestRequest request, Action, RestRequestAsyncHandle> callback, string httpMethod) => throw new NotImplementedException(); - public Task> ExecuteGetTaskAsync(IRestRequest request) + public Task> ExecuteGetTaskAsync(RestRequest request) => throw new NotImplementedException(); - public Task> ExecuteGetTaskAsync(IRestRequest request, CancellationToken token) + public Task> ExecuteGetTaskAsync(RestRequest request, CancellationToken token) => throw new NotImplementedException(); - public Task ExecuteGetTaskAsync(IRestRequest request) + public Task ExecuteGetTaskAsync(RestRequest request) => throw new NotImplementedException(); - public Task ExecuteGetTaskAsync(IRestRequest request, CancellationToken token) + public Task ExecuteGetTaskAsync(RestRequest request, CancellationToken token) => throw new NotImplementedException(); - public Task> ExecutePostTaskAsync(IRestRequest request) + public Task> ExecutePostTaskAsync(RestRequest request) => throw new NotImplementedException(); - public Task> ExecutePostTaskAsync(IRestRequest request, CancellationToken token) + public Task> ExecutePostTaskAsync(RestRequest request, CancellationToken token) => throw new NotImplementedException(); - public Task ExecutePostTaskAsync(IRestRequest request) + public Task ExecutePostTaskAsync(RestRequest request) => throw new NotImplementedException(); - public Task ExecutePostTaskAsync(IRestRequest request, CancellationToken token) + public Task ExecutePostTaskAsync(RestRequest request, CancellationToken token) => throw new NotImplementedException(); - public Task> ExecuteTaskAsync(IRestRequest request, CancellationToken token) + public Task> ExecuteTaskAsync(RestRequest request, CancellationToken token) => throw new NotImplementedException(); - public Task> ExecuteTaskAsync(IRestRequest request, Method httpMethod) + public Task> ExecuteTaskAsync(RestRequest request, Method httpMethod) => throw new NotImplementedException(); - public Task> ExecuteTaskAsync(IRestRequest request) + public Task> ExecuteTaskAsync(RestRequest request) => throw new NotImplementedException(); - public Task ExecuteTaskAsync(IRestRequest request, CancellationToken token) + public Task ExecuteTaskAsync(RestRequest request, CancellationToken token) => throw new NotImplementedException(); - public Task ExecuteTaskAsync(IRestRequest request, CancellationToken token, Method httpMethod) + public Task ExecuteTaskAsync(RestRequest request, CancellationToken token, Method httpMethod) => throw new NotImplementedException(); - public Task ExecuteTaskAsync(IRestRequest request) + public Task ExecuteTaskAsync(RestRequest request) => throw new NotImplementedException(); public void RemoveHandler(string contentType){} diff --git a/SnipeSharp.Tests/SnipeSharp.Tests.csproj b/SnipeSharp.Tests/SnipeSharp.Tests.csproj index d5484e8..334e2a5 100644 --- a/SnipeSharp.Tests/SnipeSharp.Tests.csproj +++ b/SnipeSharp.Tests/SnipeSharp.Tests.csproj @@ -1,9 +1,10 @@ - netcoreapp3.0 + net8.0 library false + 8.0 diff --git a/SnipeSharp.Tests/Utility.cs b/SnipeSharp.Tests/Utility.cs index b85beb7..9bfb3e9 100644 --- a/SnipeSharp.Tests/Utility.cs +++ b/SnipeSharp.Tests/Utility.cs @@ -30,7 +30,7 @@ internal static SnipeItApi SingleUseApiFromFile(string filePath, bool isSuccessf return new SnipeItApi(restClient: client) { Token = TEST_TOKEN, Uri = TEST_URI }; } - internal static SnipeItApi MultipleUseApi(out Queue responseQueue) + internal static SnipeItApi MultipleUseApi(out Queue responseQueue) { var client = new FakeRestClient(); responseQueue = client.Responses; diff --git a/SnipeSharp/RestClientManager.cs b/SnipeSharp/RestClientManager.cs index 6b7af9d..1ef6e5c 100644 --- a/SnipeSharp/RestClientManager.cs +++ b/SnipeSharp/RestClientManager.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json; using RestSharp; -using RestSharp.Authenticators; using SnipeSharp.Exceptions; using SnipeSharp.Filters; using SnipeSharp.Models; @@ -16,18 +15,24 @@ namespace SnipeSharp internal sealed class RestClientManager { private readonly SnipeItApi Api; - private readonly IRestClient Client; + private readonly RestClient Client; private readonly NewtonsoftJsonSerializer serializerDeserializer = new NewtonsoftJsonSerializer(); - internal RestClientManager(SnipeItApi api, IRestClient client) + internal RestClientManager(SnipeItApi api, RestClientOptions clientOptions) { this.Api = api; - this.Client = client; + + //clientOptions.BaseHost = api.Uri.ToString(); + //clientOptions.BaseUrl = api.Uri; + + this.Client = new RestClient(clientOptions); Client.AddDefaultHeader("Accept", "application/json"); Client.AddDefaultHeader("Cache-Control", "no-cache"); Client.AddDefaultHeader("Content-type", "application/json"); + + } internal void SetTokenAndUri() @@ -36,16 +41,13 @@ internal void SetTokenAndUri() throw new NullApiUriException(); if (null == Api.Token) throw new NullApiTokenException(); - if (null == Client.BaseUrl) - Client.BaseUrl = Api.Uri; - if (null == Client.Authenticator) - Client.Authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(Api.Token, "Bearer"); + } - internal void ResetToken() - => Client.Authenticator = null; - internal void ResetUri() - => Client.BaseUrl = null; + //internal void ResetToken() + // => Client.Authenticator = null; + //internal void ResetUri() + // => Client.BaseUrl = null; internal string GetRaw(string path) { @@ -58,11 +60,18 @@ internal string GetRaw(string path) internal ApiOptionalResponse Get(string path, ISearchFilter filter = null) where R : ApiObject { - var request = CreateRequest(path, Method.GET, filter); + var request = CreateRequest(path, Method.Get, filter); SetTokenAndUri(); #if DEBUG - var uri = Client.BuildUri(request); - Api.DebugList.Add(uri.ToString()); + try + { + var uri = Client.BuildUri(request); + Api.DebugList.Add(uri.ToString()); + } + catch (System.Exception ex) + { + string e = ex.Message.ToString(); + } #endif var response = Client.Execute(request); if (!response.IsSuccessful) @@ -115,24 +124,24 @@ internal ApiOptionalMultiResponse GetAll(string path, ISearchFilter filter internal ApiOptionalResponse> Post(string path, R obj) where R : ApiObject - => ExecuteRequest(Method.POST, path, obj); + => ExecuteRequest(Method.Post, path, obj); internal ApiOptionalResponse> Post(string path, T obj) where T : ApiObject where R : ApiObject - => ExecuteRequest(Method.POST, path, obj); + => ExecuteRequest(Method.Post, path, obj); internal ApiOptionalResponse> Put(string path, R obj) where R : ApiObject - => ExecuteRequest(Method.PUT, path, obj); + => ExecuteRequest(Method.Put, path, obj); internal ApiOptionalResponse> Patch(string path, R obj) where R : ApiObject - => ExecuteRequest(Method.PATCH, path, obj); + => ExecuteRequest(Method.Patch, path, obj); internal ApiOptionalResponse> Delete(string path) where R : ApiObject - => ExecuteRequest(Method.DELETE, path); + => ExecuteRequest(Method.Delete, path); private ApiOptionalResponse> ExecuteRequest(Method method, string path, ApiObject obj = null) where R : ApiObject @@ -167,15 +176,18 @@ internal RestRequest CreateRequest(string path, Method method, object obj) { var request = new RestRequest(path, method) { - RequestFormat = DataFormat.Json, - JsonSerializer = serializerDeserializer + RequestFormat = DataFormat.Json + + //JsonSerializer = serializerDeserializer }; if (null == obj) return request; - if (Method.GET != method) + if (Method.Get != method) { - request.AddJsonBody(obj); + //request.AddJsonBody(obj); + + request.AddBody(serializerDeserializer.Serialize(obj)); #if DEBUG Api.DebugRequestList.Add(serializerDeserializer.Serialize(obj)); #endif @@ -188,7 +200,7 @@ internal RestRequest CreateRequest(string path, Method method, object obj) if (null == attribute) continue; // don't need to bother with PatchAttribute because it only applies to Post and Put (this is Get). - var value = property.GetValue(obj); + object value = property.GetValue(obj); if (attribute.IsRequired && null == value) throw new MissingRequiredFieldException(type.Name, property.Name); if (null == value) @@ -208,7 +220,7 @@ internal RestRequest CreateRequest(string path, Method method, object obj) ?.GetCustomAttribute()?.Value ?? value.ToString(); } - request.AddParameter(attribute.Key, value); + request.AddParameter(attribute.Key, value.ToString()); } return request; } diff --git a/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs b/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs index 410ce78..7825d8f 100644 --- a/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs +++ b/SnipeSharp/Serialization/NewtonsoftJsonSerializer.cs @@ -1,6 +1,5 @@ using Newtonsoft.Json; using RestSharp; -using RestSharp.Deserializers; using RestSharp.Serializers; namespace SnipeSharp.Serialization @@ -28,11 +27,14 @@ internal sealed class NewtonsoftJsonSerializer : ISerializer, IDeserializer public static JsonSerializer Serializer { get; } = JsonSerializer.CreateDefault(SerializerSettings); public static JsonSerializer Deserializer { get; } = JsonSerializer.CreateDefault(DeserializerSettings); + ContentType ISerializer.ContentType { get => throw new System.NotImplementedException(); set => throw new System.NotImplementedException(); } public string Serialize(object @object) => JsonConvert.SerializeObject(@object, SerializerSettings); - public T Deserialize(IRestResponse response) - => JsonConvert.DeserializeObject(response.Content, DeserializerSettings); + public T Deserialize(RestResponse response) + { + return JsonConvert.DeserializeObject(response.Content, DeserializerSettings); + } } } diff --git a/SnipeSharp/SnipeItApi.cs b/SnipeSharp/SnipeItApi.cs index b6cc094..20526be 100644 --- a/SnipeSharp/SnipeItApi.cs +++ b/SnipeSharp/SnipeItApi.cs @@ -1,4 +1,6 @@ +using Newtonsoft.Json.Linq; using RestSharp; +using RestSharp.Authenticators.OAuth2; using SnipeSharp.EndPoint; using SnipeSharp.Models; using System; @@ -20,7 +22,7 @@ public sealed class SnipeItApi /// /// A list of responses from the RestClientManager. Used for debugging purposes. /// - public List DebugResponseList = new List(); + public List DebugResponseList = new List(); /// /// A list of request bodies from the RestClientManager. Used for debugging purposes. @@ -40,7 +42,7 @@ public string Token set { _token = value; - RequestManager.ResetToken(); + //RequestManager.ResetToken(); } } @@ -56,7 +58,7 @@ public Uri Uri set { _uri = value; - RequestManager.ResetUri(); + //RequestManager.ResetUri(); } } @@ -204,18 +206,15 @@ public EndPoint GetEndPoint() where T : AbstractBaseModel /// Constructs a wrapper for the Snipe-IT web API. /// The Token and Uri must be set either in an initializer or manually after construction. /// - public SnipeItApi() : this(new RestClient()) + public SnipeItApi(System.Uri uri, string token) { - } + this.Uri = uri; + this.Token = token; + RestClientOptions options = new RestClientOptions(Uri); + var authenticator = new OAuth2AuthorizationRequestHeaderAuthenticator(Token, "Bearer"); + options.Authenticator = authenticator; - /// - /// Constructs a wrapper for the Snipe-IT web API. - /// The Token and Uri must be set either in an initializer or manually after construction. - /// - /// This constructor is for internal and testing use. - internal SnipeItApi(IRestClient restClient) - { - RequestManager = new RestClientManager(this, restClient); + this.RequestManager = new RestClientManager(this, options); // endpoints Account = new AccountEndPoint(this); diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index 5a8a873..1606233 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + net8.0 library false 8.0 @@ -9,7 +9,7 @@ warnings - - + + diff --git a/test/SnipeSharp.Test/SnipeSharp.Test.csproj b/test/SnipeSharp.Test/SnipeSharp.Test.csproj index b7c25cb..c242dd2 100644 --- a/test/SnipeSharp.Test/SnipeSharp.Test.csproj +++ b/test/SnipeSharp.Test/SnipeSharp.Test.csproj @@ -1,7 +1,7 @@ - netcoreapp3.0 + net8.0 library false From 6b447662c1c065ee76b0ba1ba9ba1d749ef59170 Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Tue, 30 Jul 2024 07:57:52 -0500 Subject: [PATCH 09/14] Change to date only serialization for asset creation --- SnipeSharp/Models/Submittable/Accessory.cs | 2 +- SnipeSharp/Models/Submittable/Asset.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SnipeSharp/Models/Submittable/Accessory.cs b/SnipeSharp/Models/Submittable/Accessory.cs index 70b5d1b..d21fb12 100644 --- a/SnipeSharp/Models/Submittable/Accessory.cs +++ b/SnipeSharp/Models/Submittable/Accessory.cs @@ -197,7 +197,7 @@ public uint? Quantity /// The date this Accessory was purchased. /// [DeserializeAs("purchase_date", DeserializeAs.DateObject)] - [SerializeAs("purchase_date", SerializeAs.SimpleDate)] + [SerializeAs("purchase_date", SerializeAs.SimpleDateOnly)] [Patch(nameof(isPurchaseDateModified))] public DateTime? PurchaseDate { diff --git a/SnipeSharp/Models/Submittable/Asset.cs b/SnipeSharp/Models/Submittable/Asset.cs index ae9dba4..96a057b 100644 --- a/SnipeSharp/Models/Submittable/Asset.cs +++ b/SnipeSharp/Models/Submittable/Asset.cs @@ -387,7 +387,7 @@ public int? WarrantyMonths /// The date this Asset was purchased. /// [DeserializeAs("purchase_date", DeserializeAs.DateObject)] - [SerializeAs("purchase_date", SerializeAs.SimpleDate)] + [SerializeAs("purchase_date", SerializeAs.SimpleDateOnly)] [Patch(nameof(isPurchaseDateModified))] public DateTime? PurchaseDate { From 522f6ba6ded48ef23a444f2912b65e8dd9dc149c Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Mon, 16 Sep 2024 11:52:55 -0500 Subject: [PATCH 10/14] nuget package updates --- SnipeSharp/SnipeSharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index 1606233..9825a6b 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -10,6 +10,6 @@ - + From 069ad3f6b29d9c2b510cfa051b33586bb2060485 Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Mon, 16 Dec 2024 10:10:28 -0600 Subject: [PATCH 11/14] Delete SnipeSharp/SnipeSharp.nuspec --- SnipeSharp/SnipeSharp.nuspec | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 SnipeSharp/SnipeSharp.nuspec diff --git a/SnipeSharp/SnipeSharp.nuspec b/SnipeSharp/SnipeSharp.nuspec deleted file mode 100644 index e0ce95a..0000000 --- a/SnipeSharp/SnipeSharp.nuspec +++ /dev/null @@ -1,21 +0,0 @@ - - - - $id$ - $version$ - $title$ - Matthew Carey - Matthew Carey - https://opensource.org/licenses/MIT - https://github.com/barrycarey/SnipeSharp - false - $description$ - A .Net API wrapper for Snipe IT that allows you to manage the full Snipe IT API within a .NET project. - Added support for FieldSet endpoint - Copyright 2017 - SnipeIT Snipe IT - - - - - From ba2df1bff9b576d283952daf2178b6b146ccb882 Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Mon, 16 Dec 2024 10:10:56 -0600 Subject: [PATCH 12/14] Update SnipeSharp.csproj --- SnipeSharp/SnipeSharp.csproj | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index 9825a6b..68cda85 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -8,6 +8,14 @@ true warnings + + SnipeSharp + 1.0.0 + Ross Louch + C# wrapper for the SnipeIT API. + https://nuget.pkg.github.com/rlouch2/RS2SwaggerAPI/index.json + NuGet + From 6c8a179fe12380c0656fcd4bab9e269295e15312 Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Mon, 16 Dec 2024 10:12:32 -0600 Subject: [PATCH 13/14] Create dotnet-nuget.yml --- .github/workflows/dotnet-nuget.yml | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/dotnet-nuget.yml diff --git a/.github/workflows/dotnet-nuget.yml b/.github/workflows/dotnet-nuget.yml new file mode 100644 index 0000000..5b4f3eb --- /dev/null +++ b/.github/workflows/dotnet-nuget.yml @@ -0,0 +1,52 @@ +name: Build and Package NuGet + +on: + workflow_dispatch: + push: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup .NET + uses: actions/setup-dotnet@v1 + with: + dotnet-version: '8.0.x' + + - name: Restore dependencies + run: + dotnet restore SnipeSharp/SnipeSharp.csproj + + - name: Set version number to date/time + run: | + #ls SnipeSharp + echo "Setting version number" + VERSION=$(date +'%Y.%m.%d.%H%M') + cat SnipeSharp/SnipeSharp.csproj # View the updated + sed -i "s/.*<\/Version>/$VERSION<\/Version>/" SnipeSharp/SnipeSharp.csproj + cat SnipeSharp/SnipeSharp.csproj # View the updated + + - name: Build + run: + dotnet build SnipeSharp/SnipeSharp.csproj --configuration Release + + - name: Pack + run: + dotnet pack SnipeSharp/SnipeSharp.csproj --configuration Release --output ./nupkgs + + - name: Upload NuGet Packages + uses: actions/upload-artifact@v4 + with: + name: nuget-packages + path: ./nupkgs/*.nupkg + + - name: Push nuget package to Github + run: dotnet nuget push ./nupkgs/*.nupkg --api-key ${{ secrets.NUGET_GITHUB }} --source "https://nuget.pkg.github.com/rlouch2/index.json" + #- name: Push to NuGet + # run: dotnet nuget push ./nupkgs/*.nupkg --api-key ${{ secrets.NUGET }} --source https://api.nuget.org/v3/index.json From f38ff8ffbc40fb84f38ec6d48a58ec492e9a8c2a Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Mon, 16 Dec 2024 10:15:43 -0600 Subject: [PATCH 14/14] Update SnipeSharp.csproj --- SnipeSharp/SnipeSharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index 68cda85..f0a585d 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -13,7 +13,7 @@ 1.0.0 Ross Louch C# wrapper for the SnipeIT API. - https://nuget.pkg.github.com/rlouch2/RS2SwaggerAPI/index.json + https://nuget.pkg.github.com/rlouch2/index.json NuGet