Return JSON from API method - c#

I am using ASP.net Core web api (c#) here
I have a JSON string as:
{
"userId":321,
"account":"new
"fname":"Adam",
"lname":"Silver"
"features":[
{
"available":true,
"status":open,
"admin":false
}
]
}
I want to test this data in my angular code so wanted to hardcode this into my API; then I want my API to return this back. What I am finding it hard is how to return this. Shall I return this as a string or need to parse it?
I have this method in my API:
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
Do I need to represent this into string or parse it someway?

Your JSON is invalid. We need to correct it. JSONLint can be helpful for that. I took your JSON and corrected the syntax errors until I got this:
{
"userId": 321,
"account": "new",
"fname": "Adam",
"lname": "Silver",
"features":[
{
"available": true,
"status": "open",
"admin": false
}
]
}
Then I need to generate a C# class structure to represent this JSON. I could manually create it, but the excellent json2csharp.com can generate it for me quickly. I fed this JSON into and received the following classes back:
public class Feature
{
public bool available { get; set; }
public string status { get; set; }
public bool admin { get; set; }
}
public class RootObject
{
public int userId { get; set; }
public string account { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public List<Feature> features { get; set; }
}
I put these class definitions into my application. Then I need to modify my action method to create an instance of this RootObject class (you should change the name to actually match what it's intended for).
[HttpGet]
public ActionResult<RootObject> Get()
{
// Create an instance of our RootObject and set the properties
var myRootObject = new RootObject();
myRootObject.userId = 321;
myRootObject.account = "new";
myRootObject.fname = "Adam";
myRootObject.lname = "Silver";
myRootObject.features = new List<Feature>();
// Create an instance of a feature and set its properties
var feature = new Feature();
feature.available = true;
feature.status = "open";
feature.admin = false;
// Add the new feature to the features collection of our RootObject
myRootObject.features.Add(feature);
// Return the instance of our RootObject
// The framework will handle serializing it to JSON for us
return myRootObject;
}
Note that I changed the signature of your method. I made it no longer accept an IEnumerable because it wasn't clear why you had that. And I changed it to return an ActionResult after checking Microsoft's documentation.

Hi Please find correct JSON format for above one:
{
"userId": 321,
"account": "new",
"fname": "Adam",
"lname": "Silver",
"features": [{
"available": true,
"status": "open",
"admin": false
}]
}
you can use below class in your web API to pass respective data
public class Feature
{
public bool available { get; set; }
public string status { get; set; }
public bool admin { get; set; }
}
public class RootObject
{
public int userId { get; set; }
public string account { get; set; }
public string fname { get; set; }
public string lname { get; set; }
public List<Feature> features { get; set; }
}
then at the end, while returning data, convert the respective class object into JSON by serializing that into JSON format.
Hope it will fulfill your requirement.

Putting the comments into an answer:
If you are using ActionResult, I'll assume you are using asp.net mvc. What you want is JsonResult.
[HttpGet]
public JsonResult Get()
{
return new JsonResult
{
Data = new
{
userId = 321,
account = new
{
fname = "Adam",
lname = "Silver",
features = new object[]{
new
{
available = true,
status = "open",
admin = false
}
}
}
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

Related

Parsing json. Field could be plain text and object

Shortly, I'm trying to create some web-API-application and I'm parsing telegram data and I am faced up with a problem.
When I get all the JSON, I see that the program can't parse it because some field(text) couldn't resolve the object(code snip below). I'm thinking about creating a custom JSON converter(that's annoying, so that's the reason why I'm here), but maybe I just don't know how to do it correctly.
Here are examples:
{
"text": "SOME VERY VERY VERY PRIVATE INFORMATION",
},
AND
{
"text": [
{
"type": "link",
"text": "SOME VERY VERY VERY PRIVATE LINK :D(probably, onlyfans)"
}
],
}
I usually use a JsonConstructor in this case. You don't need to pass all properties into the constructor, you can pass only the properties that cause a problem.
using Newtonsoft.Json;
Data data = JsonConvert.DeserializeObject<Data>(json);
public class Data
{
public List<Text> text { get; set; }
[JsonConstructor]
public Data(JToken text)
{
if (text.Type == JTokenType.String)
this.text = new List<Text> { new Text { text = (string)text } };
else this.text = text.ToObject<List<Text>>();
}
}
public class Text
{
public string type { get; set; }
public string text { get; set; }
}
I would use system.text.json More info here
and here
public class Data
{
[JsonPropertyName("text")]
public IEnumerable<TextInformation> TextInformations{ get; set; }
}
public class TextInformation
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
and use it like this
var text = JsonSerializer.Deserialize<Data>(jsonString)

Q: How to form LINQ query to access nested attributes within class to display on Blazor WASM application

My apologies for the vast amount of code, but it is necessary for the context of the problem. I am faced with an interesting dilemma that I have not been able to solve. I am trying to access information from model called Repository. Repository contains nested classes and lists, and looks like this:
{
public User User { get; set; }
}
public class User
{
public PinnedItems PinnedItems { get; set; }
}
public class PinnedItems
{
public List<Nodes> Nodes { get; set; }
}
public class Nodes
{
public string Name { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public RepositoryTopics RepositoryTopics { get; set; }
}
public class RepositoryTopics
{
public List<TopicNodes> Nodes { get; set; }
}
public class TopicNodes
{
public Topic Topic { get; set; }
}
public class Topic
{
public string Name { get; set; }
}
I have the following method within a web api controller. It is responsible for grabbing my github repositories using graphql. This method looks like this:
{
var request = new GraphQLHttpRequest
{
Query = #"query($username: String!){
user(login: $username) {
pinnedItems(first: 6, types: REPOSITORY) {
nodes {
... on Repository {
name
description
url
repositoryTopics(first:6){
nodes{
topic{
name
}
}
}
}
}
}
}
}
",
Variables = new
{
username = _configuration.GetSection("GithubUserName").Value
}
};
var graphQlResponse = await CreateClient().SendQueryAsync<Repository>(request);
var repo = new Repository
{
User = graphQlResponse.Data.User
};
return Ok(repo);
}
repo is of type Repository.
This is an example piece of JSON that comes back from testing the controller in swagger.
"pinnedItems": {
"nodes": [
{
"name": "personal-website",
"description": "My personal website",
"url": "https://github.com/personal-website",
"repositoryTopics": {
"nodes": [
{
"topic": {
"name": "blazor-webassembly"
}
},
{
"topic": {
"name": "web-api"
}
},
{
"topic": {
"name": "contentful-api"
}
},
{
"topic": {
"name": "contentful"
}
}
]
}
}
I am accessing the code in my blazor component with the following:
Repository SoftwareRepos = new Repository();
protected async override Task OnInitializedAsync()
{
SoftwareRepos = await graphQLquery.GetRepositories();
}
}
And some example code such as this gets me the list of projects as a name.
#foreach(var name in SoftwareRepos.User.PinnedItems.Nodes.Select(x => x.Name).ToArray())
{
#name
}
PRINTS OUT: name, name, name, name
Ideally I would want something that looks like this:
Project One, Description, URL, html, css, react, javascript (a list of tags)
I am having trouble trying to construct LINQ queries to access this nested information (particularly repositoryTopic -> TopicNodes -> Nodes -> Topics -> Name.
I am seeking advice on how to approach this situation, or maybe some alternative solutions to what I am doing as I suspect I am a little out of my depth here. I am using graphql.client to send and retrieve information from github.
first thing to do is to deserialize that JSON into a class structure that it represents.
public class GitResponse{
public Node[] PinnedItems {get;set;}
}
public class Node{
public string Name {get;set};
public string Description {get;set;}
....
}
etc. Once this is done the rest is easy , you just walk that tree
deserialize with
System.Text.Json.Serailizer.Deserialize<GitResponse>(json);

How to use POST request to create an object in C# API?

So I'm trying to make this parking ticket system and I'm currently creating these objects manually in the code for testing. Now I've come to the step where my POST request in postman should be able to create an object in the memory of the app. I've got two classes one for a ''Car'' and one for the ''Ticket''.
public class Car
{
public string regNr { get; set; }
public string carBrand { get; set; }
public string carColor { get; set; }
public List<Ticket> ticketlist {get; set;}
public Car()
{
this.ticketlist = new List<Ticket>();
}
public void addNewTicket(Ticket newTicket)
{
ticketlist.Add(newTicket);
}
}
}
public class Ticket
{
public int ticketID { get; set; } = 0;
public DateTime date { get; set; }
public string comment { get; set; }
public int parkingAreaID { get; set; }
public int parkingsOfficerID { get; set; }
}
}
List<Bil> list = new List<Car>();
public void Post([FromBody]Bil val)
{
list.Add(val);
}
The GET requests work and I want to be able to add a new ticket to a registration number by using my post request.
My current output is this;
{
"regNr": "BT66358",
"carBrand": "BMW",
"carColor": "Yellow",
"ticketlist": [
{
"ticketID": 1,
"date": "2020-12-12T17:49:34.4000401+01:00",
"comment": "very bad parking",
"parkingsAreaID": 1,
"parkingsOfficerID": 2
},
{
"ticketID": 2,
"date": "2020-12-12T17:49:34.4000401+01:00",
"comment": "very bad parking",
"parkingsAreaID": 2,
"parkingsOfficerID": 2
}
]
}
---------------UPDATE-----------
Bil = Car
botliste = ticketlist
liste = list
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/q3UaO.png
If I understood you correctly, then most likely you just need to add some attributes, and you get something like this:
List<Car> list = new List<Car>();
[HttpPost]
[HttpPost("SomeRoute")]
public IActionResult Post([FromBody] Car val)
{
if (val == null)
{
return BadRequest("Car data must be filled");
}
if (string.IsNullOrEmpty(val.regNr))
{
return BadRequest("Reg number must be filled");
}
var car = list.FirstOrDefault(c => string.Equals(c.regNr, val.regNr));
if (car != null)
{
car.ticketlist.AddRange(val.ticketlist);
}
else
{
list.Add(val);
}
/// And return IActionResult
return Ok();
}
P.S. Give a description of the Bil type to get a more detailed answer.
upd:
You can also add attributes to the fields of your classes that will validate the values, for example:
...
public class Car
{
[MinLength(6, ErrorMessage = "regNr field must be at least 6 characters")]
public string regNr { get; set; }
...
The "MinLength" attribute indicates that the value for this property is required, and must be at least 6 characters.
More details here: https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations?view=net-5.0
upd2:
This is how I get to invoke this method:

Getting null value from Web api

I am trying to store a List of strings that are members of a conversation.
[DataContract]
public class Conversation
{
[Key]
[DataMember]
public string Key { get; set; }
[DataMember]
public string ConversationName { get; set; }
[DataMember]
public string Administrator { get; set; }
[DataMember]
public List<string> Members { get; set; }
public Conversation(string key, string name, string admin, List<string> members)
{
Key = key;
ConversationName = name;
Administrator = admin;
Members = members;
}
public Conversation()
{
}
}
I am using Postman to make a Post request to the URI which seems to work fine, returning 201 Created and giving a json object containing the correct info.
This is the json I am posting:
{
"Key": "123",
"ConversationName": "Test",
"Administrator": "Ken",
"Members": ["y#12.com", "f#78.com"]
}
However, when I try to get the conversation in a GET method this is the result:
{
"Key": "123",
"ConversationName": "Test",
"Administrator": "Ken",
"Members": null
}
These are my functions in my controller:
Post:
[HttpPost]
//[ResponseType(typeof(Conversation))]
public async Task<IHttpActionResult> PostConversation(Conversation convo)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Conversations.Add(convo);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { name = convo.Key }, convo);
}
GET:
[HttpGet]
public IQueryable<Conversation> GetConversations()
{
return db.Conversations;
}
Any help would be much appreciated. Thanks!
The post basically returns the entity as you offer it, which is with Members, apparently.
The get loads a Conversation from the database. It can't have any Members at that moment, because Members is a List<string>, which can't possibly be mapped to a database column.
You probably expect the post to store the Members into the database. This doesn't happen, because you should use Member entities in stead of strings. Member can be a simple class having an Id and a string property.

Converting .Net object to JSON missing most properties

I'm playing around with Web API 4 for the first time and preparing to hook up connection to a MongoDb. I've defined some simple objects to represent the models but when I try to return a collection of them from the GET request of my API only one property is being included in the resulting JSON object.
public class Topic : Entity
{
public string Name { get; set; }
public List<Topic> Parents { get; set; }
public List<Topic> Children { get; set; }
public List<ContentNode> ContentNodes { get; set; }
}
public class ContentNode
{
public enum ContentNodeType { VIDEO, TEXT, AUDIO };
public ContentNodeType ContentType { get; set; }
public string Url { get; set; }
public List<int> Scores { get; set; }
public List<Link> Links { get; set; }
public List<string> Comments { get; set; }
}
public string Get()
{
List<Topic> topics = new List<Topic>();
var programming = new Topic()
{
Id = "1",
Name = "Programming"
};
var inheritanceVideo = new ContentNode()
{
ContentType = ContentNode.ContentNodeType.VIDEO,
Url = "http://youtube.com",
Scores = new List<int>() {
4, 4, 5
},
Comments = new List<string>() {
"Great video about inheritance!"
}
};
var oop = new Topic()
{
Id = "2",
Name = "Object Oriented Programming",
ContentNodes = new List<ContentNode>() {
inheritanceVideo
}
};
programming.Children.Add(oop);
topics.Add(programming);
string test = JsonConvert.SerializeObject(topics);
return test;
}
I'm using the JSON.Net library to serialize the object here but I previously used the default JSON serializer and had the GET return IEnumerable<Topic>. In both cases the JSON being returned is simply:
"[{\"Id\":\"1\"}]"
A browser request for the XML works just fine. According to the documentation for JSON.Net it doesn't seem like there should be a problem serializing these classes to JSON. Any thoughts on why this isn't working? It doesn't seem like I should need to apply explicit attributes for every member.

Categories