这是在 MVC3 中保存表单值的正确方法吗?

发布于 2024-11-30 03:10:19 字数 946 浏览 1 评论 0原文

这是我的代码:

[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 中抓取值并将它们放入实体框架生成的类中以保留信息。

这里有什么事情让你大喊大叫是错的吗?

Here's my code:

[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);
}

Is this the best approach or is there another better tested way? Keep in mind that my database tables/field names are nothing like what I declared in my models. I have to scrape the values from the ViewModel and put them into an entity framework generated class to persist the information.

Anything here that screams out at you as wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天涯离梦残月幽梦 2024-12-07 03:10:19

我使用该模式和另一个如下所示的模式(重要部分是 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");
}

I use that pattern and another pattern which looks like this (important part is the AutoMapper part):

[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");
}
睫毛上残留的泪 2024-12-07 03:10:19

这是我通常使用的模式。

That's the pattern I generally use.

临风闻羌笛 2024-12-07 03:10:19

我更喜欢这种模式:
控制器:

 [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" })

I prefer this pattern:
Controller:

 [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();
    }

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" })
原谅过去的我 2024-12-07 03:10:19

[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);
}

更改摘要:

  • 以控制器的工作有意义的方式布局您的逻辑。获取-地图-返回。正是控制器设计的任务(按顺序)。
  • 使用 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 添加异常。使用自定义异常类来处理具有描述性、基于资源的消息的业务错误。如果错误对于用户来说太低级(外键约束等),则显示通用消息

Advised changes to [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);
}

Summary of changes:

  • Layout your logic in such a way the controller's job makes sense. Get - Map - Return. Exactly the tasks (in order) for which a Controller is designed for.
  • Use AutoMapper to do the heavy lifting of ViewModel creation for you.

Advised changes to your [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);
}

Summary of changes:

  • Try/catch. Always need to capture exceptions, whether they are domain exceptions or lower-level (database ones)
  • Check ModelState validity first. As @Cymen says - do it first so you don't forget later
  • Add exceptions to ModelState. Use custom exception classes for business errors with descriptive, resource-based messages. If the error is too low-level for the user (foreign key constraint, etc), show a generic message
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文