I am trying to show a RadioButtonList in Asp.Net MVC 3.0. This is my extension method:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Linq.Expressions;
using System.Text;
public static class HtmlExtensions
{
public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList)
{
StringBuilder stringBuilder = new StringBuilder();
var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
if (selectList != null)
{
foreach (var item in selectList)
{
var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value);
var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text));
var radio = htmlHelper.RadioButtonFor(expression, item.Value, new { id = id });
stringBuilder.AppendFormat("<div class=\"RadioButton\">{0}{1}</div>",radio.ToHtmlString(),label.ToHtmlString());
}
}
return new MvcHtmlString(stringBuilder.ToString());
}
}
These are my HomeController开发者_如何学JAVA action methods:
public ActionResult Index()
{
return View(GetIndexViewModel());
}
private IndexViewModel GetIndexViewModel()
{
List<SelectListItem> list = new List<SelectListItem>
{
new SelectListItem{ Selected = true, Value = "1", Text = "Sunday" },
new SelectListItem{ Selected = false, Value = "2", Text = "Monday" },
new SelectListItem{ Selected = false, Value = "3", Text = "Tuesday" },
new SelectListItem{ Selected = false, Value = "4", Text = "Wednesday" },
new SelectListItem{ Selected = false, Value = "5", Text = "Thursday" },
new SelectListItem{ Selected = false, Value = "6", Text = "Friday" },
new SelectListItem{ Selected = false, Value = "7", Text = "Saturday" },
};
return new IndexViewModel { SelectLists = list, SelectedItem = list[0] };
}
[HttpPost]
public ActionResult Index(IndexViewModel indexViewModel)
{
return View(GetIndexViewModel()); //this works
return View(indexViewModel); //why this doesn't work??
}
This is my index.cshtml:
@model IndexViewModel
@using (Html.BeginForm())
{
<h2>Select any one item</h2>
@Html.RadioButtonForSelectList(model => model.SelectedItem.Value, Model.SelectLists)
<br />
<input type="submit" value="Submit" />
}
I have commented which one works and which one doesn't. Basically my List becomes null. What am I doing wrong? If I have to do this everytime then it's better to use webforms because webforms can preserve data in postbacks. Using MVC basically means I have to make database call everytime the value is posted. Am I correct or there is some mistake in my code?
Because you bound something in the GET action doesn't mean at all that it will be bound back to the same property in the POST action. The default model binder binds only what it sees in the Request. So if this information is not sent to the server when posting it will be lost.
Your custom helper generates a bunch of radio buttons and labels, but I can't see you anywhere generating input fields for the text properties. As a consequence they will be lost.
This being said your helper looks correct and in your POST action you should simply refetch this information from the datastore you feteched it initially if you want to redisplay the same view. So the correct way to do this is the following:
[HttpPost]
public ActionResult Index(IndexViewModel IndexViewModel)
{
return View(GetIndexViewModel());
}
精彩评论