From 309ad74ad29445a24a98b760e20274355cdbe5ae Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Thu, 23 Jun 2022 15:48:08 -0500 Subject: [PATCH 01/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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/20] 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 From 8b8b1436b0e189f9f18e99f5c6e979841961073e Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Fri, 13 Mar 2026 08:28:41 -0500 Subject: [PATCH 15/20] Update to handle audit as a AvaliableAction enum --- SnipeSharp/Models/Enumerations/AvailableAction.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SnipeSharp/Models/Enumerations/AvailableAction.cs b/SnipeSharp/Models/Enumerations/AvailableAction.cs index e756dcf..a782166 100644 --- a/SnipeSharp/Models/Enumerations/AvailableAction.cs +++ b/SnipeSharp/Models/Enumerations/AvailableAction.cs @@ -40,5 +40,8 @@ public enum AvailableAction /// The associated request may be canceled. [EnumMember(Value = "cancel")] CancelRequest = 128, + /// The associated object may be audited. + [EnumMember(Value = "audit")] + Audit = 256, } } From 66fb7a33876df71fe6237f06f940215fd331f05a Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Fri, 13 Mar 2026 08:59:29 -0500 Subject: [PATCH 16/20] Updates of packages and change of the powershell ot dotnet8.0 --- SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj | 2 +- SnipeSharp/SnipeSharp.csproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj b/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj index eadaaeb..4cb29ec 100644 --- a/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj +++ b/SnipeSharp.PowerShell/SnipeSharp.PowerShell.csproj @@ -2,7 +2,7 @@ - netstandard2.1 + net8.0 library SnipeSharp.PowerShell false diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index f0a585d..7ab9d18 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -17,7 +17,7 @@ NuGet - - + + From db9735da64de679b702620f32f0cceb302d8a42f Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Fri, 13 Mar 2026 09:30:11 -0500 Subject: [PATCH 17/20] Refactor GitHub Actions for .NET Core Desktop build --- .github/workflows/dotnet-desktop.yml | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/dotnet-desktop.yml diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml new file mode 100644 index 0000000..34cb334 --- /dev/null +++ b/.github/workflows/dotnet-desktop.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@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + 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 --no-restore + + - name: Pack + run: + dotnet pack SnipeSharp/SnipeSharp.csproj --configuration Release --no-build --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" --skip-duplicate + #- name: Push to NuGet + # run: dotnet nuget push ./nupkgs/*.nupkg --api-key ${{ secrets.NUGET }} --source https://api.nuget.org/v3/index.json From 6fcbb121c7c9a9ba2485e77f0e9bd02ee683725d Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Fri, 13 Mar 2026 09:31:40 -0500 Subject: [PATCH 18/20] Update workflow name to include creation year --- .github/workflows/dotnet-desktop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet-desktop.yml b/.github/workflows/dotnet-desktop.yml index 34cb334..938f1e4 100644 --- a/.github/workflows/dotnet-desktop.yml +++ b/.github/workflows/dotnet-desktop.yml @@ -1,4 +1,4 @@ -name: Build and Package NuGet +name: Build and Package NuGet created 2026 on: workflow_dispatch: From 0b3584c925a418fbaaa20954eb41e9b71fa7befd Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Fri, 13 Mar 2026 09:38:50 -0500 Subject: [PATCH 19/20] Updaed proj file for git nuget package --- SnipeSharp/SnipeSharp.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SnipeSharp/SnipeSharp.csproj b/SnipeSharp/SnipeSharp.csproj index 7ab9d18..7dd0266 100644 --- a/SnipeSharp/SnipeSharp.csproj +++ b/SnipeSharp/SnipeSharp.csproj @@ -14,7 +14,7 @@ Ross Louch C# wrapper for the SnipeIT API. https://nuget.pkg.github.com/rlouch2/index.json - NuGet + git From d20fe6ed161d0f05f6dd4df60fb8e81ff706625b Mon Sep 17 00:00:00 2001 From: Ross Louch Date: Fri, 10 Apr 2026 12:29:47 -0500 Subject: [PATCH 20/20] Closes #4 The API model was referencing the name of the maintenance as "title" instead of "name" as it should in the newer versions. The model serialization has been updated to reflect the correct field names --- SnipeSharp/Models/Submittable/Maintenance.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SnipeSharp/Models/Submittable/Maintenance.cs b/SnipeSharp/Models/Submittable/Maintenance.cs index 132c66d..aaa9669 100644 --- a/SnipeSharp/Models/Submittable/Maintenance.cs +++ b/SnipeSharp/Models/Submittable/Maintenance.cs @@ -43,8 +43,8 @@ public StubAsset Asset /// /// This field is required. - [DeserializeAs("title")] - [SerializeAs("title")] + [DeserializeAs("name")] + [SerializeAs("name")] [Patch(nameof(isNameModified))] public override string Name {