PUT Request Does not Convert Snake Case to Pascal Case - c#

I am trying to send a PUT request, but for some reason my API refuses to convert snake case properties
The request looks like this:
Where mercuryParserResponse looks like this in C#:
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class MercuryParserResponseDto
{
public string Author { get; set; }
public string Content { get; set; }
public DateTimeOffset DatePublished { get; set; }
public string Direction { get; set; }
public string Domain { get; set; }
public string Excerpt { get; set; }
public string LeadImageUrl { get; set; }
public string Url { get; set; }
[JsonProperty("word_count")]
public int WordCount { get; set; }
public string NextPageUrl { get; set; } //
public int RenderedPages { get; set; } //
public string Title { get; set; }
[JsonProperty("total_pages")]
public int TotalPages { get; set; }
}
And my API endpoint
[HttpPut]
public async Task<IActionResult> Put(
[FromBody]ImportArticleDto article,
CancellationToken cancellationToken = default)
{
return null;
}
But article.MercuryParserResponse.WordCount is always 0 (Note that single-word properties such as author are coming through correctly)
Why? Why are my Json attributes not working here?

From this answer, using JsonPropertyName works:
[JsonPropertyName("word_count")]
However I don't really want to have to add this to every single property
If anyone can advise how to apply this casing to the entire class I will accept your answer

Related

Note field required even though it has no required attribute

I have the following class:
public class UpdateActionRequest
{
[Required]
public int ActionId { get; set; }
[Required]
public int LeadId { get; set; }
[Required]
public int AssignedToUserId { get; set; }
public string Note { get; set; }
public DateTime? PlannedDate { get; set; }
}
Which I use in an api call:
[HttpPatch("update", Name = nameof(UpdateAction))]
public async Task<LeadAction> UpdateAction(UpdateActionRequest request)
{
return await _actionsHandler.Value.UpdateAction(request);
}
But when I send the following JSON:
{
"ActionId":7,
"LeadId":40,
"AssignedToUserId": 8306,
"PlannedDate":"2022-11-14T11:23:45.343Z"
}
I'm getting a bad request saying the note field is required - how do I make it so that I don't need to send the note property?
you can use
public string? Note { get; set; };
or
public string Note { get; set; } = string.Empty;

Problems deserializing Json from MusixMatch API?

