RandomBoy
RandomBoy

Reputation: 464

ASP.net Web api response - looping data

Iam using ADO.net as my ORM tool in my MVC 5 app, and the problem is :

look at this simple line:

    public async Task<IHttpActionResult> GetMyMessage(int id)
    {

        List<Messages> messages = await db.Messages.Where(a => a.GroupID == id).ToListAsync();


        return Ok(messages);

    }

The problem is here that I didn't inclued any data(e.g. db.Messages.Include(something...)) to my messages but stil in response i got e.g all Users collections, and other stuff that my message table is connected with in DB.

my global asax is:

protected void Application_Start()
    {

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

    }

Does anyone Know how to get rid off this linked tables and have clean json response. Otherwise i would have to do some workaround and clean it a bit. ?

Upvotes: 1

Views: 1999

Answers (2)

ntl
ntl

Reputation: 1299

You should disable lazy loading for your context. I think that related entities are loaded when the main objects that you want to return are serialized.

Example from msdn:

public class MyContext : DbContext
{
    public MyContext()
    {
        this.Configuration.LazyLoadingEnabled = false;
    }
}

Upvotes: 1

Neil Smith
Neil Smith

Reputation: 2565

This sounds like a case for ViewModels. Instead of returning your Message entity you can create a new type with only the properties you care about for that result. Say your entities look like:

public class Message {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual User User { get; set; }
    public virtual Group Group { get; set; }
}

public class User {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Message> Messages { get; set; }
}

public class Group {
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Message> Messages { get; set; }
}

And you have an endpoint that retrieves a Message by the Group Id but does not want any info about the User or Group. Create a ViewModel to represent the actual response you want:

public class MessageViewModel {
    public int Id { get; set; }
    public string Name { get; set; }
}

And then convert the entity to the ViewModel:

public async Task<IHttpActionResult> GetMyMessage(int id)
{
    var messages = await db.Messages.Where(a => a.Group.Id == id).ToListAsync();
    var models = messages.Select(
        m => new MessageViewModel {
            Id = m.Id, 
            Name = m.Name
        }).ToList();

    return Ok(models);
}

And now something like the following is returned:

[{id: 1, name: 'SomeMessageName'}, {id: 2, name: 'SomeOtherMessageName'}, ...]

Upvotes: 2

Related Questions