How to avoid ViewBag (or ViewData) in favor of a Model?
This is a very simple example, but it should be enough to demonstrate my issue. I need to pass a model to my view that the user will update, but the view also needs some other data to create a dropdownlist or to provide other开发者_如何学编程 information.
Based on my code below, I want to avoid use of ViewBag
/ViewData
, so do I somehow combine QuestionList
and PasswordLength
(thrown in for a superfluous example scenario) into the ChangeSecurityQuestionModel
or create a new ViewModel or some other object?
[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);
}
Why not put QuestionList and PasswordLength in your ChangeSecurityQuestionModel
var model = new ChangeSecurityQuestionModel() {
PasswordQuestion = user.PasswordQuestion,
QuestionList = new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question"),
PasswordLength = MembershipService.MinPasswordLength;
};
One alternative to the recurring "do-I-use ViewState or keep adding to a Model" problem is to create extension methods for HtmlHelper:
public static class HtmlExtensions
{
public static MvcHtmlString SecurityQuestionDropDown(this HtmlHelper helper)
{
return helper.DropDownList(....,new SelectList(membershipRepository.GetSecurityQuestionList(), "Question", "Question"));
}
}
You could add the QuestionList
and PasswordLength
properties to your ChangeSecurityQuestionModel
view model. And then:
[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);
}
精彩评论