2017-01-11 14 views
0

Снова ...MVC Entity Framework Mapper для просмотра модели для обновления таблицы

Я делаю MVC с EF5 App. У меня есть User Entity, что EF связывается с таблицей Users в базе данных ... Похоже на это.

public partial class Users 
{ 
    public long User_id { get; set; } 
    [Required] 
    [StringLength(30, ErrorMessage = "LastName cannot be longer than 30 characters.")] 
    public string LastName { get; set; } 
    [Required] 
    [StringLength(30, ErrorMessage = "Name cannot be longer than 30 characters.")] 
    public string Name { get; set; } 
    public int ProcessState_id { get; set; } 
    public string Sex { get; set; } 

    [Required,Range(1, int.MaxValue, ErrorMessage = "El País es Obligatorio")] 
    public int Country_id { get; set; } 

    [Required] 
    [EmailAddress(ErrorMessage = "Invalid Email Address")] 
    public string Email { get; set; } 
    public System.DateTime CreationDate { get; set; } 
    public Nullable<System.DateTime> UpDateTime { get; set; } 
    [RegularExpression(@"^.{5,}$", ErrorMessage = "Minimum 3 characters required")] 
    [Required] 
    [StringLength(9, MinimumLength = 3, ErrorMessage = "Password cannot be longer than 9 characters.")] 
    public string Password { get; set; } 
    public string Url { get; set; } 
    public byte[] Picture { get; set; } 
    public string CodArea { get; set; } 
    public string PhoneNumber { get; set; } 
    public virtual Countries Countries { get; set; } 
    public virtual ProcessStates ProcessStates { get; set; } 
    public virtual States States { get; set; } 
    [NotMapped] // Does not effect with your database 
    [RegularExpression(@"^.{5,}$", ErrorMessage = "Minimum 3 characters required")] 
    [StringLength(9, MinimumLength = 3, ErrorMessage = "Confirm Password cannot be longer than 9 characters.")] 
    [Compare("Password")] 
    public virtual string ConfirmPassword { get; set; } 
} 

У меня есть класс модели, что я использую его в своей Create View ....

public class UserViewModel 
{ 
    public Users user { get; set; } 
    public IList<SelectListItem> AvailableCountries { get; set; } 
} 

Мой метод создания в контроллере получает UserViewModel экземпляр ...

Моя страница Метод выглядит так.

public async Task<ActionResult> Create(UserViewModel model, System.Web.HttpPostedFileBase image = null) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      model.user.ProcessState_id = Security.WAITING; 
      model.user.Rol_id = Security.ROL_PUBLIC; 
      model.user.CreationDate = DateTime.Now; 
      model.user.IP = Request.UserHostAddress; 
      model.user.Url = UserValidation.EncriptacionURL(model.user.Email); 
      if (image != null) 
      { 
       // product.ImageMimeType = image.ContentType; 
       model.user.Picture= new byte[image.ContentLength]; 
       image.InputStream.Read(model.user.Picture, 0, image.ContentLength); 
      } 
      _db.Users.Add(model.user); 
      _db.SaveChanges(); 
      return RedirectToAction("Create"); 
     } 
     model.AvailableCountries = GetCountries(); 
     return View(model); 
    } 
    catch (RetryLimitExceededException /* dex */) 
    { 
    } 
    return View(model); 
} 

Пока все хорошо.

Для моего редактирования вида мне нужно меньше свойств из класса User, поэтому у меня есть новый класс со свойствами, которые мне нужны. Этот класс называется UserEditView.

public class UserEditView 
{ 
    public long User_id { get; set; } 
    [Required] 
    [StringLength(30, ErrorMessage = "LastName cannot be longer than 30 characters.")] 
    public string LastName { get; set; } 
    [Required] 
    [StringLength(30, ErrorMessage = "Name cannot be longer than 30 characters.")] 
    public string Name { get; set; } 
    [Required, Range(1, int.MaxValue, ErrorMessage = "El País es Obligatorio")] 
    public int Country_id { get; set; } 
    [Required] 
    [EmailAddress(ErrorMessage = "Invalid Email Address")] 
    public string Email { get; set; } 
    public Nullable<System.DateTime> UpDateTime { get; set; } 
    public byte[] Picture { get; set; } 
    public string CodArea { get; set; } 
    public string PhoneNumber { get; set; } 

    public virtual Countries Countries { get; set; } 
} 

Я также создать новую модель для Edit View, называется UserEditViewModel и выглядит следующим образом.

public class UserEditViewModel 
{ 
    public UserEditView user { get; set; } 
    public IList<SelectListItem> AvailableCountries { get; set; } 
} 

На моем методе редактирования я использую Mapper связать User сущность с UserEditView

public ViewResult Edit(int User_id=3) 
{ 
    Users users = _db.Users 
    .FirstOrDefault(p => p.User_id == User_id); 

    var config = new MapperConfiguration(cfg => 
    { 
     cfg.CreateMap<Users, UserEditView>(); 
    }); 

    IMapper mapper = config.CreateMapper(); 
    UserEditView userEditView = mapper.Map<Users, UserEditView>(users); 

    var model = new UserEditViewModel 
    { 
     user = userEditView, 
     AvailableCountries = GetCountries(), 
    }; 

    return View(model); 
} 

