возможно, этот вопрос задавался во многих формах и раньше, но все же я думаю, что их сценарий не дает четкого решения.
У меня есть следующие классы сущностей.
public class Project
{
public int ProjectId { get; set; }
[Required(ErrorMessage="please enter name")]
public string Name { get; set; }
public string Url { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public bool isFeatured { get; set; }
public bool isDisabled { get; set; }
public int GroupId { get; set; }
public virtual Group Group { get; set; }
[Required(ErrorMessage="Please select atleast one tag")]
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int TagId { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
public class Group
{
public int GroupId { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public virtual ICollection<Project> Projects { get; set; }
}
У меня есть viewmodelдля сущности проекта и пользовательского связывателя модели для этой модели представления.
public class NewProjectModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ProjectNewViewModel model = (ProjectNewViewModel)bindingContext.Model ??
(ProjectNewViewModel)DependencyResolver.Current.GetService(typeof(ProjectNewViewModel));
bool hasPrefix = bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName);
string searchPrefix = (hasPrefix) ? bindingContext.ModelName + ".":"";
//since viewmodel contains custom types like project make sure project is not null and to pass key arround for value providers
//use Project.Name even if your makrup dont have Project prefix
model.Project = model.Project ?? new Project();
//populate the fields of the model
if (GetValue(bindingContext, searchPrefix, "Project.ProjectId") != null)
{
model.Project.ProjectId = int.Parse(GetValue(bindingContext, searchPrefix, "Project.ProjectId"));
}
//
model.Project.Name = GetValue(bindingContext, searchPrefix, "Project.Name");
model.Project.Url = GetValue(bindingContext, searchPrefix, "Project.Url");
model.Project.CreatedOn = DateTime.Now;
model.Project.UpdatedOn = DateTime.Now;
model.Project.isDisabled = GetCheckedValue(bindingContext, searchPrefix, "Project.isDisabled");
model.Project.isFeatured = GetCheckedValue(bindingContext, searchPrefix, "Project.isFeatured");
model.Project.GroupId = int.Parse(GetValue(bindingContext, searchPrefix, "Project.GroupId"));
model.Project.Tags = new List<Tag>();
foreach (var tagid in GetValue(bindingContext, searchPrefix, "Project.Tags").Split(','))
{
var tag = new Tag { TagId = int.Parse(tagid)};
model.Project.Tags.Add(tag);
}
var total = model.Project.Tags.Count;
return model;
}
private string GetValue(ModelBindingContext context, string prefix, string key)
{
ValueProviderResult vpr = context.ValueProvider.GetValue(prefix + key);
return vpr == null ? null : vpr.AttemptedValue;
}
private bool GetCheckedValue(ModelBindingContext context, string prefix, string key)
{
bool result = false;
ValueProviderResult vpr = context.ValueProvider.GetValue(prefix + key);
if (vpr != null)
{
result = (bool)vpr.ConvertTo(typeof(bool));
}
return result;
}
}
//My project controller edit action defined as under:
[HttpPost]
[ActionName("Edit")]
public ActionResult EditProject( ProjectNewViewModel ProjectVM)
{
if (ModelState.IsValid) {
projectRepository.InsertOrUpdate(ProjectVM.Project);
projectRepository.Save();
return RedirectToAction("Index");
}
else {
ViewBag.PossibleGroups = groupRepository.All;
return View();
}
}
//Group Repository
public void InsertOrUpdate(Project project)
{
if (project.ProjectId == default(int)) {
// New entity
foreach (var tag in project.Tags)
{
context.Entry(tag).State = EntityState.Unchanged;
}
context.Projects.Add(project);
} else {
context.Entry(project).State = EntityState.Modified;
}
}
Теперь, когда у меня есть проект внутри вида редактирования, я выбираю новые теги для проекта и отправляю параметр действия редактирования формы, использую связующее звено модели и устанавливаемвсе свойства объекта проекта, включая теги.Но когда объект проекта передается методу inserttorupdate grouprepository, все сделанные нами изменения помещаются в базу данных, за исключением свойства коллекции Tags, теперь я действительно разочарован этой вещью.
Пожалуйста, предоставьте мне решение, которое не будет вносить изменений в структуру, было разработано до сих пор.