4

I'm having this model :

public class Quiz
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int CurrentQuestion { get; set; }
    [JsonIgnore]
    public virtual ICollection<Question> Questions { get; set; } 
}

There is [JsonIgnore] which tells JSON Serializer to ignore this field(Questions). So,I'm having an action which returns serialized Quiz without Questions. I have to implement another action which will return all fields (Questions inclusive). How can I do this ? I need both actions.

2
  • Probably the simplest way would be to simply copy all the information to another class (with the same variables but no [JsonIgnore] attributes), and then serialize that. Commented Oct 16, 2015 at 12:43
  • Why not have 2 classes. Everything but Questions goes into a class called CurrentQuestion, then Quiz has a CurrentQuestion Object and the collection. Then you can have a "GetCurrentQuestion" action, and a "GetQuiz" action Commented Oct 16, 2015 at 12:45

3 Answers 3

5

It's very good practice not to return your domain models from and API. Better way is to create view model classes and return them instead.

So in your example you'd simply create:

public class QuizViewModel 
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int CurrentQuestion { get; set; }
}

and use it to return data from your API.

Obviously in some bigger classes it would be nightmare to crate the code copying all the properties, but don't worry - Automapper (http://automapper.org/) comes to rescue! :)

//Best put this line in app init code
Mapper.CrateMap<Quiz, QuizViewModel>();

//And in your API
var quiz = GetSomeQuiz();
return Mapper.Map<QuizViewModel>(quiz);

You then create another view model class with Questions field in the same way.

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

Comments

2

You need to slightly change your code as below although its very simple :)

    [Serializable]
    public class Quiz
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public int CurrentQuestion { get; set; }
    }

    [Serializable]
    public class QuizWithQuestions : Quiz
    {
        public ICollection<Question> Questions { get; set; }
    }

Now when you want to include Collection of Questions as well use QuizWithQuestions class.

2 Comments

Excellent, but why have you put Quiz as abstract class ?
Sorry old habbit :P @XavierWOLFF
0

I had the similar problem. And my solution is:
By default I have DBContext with disable LazyLoading:

        public EFDbContext()
            :base("EFDbContext")
        {
            this.Configuration.ProxyCreationEnabled = true;
            this.Configuration.LazyLoadingEnabled = false;
        }

So, all navigation property (like Questions) will be NULL. Then in my WebAPIConfig I configure formatter to hide null values:

            config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
                = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling
                 = Newtonsoft.Json.NullValueHandling.Ignore;

When I need a result with all fields from model then I just turn on the LazyLoading in controller:

 repository.SwitchLazyLoading(true);

The method in repository:

       public void SwitchLazyLoading(bool value)
        {
             this.context.Configuration.LazyLoadingEnabled = value;
        }

I do not use [JsonIgnore] I use only [IgnoreDataMember] Please look at the Switches for LazyLoading with Repository pattern

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.