DTO Organization in vNext API's
So lets face it, projects are getting more complicated, with more and more objects to keep track of. If you follow any type of agile process you're often creating an object per operation with the hopes that your technical debt will allow you to reactor the dupes later. If you're following a DRY principle or a seperation of concerns it can open add layers of abstraction that confuse your object graph even more.
I've faced this often in my projects, especially API projects. I was recently working on a prototype project using ASP.NET vNext (MVC 6) where Controllers for API and MVC Views are all first class now and share a base class, this makes Object DTO's a little blurry. In this project I've also incorporated Entity Framework 7, so all of my "model" classes are my true authority to my backing persistance layer.
Models
Data
Foo.cs
Bar.cs
Widget.cs
ViewModel
FooView.cs
BarView.cs
Widget.cs
ApiModel
FooPost.cs
FooPut.cs
FooDelete.cs
Bar..
...etc
So you get the point above. You can imagine what it's like to go back and add a required property later and have to go find every dependant view model and update it to add that property.
While I dont think this is revolutionary by any means, I think we often forget about sub classing objects to allow inheritance to work, and organization to naturally flow.
public class ForumSection
{
[Key]
public int ForumSectionId { get; set; }
public string SectionName { get; set; }
//Navigation Properties
public List<ForumGroup> ForumGroups { get; set; }
// API Models
public class CreateModel
{
public string SectionName { get; set; }
}
public class UpdateModel
{
public int ForumSectionId { get; set; }
public string SectionName { get; set; }
}
public class DeleteModel
{
public int ForumSectionId { get; set; }
}
}
Here's a real world object that I'm building, and using SubClassing to store the relevant view models, This also makes it extreemly clear inside the API model binding what I'm trying to accomplish.
// GET: api/values
[HttpGet]
public IEnumerable<ForumSection> Get()
{
return _context.ForumSections;
}
// GET api/values/5
[HttpGet("{id}")]
public ForumSection Get(int id)
{
return _context.ForumSections.Find(id);
}
// POST api/values
[HttpPost]
public void Post([FromBody]ForumSection.CreateModel value)
{
...//TODO: DO YOUR CLASS WORK HERE
}
I'd be interested in feedback on this, it's kind of a new concept I'm attempting to make inclusion or removal updates much more clear across related but not coupled types.