I'm trying to implement MusixMatch API, I must admit, when I debug I'm unable to see what's in the ObservableCollection after the API call because the debugger jumps to another thread (I have zero expertise in thread management), however I can see what's the from the API response, Visual Studio says is not Json formatted:
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetStringAsync($"https://api.musixmatch.com/ws/1.1/artist.search?format=jsonp&callback=callback&q_artist=queen&page=1&page_size=5&apikey={apikey}");
RootObject testList= JsonConvert.DeserializeObject<RootObject>(response);
return testList;
I have a model with this structure:
public class Header
{
public int status_code { get; set; }
public double execute_time { get; set; }
public int available { get; set; }
}
public class ArtistNameTranslation
{
public string language { get; set; }
public string translation { get; set; }
}
public class ArtistNameTranslationList
{
public ArtistNameTranslation artist_name_translation { get; set; }
}
public class ArtistAliasList
{
public string artist_alias { get; set; }
}
public class ArtistCredits
{
public List<object> artist_list { get; set; }
}
public class Artist
{
public int artist_id { get; set; }
public string artist_name { get; set; }
public List<ArtistNameTranslationList> artist_name_translation_list { get; set; }
public string artist_comment { get; set; }
public string artist_country { get; set; }
public List<ArtistAliasList> artist_alias_list { get; set; }
public int artist_rating { get; set; }
public string artist_twitter_url { get; set; }
public ArtistCredits artist_credits { get; set; }
public int restricted { get; set; }
public DateTime updated_time { get; set; }
}
public class ArtistList
{
public Artist artist { get; set; }
}
public class Body
{
public List<ArtistList> artist_list { get; set; }
}
public class Message
{
public Header header { get; set; }
public Body body { get; set; }
}
public class RootObject
{
public Message message { get; set; }
}
}
As I said I was able to see what's in the response from the API, you can look at the complete response:
callback({"message":{"header": {"status_code":200,"execute_time":0.043232917785645,"available":6936},"body":{"artist_list":[{"artist":{"artist_id":118,"artist_name":"Queen","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30af\u30a4\u30fc\u30f3"}}],"artist_comment":"","artist_country":"","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3"},{"artist_alias":"Queen + Adam Lambert"}],"artist_rating":99,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2015-12-16T15:50:53Z"}},{"artist":{"artist_id":13755603,"artist_name":"Queen with David Bowie","artist_name_translation_list":[{"artist_name_translation":{"language":"EN","translation":"Queen"}}],"artist_comment":"","artist_country":"","artist_alias_list":[{"artist_alias":"Queen"}],"artist_rating":38,"artist_twitter_url":"","artist_credits":{"artist_list":[{"artist":{"artist_id":118,"artist_name":"Queen","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30af\u30a4\u30fc\u30f3"}}],"artist_comment":"","artist_country":"","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3"},{"artist_alias":"Queen + Adam Lambert"}],"artist_rating":99,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2015-12-16T15:50:53Z"}},{"artist":{"artist_id":431,"artist_name":"David Bowie","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30c7\u30f4\u30a3\u30c3\u30c9\u30fb\u30dc\u30a6\u30a4"}}],"artist_comment":"","artist_country":"GB","artist_alias_list":[{"artist_alias":"\u30c7\u30f4\u30a3\u30c3\u30c9\u30fb\u30dc\u30a6\u30a4"},{"artist_alias":"David Robert Jones"},{"artist_alias":"David Jones"},{"artist_alias":"Ziggy Stardust"},{"artist_alias":"\ub370\uc774\ube44\ub4dc \ubcf4\uc704"},{"artist_alias":"\u0414\u044d\u0432\u0438\u0434 \u0411\u043e\u0443\u0438"},{"artist_alias":"Davis Bowie"},{"artist_alias":"Bowie"},{"artist_alias":"\u30c7\u30d3\u30c3\u30c9\u30fb\u30dc\u30a6\u30a4"},{"artist_alias":"David Bowie"},{"artist_alias":"Davie Bowie"},{"artist_alias":"The Thin White Duke"}],"artist_rating":85,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2018-10-20T16:37:59Z"}}]},"restricted":0,"updated_time":"2015-12-01T18:35:35Z"}},{"artist":{"artist_id":17057,"artist_name":"Queen Latifah","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30af\u30a4\u30fc\u30f3\u30fb\u30e9\u30c6\u30a3\u30d5\u30a1"}}],"artist_comment":"","artist_country":"US","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3\u30fb\u30e9\u30c6\u30a3\u30d5\u30a1"},{"artist_alias":"Queen Latifa"},{"artist_alias":"Dana Owens"}],"artist_rating":46,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2013-11-05T11:25:25Z"}},{"artist":{"artist_id":7321,"artist_name":"Queens of the Stone Age","artist_name_translation_list":[{"artist_name_translation":{"language":"RU","translation":"Queens Of The Stone Age"}}],"artist_comment":"","artist_country":"US","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3\u30ba\u30aa\u30d6\u30b6\u30b9\u30c8\u30fc\u30f3\u30a8\u30a4\u30b8"},{"artist_alias":"Queens Of The Stone Age"},{"artist_alias":"shiqishidaihuanghou"},{"artist_alias":"Queen Of Stoneage"},{"artist_alias":"Queens Of The Stoneage"},{"artist_alias":"QOTSA"}],"artist_rating":76,"artist_twitter_url":"https:\/\/twitter.com\/qotsa","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2015-12-09T18:04:11Z"}},{"artist":{"artist_id":26029011,"artist_name":"\u5973\u738b\u8702","artist_name_translation_list":[{"artist_name_translation":{"language":"EN","translation":"Queen Bee"}}],"artist_comment":"","artist_country":"JP","artist_alias_list":[{"artist_alias":"Queen Bee"}],"artist_rating":48,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2019-07-15T13:55:16Z"}}]}}});
(https://drive.google.com/file/d/1RH9qxrCfKOXdX16eKy74iWhtbnfT46mD/view?usp=sharing)
As I said, Visual Studio is telling me that the response is not in Json>
(https://drive.google.com/file/d/1MoZlKEIbh8Epp_CC9gukWYtMBwp5oXwy/view?usp=sharing)
Looks like you are passing a parameter format=jsonp in the URL. JSONP is a format where JSON data is wrapped in a callback function. It is intended to be used from within <script> tags in HTML pages. If you want plain JSON, try changing that parameter to format=json and removing the corresponding callback parameter. Or you could try removing both format and callback parameters, assuming that JSON is the default format.
If that doesn't work, then the other alternative is to strip off the callback() function wrapper from the response string prior to trying to parse it as JSON. You can do that with a helper method like this:
public static string ExtractJson(string text)
{
int i = text.IndexOf('(');
int j = text.LastIndexOf(')');
return i > -1 && j > i ? text.Substring(i + 1, j - i - 1) : null;
}
You need to update your code to:
var response = await httpClient.GetStringAsync($"https://api.musixmatch.com/ws/1.1/artist.search?format=jsonp&callback=callback&q_artist=queen&page=1&page_size=5&apikey={apikey}");
var contents = await response.Content.ReadAsStringAsync();
RootObject testList= JsonConvert.DeserializeObject<RootObject>(contents);
return testList;

How to send list of object to webapi c#?

I'm trying to send a list of objects to webapi in json-array format. But, in the parameter its getting null.
Now, let me post the code that i have tried so far
[HttpPost]
[Route("~/api/visitsave")]
public IHttpActionResult Save(List<VisitDataModel> visitobj)
{
foreach (VisitDataModel visitobjs in visitobj) {
VisitManager obj = new VisitManager(visitobjs);
bool value = obj.Save();
}
return Ok();
}
This is the json-array I'm trying to pass, but it is not working in the parameter visitobj.
Its receiving null. As I'm new to webapi and c#, I'm struggling with this.
But when i pass single json object I'm getting values and when i switched back to list, it's not working.
Let me post the json array that am trying to post:
{"visitobj":[{"Remarks":"test","UserID":193,"FindingsAtSite":"nothing","CheckInDate":"2017-02-01 12:00:00","CheckOutDate":"2017-02-01 12:00:00","VisitStatusID":1,"CreatedBy":192,"CreatedDateTime":"2017-02-01 12:00:00","Claim":{"TransportMode":1,"Date":"2017-02-01 12:00:00","FromLocation":"chennai","ToLocation":"re","Ticket":123.2,"Conveyance":123.5,"Lodge":234.0,"Meals":23}}]}
This is the jsonresponse am trying to send to my webapi can someone helpme out this may be dumb question but am struggling with this. Thanks in advance!!
May be you are passing json in wrong format. I have an API action like this
[HttpPost]
[Route("sample")]
public IHttpActionResult SampleOp(List<SampleObj> smpJson)
{
foreach (var item in smpJson){
//Do Some Thing Here
}
return ok();
}
And passing the json data as
[{
"name":"name 1",
"address":"address 1",
"age":1
},
{
"name":"name 2",
"address":"address 2",
"age":2
}]
Here is my SampleObj modal
public class SampleObj {
public string name { get; set; }
public string address { get; set; }
public int age { get; set; }
}
It is tested and working here
This is a normal behavior since your contract does not match.
Change your parameters to the following and your argument will be ok
public class Claim
{
public int TransportMode { get; set; }
public string Date { get; set; }
public string FromLocation { get; set; }
public string ToLocation { get; set; }
public double Ticket { get; set; }
public double Conveyance { get; set; }
public double Lodge { get; set; }
public int Meals { get; set; }
}
public class Visitobj
{
public string Remarks { get; set; }
public int UserID { get; set; }
public string FindingsAtSite { get; set; }
public string CheckInDate { get; set; }
public string CheckOutDate { get; set; }
public int VisitStatusID { get; set; }
public int CreatedBy { get; set; }
public string CreatedDateTime { get; set; }
public Claim Claim { get; set; }
}
public class VisiteRequest
{
public List<Visitobj> visitobj { get; set; }
}
Or the second option you have to change the Json sent object as an array
[{"Remarks":"test","UserID":193,"FindingsAtSite":"nothing","CheckInDate":"2017-02-01 12:00:00","CheckOutDate":"2017-02-01 12:00:00","VisitStatusID":1,"CreatedBy":192,"CreatedDateTime":"2017-02-01 12:00:00","Claim":{"TransportMode":1,"Date":"2017-02-01 12:00:00","FromLocation":"chennai","ToLocation":"re","Ticket":123.2,"Conveyance":123.5,"Lodge":234.0,"Meals":23}}]

Parse query string filter/sorting passed in JQuery style

Does anyone know of a standard library (or model binder) in C# to parse JQuery-style serialized filters (and sorting), like the one passed from the Kendo DataSource?
So to parse a query string like this to strongly typed array(s) with filter and sort objects:
sort[0][field]=status.name&sort[0][dir]=desc&filter[logic]=and&filter[filters][0][field]=status.name&filter[filters][0][operator]=eq&filter[filters][0][value]=Sold
I've tried searching but I mostly seem to run into incomplete implementations or JavaScript samples unfortunately.
UPDATE: I didn't realise this format is already standard supported until #Lali pointed out this is standard body form serialization.
I solved it now by creating some classes and just using this as parameter for the web API action, and it just magically works:
public async Task<IHttpActionResult> Get([FromUri] ListSelectionOptionsWithFilter options)
{
//query something
}
public class ListSelectionOptionsWithFilter
{
public int? Skip { get; set; }
public int? Take { get; set; }
public List<ListSortOption> Sort { get; set; }
public ListFilterOptions Filter { get; set; }
}
public class ListFilterOptions
{
public string Logic { get; set; }
public List<ListFilterOption> Filters { get; set; }
}
public class ListFilterOption
{
public string Field { get; set; }
public string Operator { get; set; }
public string Value { get; set; }
}
public class ListSortOption
{
public string Field { get; set; }
public string Dir { get; set; }
}
I didn't realise this format is already standard supported until #Lali pointed out this is standard body form serialisation.
I solved it now by creating some classes and just using this as parameter for the web API action, and it just magically works:
public async Task<IHttpActionResult> Get([FromUri] ListSelectionOptionsWithFilter options)
{
//query something
}
public class ListSelectionOptionsWithFilter
{
public int? Skip { get; set; }
public int? Take { get; set; }
public List<ListSortOption> Sort { get; set; }
public ListFilterOptions Filter { get; set; }
}
public class ListFilterOptions
{
public string Logic { get; set; }
public List<ListFilterOption> Filters { get; set; }
}
public class ListFilterOption
{
public string Field { get; set; }
public string Operator { get; set; }
public string Value { get; set; }
}
public class ListSortOption
{
public string Field { get; set; }
public string Dir { get; set; }
}

JsonConvert.DeserializeObject from PubNub message

When I send in this message to MakeAction manually it works and the message box pops up:
string json = #"{'action':'turncompleted', 'messageID':'123123123', 'playerID':'100000067174580', 'round':1, 'values':[{'longitude':21.09375, 'latitude':24.527134822598}, {'longitude':1.40625, 'latitude':23.885837699862}]}";
public void MakeAction(string message)
{
Poker_Server_v4_0.Action a = JsonConvert.DeserializeObject<Poker_Server_v4_0.Action>(message);
System.Windows.Forms.MessageBox.Show(a.action + a.messageID);
}
But when I use the message from PubNub it doesn't work:
static void DisplaySubscribeReturnMessage(string result)
{
//Receives the message from Pubnub takes care of the Action.
MessageToAction MTA = new MessageToAction();
MTA.MakeAction(result);
}
The message from PubNub differes a little bit from the one that I created manually:
[{\"action\":\"turncompleted\",\"messageID\":\"123123123\",\"playerID\":\"100000067174580\",\"round\":1,\"answers\":[{\"longitude\":21.09375,\"latitude\":24.527134822598},{\"longitude\":1.40625,\"latitude\":23.885837699862}]},\"13926740640746402\",\"chinese-jefecito\"]
I tried to remove the brackets and the slashes the text but then the slashes around the "values" values also got replaces.
I was wondering what I'm doing wrong here?
Here is the action class as well:
class Action
{
[JsonProperty("action")]
public string action { get; set; }
[JsonProperty("messageID")]
public string messageID { get; set; }
[JsonProperty("gameID")]
public string gameID { get; set; }
[JsonProperty("invitorFacebookID")]
public string invitorFacebookID { get; set; }
[JsonProperty("gametype")]
public string gametype { get; set; }
[JsonProperty("numberOfPlayers")]
public string numberOfPlayers { get; set; }
//public List<string> longitude { get; set; }
//public List<string> latitude { get; set; }
//public List<string> values { get; set; }
[JsonProperty("players")]
public List<Players> players { get; set; }
//Should be empty and removed!
[JsonProperty("values")]
public List<Value> values { get; set; }
public Action() { }
}
class Players
{
//Players
[JsonProperty("playerID")]
public string playerID { get; set; }
[JsonProperty("facebookID")]
public string facebookID { get; set; }
}
class Value
{
//Answers
[JsonProperty("longitude")]
public string longitude {get; set;}
[JsonProperty("latitude")]
public string latitude { get; set; }
}
Thanks in advance,
Tomas
Alright, rather than offering corrections I'll just give you the code I would use. Note the sample json you posted is not valid. I'm removing this part; \"13926740640746402\",\"chinese-jefecito\"] and closing the array of Action objects there. You can't have keys on their own in json (both those are keys without values) and also they're in the array rather than within an object. Anyway, here is the json I'm using;
[{\"action\":\"turncompleted\",\"messageID\":\"123123123\",\"playerID\":\"100000067174580\",\"round\":1,\"answers\":[{\"longitude\":21.09375,\"latitude\":24.527134822598},{\"longitude\":1.40625,\"latitude\":23.885837699862}]}]
public class Action
{
public string action { get; set; }
public string messageID { get; set; }
public string round { get; set; }
public Answer[] answers { get; set; }
}
public class Answer
{
public string longitude { get; set; }
public string latitude { get; set; }
}
Action[] actions = JsonConvert.DeserializeObject<Action[]>(jsonString);

Categories