这是在MVC3中保存表单值的正确方法吗?
问题描述:
这里是我的代码:这是在MVC3中保存表单值的正确方法吗?
[HttpGet]
public ActionResult Register()
{
RegisterViewModel model = new RegisterViewModel();
using (CityRepository city = new CityRepository())
{
model.SelectCityList = new SelectList(city.FindAllCities().ToList(), "CityID", "CityName");
}
using (CountryRepository country = new CountryRepository())
{
model.SelectCountryList = new SelectList(country.FindAllCountries().ToList(), "CountryID", "CountryName");
}
return View(model);
}
[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
//Actually register the user here.
RedirectToAction("Index", "Home");
}
//Something went wrong, redisplay the form for correction.
return View(model);
}
这是最好的办法还是有另一种更好的方式进行测试?请记住,我的数据库表/字段名称与我在模型中声明的完全不同。我必须从ViewModel刮取值并将它们放入实体框架生成的类中以保存信息。
任何在这里尖叫你的错误?
答
这就是我通常使用的模式。
答
我使用的模式和它看起来像这样(重要的部分是AutoMapper部分)另一种模式:
[HttpPost] public ActionResult Register(RegisterViewModel model) { if (!ModelState.IsValid) { // repopulate any input or other items set in GET // prefer to do at top due to ^^^ is easy to overlook return View(model); } // if it's an edit, pull to new instance // from the database and use automapper to // map over the submitted values from model to instance // then update instance in database // // VALUE: useful if form only shows // some of the properties/fields of model // (otherwise, those not shown would be null/default) // if it's new, insert RedirectToAction("Index", "Home"); }
答
我更喜欢这种模式:
控制器:
[HttpGet]
public ActionResult Index()
{
var cities= (from m in db.cities select m);
ViewBag.Cities= cities;
var states = (from m in db.States select m);
ViewBag.States = states;
return View();
}
[HttpPost]
public ActionResult Index(RegisterViewModel model)
{
if (ModelState.IsValid)
{
// Saving the data
return View("ActionName", model);
}
return View();
}
查看:
@Html.DropDownList("DDLCities",new SelectList(ViewBag.Cities, "CityId" , "CityName"), new { @class = "className" })
@Html.DropDownList("DDLStates",new SelectList(ViewBag.States, "StateId" , "StateName"), new { @class = "className" })
答
名
劝更改[HttpGet]
:
[HttpGet]
public ActionResult Register()
{
// Get
var cities = new List<City>();
var countries = new List<Country>();
using (CityRepository city = new CityRepository())
{
cities = city.FindAllCities().ToList();
}
using (CountryRepository country = new CountryRepository())
{
counties = country.FindAllCountries().ToList();
}
// Map.
var aggregatedObjects = new SomePOCO(cities, countries);
var model = Mapper.Map<SomePOCO,RegisterViewModel>(aggregatedObjects);
// Return
return View(model);
}
变更摘要:
- 布局以这样的方式,控制器的工作是有意义的逻辑。 Get - Map - Return。控制器专为其设计的任务(按顺序)。
- 使用AutoMapper为您完成ViewModel创作的繁重工作。
劝更改您的[HttpPost]
:
[HttpPost]
public ActionResult Register(RegisterViewModel model)
{
if (!ModelState.IsValid)
return View(model);
try
{
var dbObj = Mapper.Map<RegisterViewModel,SomeDomainObj>(model);
_repository.Save(dbObj);
return RedirectToAction("Index");
}
catch (Exception exc)
{
if (exc is BusinessError)
ModelState.AddModelError("SomeKey", ((BusinessError)exc).FriendlyError);
else
ModelState.AddModelError("SomeKey", Resources.Global.GenericErrorMessage);
}
return View(model);
}
变更摘要:
- try/catch语句。始终需要捕获异常,无论它们是域例外还是较低级(数据库例外)
- 首先检查ModelState的有效性。正如@Cymen所说 - 先做,以便日后不要忘记
- 向ModelState添加异常。使用自定义异常类来处理具有描述性,基于资源的消息的业务错误。如果错误对用户而言太低(外键约束等),则显示一条通用消息