ASP.Net MVC 和状态 - 如何从双列表框中的会话更改更新数据库?

ASP.Net MVC and state - How to update the database from Session changes in dual listboxes?

我正在开发一个双列表框系统,操作员可以在其中为特定用户制度分配和删除不同的练习。对于 RemoveExercises 函数,我已经开始使用 Session 以便 RequestedExercises 列表框根据所做的更改(添加和删除练习)进行更新。

目前,AddExercises 函数将练习从 AvailableExercises 列表框添加到数据库上的 RequestedExercises 列表框(也称为 RegimeItems),但它不会显示在 RequestedExercises 列表框中,直到我返回页面。

然而,RemoveExercises 函数会从 RequestedExercises 列表框中删除选定的练习,但不会对数据库进行更改。所以这两个功能只完成了我希望它们完成的一半,但方式不同。

这让我相信由于会话状态,添加的练习没有显示在 RequestedExercises 列表框中,并且 RemoveExercises 没有更新其对数据库的更改。任何帮助将不胜感激。

UPDATE:在 post 请求中将 return View(model); 更改为 return RedirectToAction("ExerciseIndex", new { id = model2.UserID, vmodel = model2 }); 后,添加练习效果很好。 我应该怎么做才能让 RemoveExercises 对域对象 User 起作用?

Controller.cs

    [HttpGet]
    public ActionResult ExerciseIndex(int id, UserExerciseViewModel vmodel)
    {
        User user = db.Users.Find(id);
        UserExerciseViewModel model = new UserExerciseViewModel { AvailableExercises = GetAllExercises(), RequestedExercises = ChosenExercises(user, vmodel) };
        model.UserID = user.UserID;
        Session["UserExerciseViewModel"] = model;
        return View(model);
    }

    [HttpPost]
    public ActionResult ExerciseIndex(UserExerciseViewModel model, string add, string remove, string send, int id, RegimeItem item)
    {
        UserExerciseViewModel model2 = (UserExerciseViewModel)(Session["UserExerciseViewModel"]);
        model.RequestedExercises = model2.RequestedExercises;
        model.AvailableExercises = model2.AvailableExercises;
        if (!string.IsNullOrEmpty(add))
            AddExercises(model, id);
        else if (!string.IsNullOrEmpty(remove))
            RemoveExercises(model, id);
        User user = db.Users.Find(model2.UserID);
        model2.RequestedExercises = ChosenExercises(user, model);
        user.RegimeItems = model.RequestedExercises;
        RestoreSavedState(model, user);
        return RedirectToAction("ExerciseIndex", new { id = model2.UserID, vmodel = model2 });
    )

    void RemoveExercises(UserExerciseViewModel model, int id)
    {
        var userExerciseViewModel = (UserExerciseViewModel)(Session["UserExerciseViewModel"]);
        foreach (int selected in model.RequestedSelected)
        {
            RegimeItem item = model.RequestedExercises.FirstOrDefault(i => i.RegimeItemID == selected);
            if (item != null)
            {
                model.RequestedExercises.Remove(item);
            }
        }
        db.SaveChanges();
    }

    void AddExercises(UserExerciseViewModel model, int id)
    {
        var userExerciseViewModel = (UserExerciseViewModel)(Session["UserExerciseViewModel"]);
        foreach (int selected in model.AvailableSelected)
        {
            if (model.AvailableSelected != null)
            {
                User user = db.Users.Find(id);
                user.RegimeItems.Add(new RegimeItem()
                {
                    RegimeExercise = (this.GetAllExercises().FirstOrDefault(i => i.ExerciseID == selected))
                });
            }
        }
        db.SaveChanges();
    }

    void RestoreSavedState(UserExerciseViewModel model, User user)
    {
        user.RegimeItems = this.ChosenExercises(user, model);
        if (!string.IsNullOrEmpty(model.SavedRequested))
        {
            string[] exIds = model.SavedRequested.Split(',');
            var regimeItems = ChosenExercises(user, model).Where(p => exIds.Contains(p.RegimeItemID.ToString()));
            model.RequestedExercises.AddRange(regimeItems);
        }
        db.SaveChanges();
    }

    private List<Exercise> GetAllExercises() //Gets all the data for AvailableExercises
    {
        return db.Exercises.ToList();
    }

    private List<RegimeItem> ChosenExercises(User user, UserExerciseViewModel model) //Gets all the data for RequestedExercies
    {
     return db.Users
     .Where(u => u.UserID == user.UserID)
     .SelectMany(u => u.RegimeItems)
     .ToList();
    }

