C# 如何避免ViewBag(或ViewData)使用模型?

C# 如何避免ViewBag(或ViewData)使用模型?,c#,asp.net-mvc,asp.net-mvc-3,C#,Asp.net Mvc,Asp.net Mvc 3,这是一个非常简单的例子,但足以说明我的问题。我需要将一个模型传递给我的视图,用户将更新该模型,但是视图还需要一些其他数据来创建dropdownlist或提供其他信息 基于我下面的代码,我想避免使用ViewBag/ViewData,那么我是否要以某种方式将QuestionList和PasswordLength(为多余的示例场景而引入)组合到ChangeSecurityQuestionModel中,或者创建一个新的ViewModel或其他对象 [Authorize] public ActionRes

这是一个非常简单的例子,但足以说明我的问题。我需要将一个模型传递给我的视图,用户将更新该模型,但是视图还需要一些其他数据来创建dropdownlist或提供其他信息

基于我下面的代码,我想避免使用
ViewBag
/
ViewData
,那么我是否要以某种方式将
QuestionList
PasswordLength
(为多余的示例场景而引入)组合到
ChangeSecurityQuestionModel
中,或者创建一个新的ViewModel或其他对象

[Authorize]
public ActionResult ChangeSecurityQuestion() {
  var user = Membership.GetUser();
  if (user != null) {
    var model = new ChangeSecurityQuestionModel() {
      PasswordQuestion = user.PasswordQuestion
    };
    ViewBag.QuestionList = new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question");
    ViewBag.PasswordLength = MembershipService.MinPasswordLength;
    return View(model);
  }

  // user not found
  return RedirectToAction("Index");
}

[Authorize]
[HttpPost]
public ActionResult ChangeSecurityQuestion(ChangeSecurityQuestionModel model) {
  if (ModelState.IsValid) {
    var user = Membership.GetUser();
    if (user != null) {
      if (user.ChangePasswordQuestionAndAnswer(model.Password, model.PasswordQuestion, model.PasswordAnswer)) {
        return View("ChangeQuestionSuccess");
      } else {
        ModelState.AddModelError("", "The password is incorrect.");
      }
    }
  }

  // If we got this far, something failed, redisplay form
  ViewBag.QuestionList = new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question");
  ViewBag.PasswordLength = MembershipService.MinPasswordLength;
  return View(model);
}

为什么不在ChangeSecurityQuestionModel中添加问题列表和密码长度

var model = new ChangeSecurityQuestionModel() {
      PasswordQuestion = user.PasswordQuestion,
      QuestionList = new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question"),
      PasswordLength = MembershipService.MinPasswordLength;
    };

您可以将
QuestionList
PasswordLength
属性添加到
ChangeSecurityQuestionModel
视图模型中。然后:

[Authorize]
public ActionResult ChangeSecurityQuestion() {
    var user = Membership.GetUser();
    if (user != null) {
        var model = new ChangeSecurityQuestionModel() {
            PasswordQuestion = user.PasswordQuestion,
            QuestionList = new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question"),
            PasswordLength = MembershipService.MinPasswordLength
        };
        return View(model);
    }
    // user not found
    return RedirectToAction("Index");
}

[Authorize]
[HttpPost]
public ActionResult ChangeSecurityQuestion(ChangeSecurityQuestionModel model) {
    if (ModelState.IsValid) {
        var user = Membership.GetUser();
        if (user != null) {
            if (user.ChangePasswordQuestionAndAnswer(model.Password, model.PasswordQuestion, model.PasswordAnswer)) {
                return View("ChangeQuestionSuccess");
            } else {
                ModelState.AddModelError("", "The password is incorrect.");
            }
        }
    }
    // If we got this far, something failed, redisplay form
    model.QuestionList = new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question");
    model.PasswordLength = MembershipService.MinPasswordLength;
    return View(model);
}

重复出现的“do-I-use ViewState或keep adding to a Model”问题的一个替代方法是为HtmlHelper创建扩展方法:

public static class HtmlExtensions
{
     public static MvcHtmlString SecurityQuestionDropDown(this HtmlHelper helper)
     {
          return helper.DropDownList(....,new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question"));
     }
}

这似乎是显而易见的答案,但我不确定这是否是一个合适的位置,因为模型中的其他属性与用户相关并由用户更新。谢谢。如果你能接受,这就是我想知道的。另外,
ChangePasswordQuestionAndAnswer
在这段代码中是一种方法,不是一种模型,但我理解你所说的。再次感谢你,达林。我需要得到保证,这是一个好办法。对不起,不过,我不得不接受多夫的回答,因为基本上是一样的,他先回答。啊,这是一个有趣的想法。+1-html帮助程序可以被重用,用于解决像这样的目标问题,确实可以将模型污染降到最低程度。这不是假设您有一个静态成员资格存储库吗?@dove只需使用与控制器相同的设置,除非它依赖于http上下文。这似乎是DTO模式的尖叫抱歉,我讨厌看到这张脸上的表情如果(user==null)返回RedirectToAction(“索引”)//“用户现有代码”我倾向于将MVC模型看得更像视图模型,因此添加到ChangeSecurityQuestionModel也是我会采取的方法。回到我在.NET中开发时,我的视图和输入模型是分开的,所以在这个示例中,我会使用“视图模型”,其中包括PasswordQuestion、QuestionList和PasswordLength。。。然后我会有一个“输入模型”,不包括这些信息,只是输入。。。当然,我也大量使用了ajax帖子,因为我不必维护帖子之间的状态(即,重新填充视图模型)。