0

I need to create a nested JSON for a Trivia application using WebAPI. My Database structure is

TriviaQuiz - A Quiz can have many questions. TriviaQuestion - A Question can have many options (choices) TriviaOption - List of answers (choices)

I need to Produce JSON in below Format

{
    "quiz" : [{
        "id" : 1,
        "name" :"Guess Fruit Color",
        "description": "You need to guess color of fruits",
        "questions" : [
            {"id" : 1000 , "quizId" : 1 , "description": "The color of apple is" , "options" : [
                          {"id" : 1 , "questionId" : 1000 , "description" : "Green", "correctAnswer" : false },
                          {"id" : 2 , "questionId" : 1000 , "description" : "Red",   "correctAnswer" : true },
                          {"id" : 3 , "questionId" : 1000 , "description" : "Pink",  "correctAnswer" : false },
                          {"id" : 4 , "questionId" : 1000 , "description" : "Purple", "correctAnswer": false }      
            ]
            },
            {"id" : 1001 , "quizId" : 1 , "description": "The color of mangoss is" , "options" : [
                          {"id" : 5 , "questionId" : 1001 , "description" : "Green", "correctAnswer" : false },
                          {"id" : 6 , "questionId" : 1001 , "description" : "Red",   "correctAnswer" : false },
                          {"id" : 6 , "questionId" : 1001 , "description" : "Yello", "correctAnswer" : true },
                          {"id" : 8 , "questionId" : 1001 , "description" : "Purple", "correctAnswer": false }      
            ]
            }      
        ]}
    ]
}

I have designed my class like

public class TriviaQuiz
    {
        public int id { get; set; }
        public string name { get; set; }
        public string description { get; set; }

        //A Quiz can have many questions
        public virtual List<TriviaQuestion> questions { get; set; }
    }

public class TriviaQuestion
    {
        [Key(), ForeignKey("triviaQuiz")]
        public int id { get; set; }
        public string description { get; set; }

        //Navigation Property to set foreign key relationship
        [JsonIgnore]
        public virtual TriviaQuiz triviaQuiz { get; set; }

       //A question can have many options 
        public virtual List<TriviaOption> options { get; set; }
    }

public class TriviaOption
    {
        public int id { get; set; }
        [ForeignKey("triviaQuestion")]
        //Tell EF That questionId is a Foreign key to TriviaQuestion table
        public int questionId { get; set; }
        public string description { get; set; }
        public Boolean correctAnswer { get; set; }

        //Navigation Property to set up Foreign key relation ship
        [JsonIgnore]
        public virtual TriviaQuestion triviaQuestion { get; set; }
    }

My WebAPI Looks like this

public List<TriviaQuiz> getTopJson()
        {
            return _db.TriviaQuizs.ToList();
        }

Can some some suggest what is the best approach to generate JSON. Should I be creating a ViewModel for this?

When I run this I get an error: One or more validation errors were detected during model generation:

TriviaQuestion_triviaQuiz_Source: : Multiplicity is not valid in Role 'TriviaQuestion_triviaQuiz_Source' in relationship 'TriviaQuestion_triviaQuiz'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be 'enter code here1'.

I have already spend a week researching but not able to find anything relevant on the internet, Can some one help.

2 Answers 2

2

Can some some suggest what is the best approach to generate JSON. Should I be creating a ViewModel for this?

Nope just configure you web application to return json by default and return the object.

add

    /// <summary>
    /// The Web api config.
    /// </summary>
    public class WebApiConfig
    {
        /// <summary>
        /// Registers the specified configuration.
        /// </summary>
        /// <param name="config">The configuration.</param>
        public static void Register(HttpConfiguration config)
        {
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

            var settings = config.Formatters.JsonFormatter.SerializerSettings;

            settings.Formatting = Formatting.None;
            settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            settings.NullValueHandling = NullValueHandling.Ignore;
            settings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
            settings.DateParseHandling = DateParseHandling.DateTimeOffset;
            settings.Converters.Add(new OptionalJsonConverter());

to your app_start folder

When I run this I get an error: One or more validation errors were detected during model generation:

your using an ORM, I'm guessing from the message. You have a many-to-one defined but neither side owns the relationship. try adding public intTriviaQuiz triviaQuizId { get; set; }

As a general observation it looks like your using the same model for both the database and the api. I wouldn't advice this. Rather create models dedicated to the database and ones dedicated to the api (DTO's). Then map between them this may be a 1-1 mapping at present but will save you potential headaches in the long run.

Sign up to request clarification or add additional context in comments.

6 Comments

you beat me to it :)
I'd also suggest defining your models using Pascal casing as opposed to camelCasing because that is a standard .net naming convention. Then set the Json serializer to write camelCase using the CamelCasePropertyNamesContractResolver
I added these entries in Web.config to only return JSON but still getting same error. I have also removed Virtual keyword to disable lazy loading but did not help. So I am confused when you say Create DTO you mean create a ViewModel?
Your error is not to do with JSON, but the invalid model for your database.Yes DTO/ViewModel call it what you like but they will more or less a mirror of your db models. I suggest using automapper to map between them.
I am not able to find any DTO Code online. Can you please point to some sample code?
|
1

If the only purpose of this application is to provide the data, and not any presentation layer; you don't need to code a view model. It's also generally bad practice to use database layer attributes (Key, ForeignKey etc..) on the objects that you're serializing - you probably want a safer customized serializable version of the objects that you retrieved from database. For now just remove

[Key(), ForeignKey("triviaQuiz")]

and

[ForeignKey("triviaQuestion")]

from the objects, you can include Newtonsoft.JSon library to your project, and then just call

JsonConvert.SerializeObject(_db.TriviaQuizs.ToList());

1 Comment

He shouldn't need to call SerializeObject. WebApi will do that for him.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.