I have this 4 models - 2 Domain Models and 2 DTOs
public class Project
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
public class Task
{
public int ID { get; set; }
public virtual int ProjectID { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
}
public class ProjectDTO
{
[Required]
public string Name { get; set; }
public List<TaskDTO> Tasks { get; set; }
}
public class TaskDTO
{
[Required]
public string Name { get; set; }
public int ID { get; set; }
public bool MarkRemove { get; set; }
}
Heres my automapper configuration
Mapper.CreateMap<Project, ProjectDTO>();
Mapper.CreateMap<ProjectDTO, Project>().ForMember(p =>p.ID, opt=>opt.Ignore()).ForMember(p=>p.Tasks, opt=>opt.Ignore());
Mapper.CreateMap<Task, TaskDTO>();
Mapper.CreateMap<TaskDTO, Task>().ForMember(task=>task.ProjectID, opt=>opt.Ignore()).ForMember(task=>task.Project, opt=>opt.Ignore());
Heres my HttpPost Edit action
[HttpPost]
public ActionResult Edit(int id, ProjectDTO p)
{
if (ModelState.IsValid)
{
var dbProject = db.Projects.Where(pr => pr.ID == id).Single();
Mapper.Map(p, dbProject);
foreach (var task in p.Tasks)
{
Task dbTask;
try
{
dbTask = dbProject.Tasks.Where(t => t.ID == task.ID).Single();
}
catch
{
dbTask = new Task();
Mapper.Map(task, dbTask);
dbProject.Tasks.Add(dbTask);
}
if (task.MarkRemove)
{
db.Tasks.Remove(dbTask);
}
else {
Mapper.Map(task, dbTask);
}
}
db.Entry(dbProject).State = EntityState.Modified;
db.SaveChanges();
TempData["Success"] = "Modelo Valido";
return RedirectToAction("Index");
}
return View(p);
}
Im not completely happy with this but I dont think there is a much cleaner approach to handling this somewhat complex scenario....
now that it is working I would like to at least refactor this to use repository pattern or something in a way that the controller action is not that convoluted.. this will eventually be production code :s
can anyone give me some advice on how to refactor this? please help.