おそらく、この質問は以前に多くの形で尋ねられてきましたが、それでもシナリオでは明確な解決策ではないと思います.
次のエンティティクラスがあります。
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; }
}
プロジェクト エンティティのビューモデルと、このビューモデルのカスタム モデル バインダーがあります。
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;
}
}
編集ビュー内にプロジェクトがあり、プロジェクトの新しいタグを選択し、フォーム編集アクション パラメーターを送信すると、モデル バインダーを使用し、タグを含むプロジェクト オブジェクトのすべてのプロパティを設定します。しかし、プロジェクト オブジェクトが grouprepository の insertorupdate メソッドに渡されると、行ったすべての変更が、タグ コレクション プロパティを除いてデータベースに保存されます。
これまで開発してきた構造を変えないような解決策を教えてください。