MVC实体框架映射器到视图模型到更新表



再次。。。

我正在用EF5应用程序做MVC。我有一个用户实体,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; }
}

我有一个模型类,我在创建视图中使用它。。。。

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

我在控制器中的Create方法得到一个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; }
}

我还为编辑视图创建了一个新的模型,名为UserEditViewModel,如下所示。

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

在我的Edit方法中,我使用MapperUser实体与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);
}

当我想更新用户表时,我的问题就出现了。

Edit方法获取UserEditViewModel实例。

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

UserEditViewModel具有UserEditView的实例,但我需要Users的实例以便EF更新用户表。

我需要再次绘制地图吗?如何获取用户实例?

我添加以下类别

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没有被实例化。

问题是因为我定义了多个Mapper。如果我只定义一个,它很好。。。

我需要再次映射吗?如何获取用户实例?

您可以使用id从数据库中获取用户模型,然后从视图模型中映射需要更新的属性:

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

这绝对是NOT您应该在控制器操作中执行的操作。AutoMapper映射在每个应用程序生存期内只应配置一次,理想情况下是在应用程序启动时,即对于Global.asax中的Application_Startweb应用程序。在控制器操作中,您应该只使用已配置的映射。我强烈建议您阅读AutoMapper的文档,以便更好地了解如何使用此框架。

引用documentation:

在哪里配置AutoMapper

如果您使用的是静态Mapper方法,则配置应该仅每个AppDomain发生一次。这意味着放置配置代码处于应用程序启动中,例如Global.asaxASP.NET应用程序的文件。通常,配置引导程序类在它自己的类中,而这个引导程序类是从启动方法调用。引导程序类应该调用映射器。初始化以配置类型映射。

最新更新