I am trying to send multiple ID's of objects that I want to delete from Angular 13 to my C# .net API.
Through research online this was the method suggested to send a body using http.delete which will need to return the updated show costs.
My first question, is this the appropriate way to call this method via a RESTful API?
deleteMultipleReturnShowCosts(showId: number, objs: number[]): Observable<ShowCost[]>{
const options = { headers: new HttpHeaders({'Content-Type': 'application/json'}),
body: { ids: JSON.stringify({...objs})}};
return this.http.delete<ShowCost[]>(`${this.url}/${showId}`, options)
.pipe(
catchError(this.handleError<ShowCost[]>('Delete: Show Item'))
);
}
In this method for instance, I send the objs: number[] of [151,152,153]
This is the current test code for my C# API Delete Method
/// <summary>
/// Delete Show Item
/// </summary>
/// <param name="ids"></param>
/// <param name="showId"></param>
/// <returns></returns>
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[HttpDelete("{showId:int}", Name = nameof(DeleteShowItem))]
public async Task<IActionResult> DeleteShowItem([FromBody] object jsonObj, int showId)
{
try
{
var jsonString = JsonConvert.SerializeObject(jsonObj);
var jsonKeyValuePair = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
jsonKeyValuePair.TryGetValue("ids", out var stringArray);
if (stringArray == null) return BadRequest("Array did not parse.");
var showItemIds = JsonConvert.DeserializeObject<int[]>(stringArray);
return Ok();
}
catch (Exception e)
{
_logger.LogError(e.Message);
return BadRequest(e.Message);
}
}
I have been trying to break down the object in many different ways, but without any joy.
These are the current variable values:
jsonObj
{
"ids": "{\"0\":151,\"1\":152,\"2\":153}"
}
jsonKeyValuePair
Count = 1
key[0] = ids
value[0] = {"0":151,"1":152,"2":153}
showItemIds
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Int32[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path '0', line 1, position 5.
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
at Assembly2021.API.Controllers.ShowItemController.DeleteShowItem(Object jsonObj, Int32 showId) in /Users/alexanderlynn/RiderProjects/assembly2021-angular/Assembly2021-API/Assembly2021.API/Controllers/ShowItemController.cs:line 182
Ultimately I would like to obtain an IEnumerable for the rest of the API call.
Thanks in advance!
CodePudding user response:
you can simplify this by changing your json to just an array instead of that weird object, so instead of:
body: { ids: JSON.stringify({...objs})}};
write
body: objs };
the json will become simply an array:
[ 1,2,3,4 ]
in api just declare your parameter as something that can accept a list of objects like and array or list or IEumerable:
public async Task<IActionResult> DeleteShowItem([FromBody] int[] jsonObj, int showId)
no additional code required magic done out of the box.
also do not bake catch log logic into all of your endpoints
catch (Exception e)
{
_logger.LogError(e.Message);
return BadRequest(e.Message);
}
you already did it wrong by only logging message the most important thing about exception is the stack trace the second most is the message from inner most exception. The way you did it will hinder your ability to find errors. So log full exception either your logger should accept Exception as a parameter or at least pass e.ToString() to it. To not repeat this code write an action filter. And Bad Request is for user calling your endpoint with invalid parameters :) now for every fault of your code you are blaming the user :).