Моя проблема возникает, когда я хочу, чтобы обновить таблицу пользователей.

Метод редактирования получает экземпляр UserEditViewModel.

public async Task<ActionResult> Edit(UserEditViewModel model, System.Web.HttpPostedFileBase image = null) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     {} 
    } 
} 

UserEditViewModel имеет экземпляр UserEditView но мне нужен экземпляр Users для того, чтобы Е.Ф. обновления таблицы пользователей.

Мне нужна карта еще раз? Как я могу получить экземпляр пользователя?

добавить следующий класс

public static class AutoMapperBootStrapper 
 
    { 
 
     public static void BootStrap() 
 
     { 
 
      var config = new MapperConfiguration(cfg => 
 
      { 
 
       cfg.CreateMap<Users, UserEditView>(); 
 
       cfg.CreateMap<UserEditView, Users>(); 
 
      }); 
 
      IMapper mapper = config.CreateMapper(); 
 

 
     }

И я добавляю в моей Global.asax

public class MvcApplication : System.Web.HttpApplication 
 
    { 
 
     protected void Application_Start() 
 
     { 
 
      AutoMapperBootStrapper.BootStrap(); 
 
      AreaRegistration.RegisterAllAreas(); 
 
      RouteConfig.RegisterRoutes(RouteTable.Routes); 
 
      BundleConfig.RegisterBundles(BundleTable.Bundles); 
 
     } 
 
    }

затем в контроллер .. . Я делать

public ViewResult Edit(int User_id=3) 
 
     { 
 
      Users users = _db.Users.FirstOrDefault(p => p.User_id == User_id); 
 

 
UserEditView userEditView = Mapper.Map<Users, UserEditView>(users); 
 
}

Но Mapper.Map есть ошибка ... это говорит Mapper не экземпляр.

проблема в том, что я определил несколько карт.Если я определяю только один, он отлично работает ...

ответ

2

Мне еще нужно скопировать карту? Как я могу получить экземпляр пользователей?

Вы можете получить модель пользователя из базы данных, используя идентификатор, а затем сопоставить свойства, которые должны быть обновлены из модели представления:

[HttpPost] 
public ActionResult Edit(UserEditViewModel model, HttpPostedFileBase image = null) 
{ 
    if (!ModelState.IsValid) 
    { 
     // Validation failed => redisplay the Edit form so that the 
     // user can correct the errors 
     return View(model); 
    } 

    var user = _db.Users.FirstOrDefault(p => p.User_id == model.user.User_id); 
    if (user == null) 
    { 
     // no user with the specified id has been found in the database => 
     // there's nothing to update 
     return NotFound(); 
    } 

    // This will map only the properties of the user object that 
    // are part of the view model 
    Mapper.Map<Users, UserEditView>(model.user, user); 

    // at this stage you could manually update some properties that 
    // have not been mapped such as the uploaded image 

    // finally persist the changes to the database 
    _db.SaveChanges(); 

    // redirect to some other action to show the updated users 
    return RedirectToAction("users"); 
} 

Кроме того, код, который вы показали в вашем вопросе :

var config = new MapperConfiguration(cfg => 
{ 
    cfg.CreateMap<Users, UserEditView>(); 
}); 

IMapper mapper = config.CreateMapper(); 

Это абсолютно НЕ то, что вы должны делать в действии контроллера. Сопоставления AutoMapper следует настраивать только один раз для каждого жизненного цикла приложения, в идеале, когда ваше приложение запускается, то есть для веб-приложения, которое должно быть Application_Start в Global.asax. В действии контроллера вы должны использовать только настроенные сопоставления. Я настоятельно рекомендую вам ознакомиться с документацией AutoMapper, чтобы лучше понять, как использовать эту инфраструктуру.

Цитата из documentation:

Где настроить AutoMapper?

Если вы используете статический метод Mapper, конфигурация должна только произойти один раз в AppDomain. Это означает, что наилучшим местом для установки кода конфигурации является запуск приложения, такой как файл Global.asax для приложений ASP.NET. Как правило, класс bootstrapper находится в своем классе, и этот класс начальной загрузки - , вызываемый из метода запуска. Класс bootstrapper должен вызвать Mapper.Initialize для настройки типов карт.

+0

ЕСЛИ Я определяю MapperConfiguration в глобальной Asax, чтобы получить доступ «IMapper картограф» от контроллера, я должен определить его как Public, и вызвать UserEditView userEditView = mapper.Map <Пользователь, UserEditView> (пользователь); от 'Контроллер' ..? – Diego

+0

Вы можете использовать статический метод «Mapper.Map », как показано в моем ответе. Или введите Mapper.Engine в ваш контроллер, если вы хотите иметь лучшую абстракцию над логикой отображения. Тем не менее ваша конфигурация отображения должна произойти только один раз за время жизни AppDomain, то есть в вашем приложении Application_Start. –

+0

Это дает мне ошибку .. она говорит, что она должна быть создана .. – Diego

 Смежные вопросы

  • Нет связанных вопросов^_^