有没有办法清理这个控制器代码?

时间:2011-08-21 01:05:52

标签: asp.net-mvc-3 model controller

我在MVC3上看到的大多数代码在控制器中只有很少的代码,但我似乎无法弄清楚如何使这些代码更加简化。

也许如果你看看它,你可以建议改进。如果您需要查看我的UserModel类,请告诉我。

以下是帐户控制器的代码。

namespace WebUI.Controllers
{
    public class AccountController : Controller
    {
        public ActionResult Register()
        {
            UserModel model = new UserModel();         

            EFCityRepository cityRepo = new EFCityRepository();
            model.Cities = new List<SelectListItem>();
            foreach (var city in cityRepo.FindAllCities()) {
                model.Cities.Add(new SelectListItem { Text = city.Name, Value = city.CityId.ToString(), Selected = true });
            }

            EFGenderRepository genderRepo = new EFGenderRepository();
            model.Genders = new List<SelectListItem>();
            foreach (var gender in genderRepo.FindAllGenders()) {
                model.Genders.Add(new SelectListItem { Text = gender.Name, Value = gender.GenderId.ToString(), Selected = true });
            }

            return View(model);
        }

        [HttpPost]
        public ActionResult Register(UserModel model) 
        {
            EFCityRepository cityRepo = new EFCityRepository();
            model.Cities = new List<SelectListItem>();
            foreach (var city in cityRepo.FindAllCities())
            {
                model.Cities.Add(new SelectListItem { Text = city.Name, Value = city.CityId.ToString(), Selected = true });
            }

            EFGenderRepository genderRepo = new EFGenderRepository();
            model.Genders = new List<SelectListItem>();
            foreach (var gender in genderRepo.FindAllGenders())
            {
                model.Genders.Add(new SelectListItem { Text = gender.Name, Value = gender.GenderId.ToString(), Selected = true });
            }

            if (ModelState.IsValid)
            {
                Domain.User user = new Domain.User();
                user.UserRoleId = 1;
                user.Nickname = model.Nickname;
                user.Name = model.Name;
                user.Lastname = model.Lastname;
                user.GenderId = model.GenderId;
                user.Address = model.Address;
                user.Email = model.Email;
                user.Telephone = model.Telephone;
                user.MobilePhone = model.MobilePhone;
                user.Carnet = model.Carnet;
                user.DateOfBirth = model.DateOfBirth;
                user.DateOfRegistry = DateTime.Now;
                user.LastDateLogin = DateTime.Now;
                user.IsActive = false;
                user.LanceCreditBalance = 5;
                user.LancesSpent = 0;
                user.Login = model.Login;
                user.Password = model.Password;
                user.EmailVerificationCode = "TempTokenString";
                user.CityId = model.CityId;

                EFUserRepository repo = new EFUserRepository();
                var result = repo.CreateUser(user);

                if (result == UserCreationResults.Ok)
                {
                    FormsAuthentication.SetAuthCookie(model.Nickname, false /* createPersistentCookie */);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    switch (result)
                    {
                        case UserCreationResults.UsernameExists:
                            ModelState.AddModelError("", "El nombre de usuario ya esta siendo utilizado.");
                            break;
                        case UserCreationResults.EmailAlreadyExists:
                            ModelState.AddModelError("", "Ese correo ya esta en uso.");
                            break;
                        case UserCreationResults.NicknameAlreadyExists:
                            ModelState.AddModelError("", "El nickname ya esta siendo utilizado.");
                            break;
                        case UserCreationResults.UnknownError:
                            ModelState.AddModelError("", "Algo durante el registro. Por favor intente de nuevo.");
                            break;
                        default:
                            break;
                    }
                }

            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
    }
}

我正在使用Entity Framework作为我的ORM,它会自动为我生成一个User类。但是,我创建了一个User * Model *类,因此我可以为要使用的视图添加数据注释。也许这是错误的想法?

2 个答案:

答案 0 :(得分:2)

我有很多建议。首先,阅读有关依赖性注入和控制反转(DI和IoC)的信息。他们将使所有样板对象实例化成为过去。

接下来,将每个列表构建器转换为Linq表达式。更简洁,更快可能更快。

然后,在你的帖子处理程序中,再次执行相同的操作。此外,了解AutoMapper,它会自动将您的视图映射到域类,让您的生活更轻松。

如果你做了这些事情,你的代码将减少2倍,甚至可能减少3倍。

编辑:

示例linq查询,因为我真的不知道对象的定义......看起来像这样:

model.Cities = cityRepo.FindAllCities().Select(city => new SelectListItem() { 
         Text = city.Name, Value = city.CityId.ToString()}).ToList();

注意你不必新建一个新的List,因为它是由ToList()方法返回的。它还使用投影将项目选择为新的SelectListItem。

基本上,您可以使用Dependancy Injection,Linq和AutoMapper编写这样的方法(它看起来更长,因为我必须多次断行以适应小视图的SO):

namespace WebUI.Controllers
{
    public class AccountController : Controller
    {
        private IGenderRepository _genderRepo;
        private ICityrRepository _cityRepo;
        private IUserRepository _userRepo;

        public AccountController(IGenderRepository gr, ICityRepository cr, 
               IUserRepository ur)
        {
            _genderRepo = gr;
            _cityRepo = cr;
            _userRepo = ur;
        }

        public ActionResult Register()
        {
            UserModel model = new UserModel();         

            // Selected property is ignored by MVC on SelectListItems
            model.Cities = _cityRepo.FindAllCities().Select(city => 
                    new SelectListItem() { Text = city.Name, 
                         Value = city.CityId.ToString()}).ToList();

            model.Genders = _genderRepo.FindAllGenders().Select(gender => 
                    new SelectListItem() { Text = gender.Name, 
                         Value = gender.GenderId.ToString()}).ToList();

            return View(model);
        }

        [HttpPost]
        public ActionResult Register(UserModel model) 
        {
            model.Cities = _cityRepo.FindAllCities().Select(city => 
                    new SelectListItem() { Text = city.Name, 
                         Value = city.CityId.ToString()}).ToList();

            model.Genders = _genderRepo.FindAllGenders().Select(gender => 
                    new SelectListItem() { Text = gender.Name, 
                         Value = gender.GenderId.ToString()}).ToList();

            if (ModelState.IsValid)
            {
                Domain.User user = Mapper.Map<Domain.User, Model>(model)

                var result = _userRepo.CreateUser(user);
                if (result == UserCreationResults.Ok) {
                    FormsAuthentication.SetAuthCookie(model.Nickname, false);
                    return RedirectToAction("Index", "Home");
                } else {
                    ModelState.AddModelError("", GetErrorString(result));
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
    }
}

答案 1 :(得分:1)

你的想法很好。因为将实体类作为MVC层中的视图模型并不是一个好习惯,因为它会在表示和持久性逻辑之间建立紧密耦合。

要清理yuor代码,您可以使用AutoMapper(http://automapper.codeplex.com/)将实体类映射到查看模型,而无需编写太多代码。 http://jasona.wordpress.com/2010/02/05/getting-started-with-automapper/这是一篇很好的文章。