using System; using System.Linq; using System.Collections.Generic; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using AyaNova.Biz; namespace AyaNova.Api.ControllerHelpers { public class ApiErrorResponse { [JsonIgnore] private ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger(); //Mandatory properties public ApiError Error { get; } //Generic error public ApiErrorResponse(ApiErrorCode apiCode, string target = null, string message = null) { //try to get a stock message if nothing specified if (message == null) { message = ApiErrorCodeStockMessage.GetMessage(apiCode); } Error = new ApiError(apiCode, message, target); log.LogDebug("apiCode={0}, target={1}, message={2}", apiCode, target, message); } //Bad request (MODELSTATE ISSUE) error response handling public ApiErrorResponse(ModelStateDictionary modelState) { if (modelState.IsValid) { throw new ArgumentException("ModelState must be invalid", nameof(modelState)); } //Set outer error and then put validation in details Error = new ApiError(ApiErrorCode.VALIDATION_FAILED, ApiErrorCodeStockMessage.GetMessage(ApiErrorCode.VALIDATION_FAILED)); //https://www.jerriepelser.com/blog/validation-response-aspnet-core-webapi/ //Message = "Validation Failed"; Error.Details = new List(); /* https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.modelbinding.modelerror?view=aspnetcore-2.2 modelState["roles"].Errors Count = 1 [0]:{Microsoft.AspNetCore.Mvc.ModelBinding.ModelError} ErrorMessage [string]:"" Exception [Exception]:{Newtonsoft.Json.JsonSerializationException: Error converting value "" to type 'AyaNova.Biz.AuthorizationRoles'. Path 'roles', line 1, position 146. ---> System.ArgumentException: Must specify valid information for parsing in the string.\r\n at Newtonsoft.Json.Utilities.EnumUtils.ParseEnum(Type enumType, NamingStrategy namingStrategy, String value, Boolean disallowNumber) in /_/Src/Newtonsoft.Json/Utilities/EnumUtils.cs:line 285\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 958\r\n --- End of inner exception stack trace ---\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 989\r\n at Newtonsoft.Json.Serialization.Jso... Data [IDictionary]:{System.Collections.ListDictionaryInternal} HResult [int]:-2146233088 HelpLink [string]:null InnerException [Exception]:{System.ArgumentException: Must specify valid information for parsing in the string.\r\n at Newtonsoft.Json.Utilities.EnumUtils.ParseEnum(Type enumType, NamingStrategy namingStrategy, String value, Boolean disallowNumber) in /_/Src/Newtonsoft.Json/Utilities/EnumUtils.cs:line 285\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 958} LineNumber [int]:1 LinePosition [int]:146 Message [string]:"Error converting value \"\" to type 'AyaNova.Biz.AuthorizationRoles'. Path 'roles', line 1, position 146." Path [string]:"roles" Source [string]:"Newtonsoft.Json" StackTrace [string]:" at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 989\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 1032\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) in /_/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:line 2386" TargetSite [MethodBase]:{System.Object EnsureType(Newtonsoft.Json.JsonReader, System.Object, System.Globalization.CultureInfo, Newtonsoft.Json.Serialization.JsonContract, System.Type)} Static members Non-Public members Raw View Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.1\System.Reflection.Metadata.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.1\System.IO.MemoryMappedFiles.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. modelState["roles"].Errors[0].Exception.Message "Error converting value \"\" to type 'AyaNova.Biz.AuthorizationRoles'. Path 'roles', line 1, position 146." modelState["roles"].Errors Count = 1 [0]:{Microsoft.AspNetCore.Mvc.ModelBinding.ModelError */ //original method missing details: // Error.Details.AddRange(modelState.Keys // .SelectMany(key => modelState[key].Errors // .Select(x => new ApiDetailError() { Code = ((int)ApiErrorCode.VALIDATION_FAILED).ToString(), Target = key, Message = x.ErrorMessage, Error=ApiErrorCode.VALIDATION_FAILED.ToString() }))); //var vErrors = modelState.Keys.SelectMany(key => modelState[key].Errors); foreach (var key in modelState.Keys) { var vErrors = modelState[key].Errors; foreach (ModelError m in vErrors) { string msg = ""; if (!string.IsNullOrWhiteSpace(m.ErrorMessage)) { msg += m.ErrorMessage + ". "; } if (m.Exception != null && !string.IsNullOrWhiteSpace(m.Exception.Message)) { msg += "Exception: " + m.Exception.Message; } //example this produces // Error.Details.Add(new ApiDetailError() { Target = key, Message = msg, Error = ((int)ApiErrorCode.VALIDATION_INVALID_VALUE).ToString() }); } } log.LogDebug("BadRequest - Validation error"); } //Business rule validation error response public ApiErrorResponse(List errors) { Error = new ApiError(ApiErrorCode.VALIDATION_FAILED, ApiErrorCodeStockMessage.GetMessage(ApiErrorCode.VALIDATION_FAILED)); Error.Details = new List(); foreach (ValidationError v in errors) { Error.Details.Add(new ApiDetailError() { Target = v.Target, Message = v.Message, Error = ((int)v.Code).ToString() }); } log.LogDebug("BadRequest - Validation error"); } // public void AddDetailError(ApiErrorCode apiCode, string target = null, string message = null) // { // if (Error.Details == null) // { // Error.Details = new List(); // } // //try to get a stock message if nothing specified // if (message == null) // { // message = ApiErrorCodeStockMessage.GetMessage(apiCode); // } // Error.Details.Add(new ApiDetailError() { Code = ((int)apiCode).ToString(), Target = target, Message = message }); // } }//eoc }//eons