型号(cs)

 public class User
    {
        public int UserID { get; set; }
        public ICollection<RegimeItem> RegimeItems { get; set; }
        public User()
        {
            this.RegimeItems = new List<RegimeItem>();
        } 
    }
    public class RegimeItem
    {
        public int RegimeItemID { get; set; }
        public Exercise RegimeExercise { get; set; }
    }

ViewModel(cs)

public class UserExerciseViewModel
{
    public List<Exercise> AvailableExercises { get; set; }
    public List<RegimeItem> RequestedExercises { get; set; }
    public int? SelectedExercise { get; set; }
    public int[] AvailableSelected { get; set; }
    public int[] RequestedSelected { get; set; }
    public string SavedRequested { get; set; }
    public int UserID { get; set; }
}

查看(仅限片段(cshtml))

<td valign="top">
   @Html.ListBoxFor(model => model.AvailableSelected, new MultiSelectList(Model.AvailableExercises, "ExerciseID", "Name", Model.AvailableSelected))
</td>
<td valign="top">
  <input type="submit" name="add"
  id="add" value=">>" /><br />
  <input type="submit" name="remove"
  id="remove" value="<<" />
</td>
<td valign="top">
    @Html.ListBoxFor(model => model.RequestedSelected, new MultiSelectList(Model.RequestedExercises, "RegimeItemID", "RegimeExercise.Name", Model.RequestedSelected))
</td>

更新:将 RemoveExercises 更改为此修复了删除问题:

void RemoveExercises(UserExerciseViewModel model, int id)
{
    var userExerciseViewModel = (UserExerciseViewModel)(Session["UserExerciseViewModel"]);
    foreach (int selected in model.RequestedSelected)
    {
        if (model.RequestedSelected != null)
        {
            User user = db.Users.Find(id);
            RegimeItem item = db.RegimeItems.Find(selected);
            item.RegimeExercise = this.GetAllExercises().FirstOrDefault(i => i.ExerciseID == selected); //--this removes the regimeexercise
            user.RegimeItems.Remove(item); //deletes the user's regimeitem
            db.RegimeItems.Remove(item); //removes the regimeitem itself 
        }
    }
    db.SaveChanges();

Currently the AddExercises function adds the exercise from the AvailableExercises listbox to the RequestedExercises listbox (also known as RegimeItems) on the database but it doesn't show up on the RequestedExercises listbox until i go back into the page.

不会,因为您不更新模型,只更新用户/数据库。

void AddExercises(UserExerciseViewModel model, int id)
    {
        var userExerciseViewModel = (UserExerciseViewModel)(Session["UserExerciseViewModel"]);
        foreach (int selected in model.AvailableSelected)
        {
            if (model.AvailableSelected != null)
            {
                User user = db.Users.Find(id);
                user.RegimeItems.Add(new RegimeItem()
                {
                    RegimeExercise = (this.GetAllExercises().FirstOrDefault(i => i.ExerciseID == selected))
                });
            }
        }
        db.SaveChanges(); // db is updated but your model isn't
    }

The RemoveExercises function however, removes a selected exercise from the RequestedExercises listbox but doesn't make the changes to the database.

不会,因为您只更新模型而不是用户。

 void RemoveExercises(UserExerciseViewModel model, int id)
    {
        var userExerciseViewModel = (UserExerciseViewModel)(Session["UserExerciseViewModel"]);
        foreach (int selected in model.RequestedSelected)
        {
            RegimeItem item = model.RequestedExercises.FirstOrDefault(i => i.RegimeItemID == selected);
            if (item != null)
            {
                model.RequestedExercises.Remove(item);
            }
        }
        db.SaveChanges(); // What is the point of this? You didn't alter the user?
    }

通常,您在这里要做的是使方法 AddRemove 都在域对象 User 上工作,以便适当地更新数据库,然后而不是

return View(model)

您将重定向到您的 GET 操作。

   return RedirectToAction("ExerciseIndex", new { id = model2.ID, vmodel= model2 });

您通常只会 return 模型到视图,如果它有错误,您甚至似乎没有检查:

if (ModelState.IsValid){ ...}

还要注意您是如何找到用户的。您在 ExerciseIndex 中(无条件地)执行一次,然后在 Remove 中再次执行。为什么不直接在 ExerciseIndex 的顶部执行并传递给 Remove