我让用户使用IDE附带的AspNetSqlProfileProvider在我的网站上的某处填写他们的个人资料信息。
我允许我的用户随时编辑他们的个人资料,只需转到编辑个人资料页面,其中编辑其个人资料的表单会自动填充。我目前通过使用ViewBag将用户配置文件的每个部分从我的控制器发送到视图(例如地址和城市)来执行此操作:
控制器获取:
ViewBag.address = CustomProfile.GetUserProfile(User.Identity.Name).Address;
ViewBag.city = CustomProfile.GetUserProfile(User.Identity.Name).City;
查看:
<div class="editor-field">
@Html.TextBox("Address", (string)ViewBag.address)
</div>
<div class="editor-field">
@Html.TextBox("City", (string)ViewBag.city)
</div>
控制器帖子:
public ActionResult ChangeProfile( FormCollection favorites )
{
CustomProfile profile = CustomProfile.GetUserProfile();
profile.Address = favorites["Address"];
profile.City = favorites["City"];
profile.Save();
return RedirectToAction("Profile");
}
以上工作对于编辑配置文件很好,从我的用户的角度看它非常流畅(尽管从在线阅读问题/答案看来我应该使用ViewModel,不确定如何进行转换 - 已经失败) 。
当我的用户从网站上“结账”时(他们一直在购物),他们会看到一个屏幕,允许他们输入允许他们购买的最终信息。我们称之为“订单页面”。这些详细信息包括姓名,地址,信用卡信息等。其中一些信息与网站个人资料页面中的信息相同。
我希望能够自动填充此订单页面中的一些详细信息(名称,地址),同时将某些字段留空(信用卡 - 因此用户必须在每次访问时填写这些详细信息订购页面。)
“订单”页面的工作方式与MVC Store Tutorial describes相同。显示订单页面时,它使用以下方式显示表单:
@Html.EditorForModel()
哪个好,允许您编辑订单模型中指定的详细信息,并允许数据验证内容(名称是必需的,地址是必需的,信用卡必须是数字,电子邮件格式正确等),但我无法弄清楚如何使用我用户的个人资料中的详细信息填充此订单页面中的特定字段。
我尝试构建一个仅使用我的个人资料中包含的信息的新ViewModel,但我没有清楚地掌握所需内容,因为我没有得到我想要的最终结果。
我考虑过只使用订单模型作为我的个人资料信息,但这还不够,因为我希望两者都有不同的信息。
我考虑过将个人资料信息用作订单模式,但我希望我的用户能够灵活地将个人资料信息与他们用来实际下订单的信息分开存储。
我认为我需要专门解决我的问题是如何在使用“@ Html.EditorForModel()”时自动填充特定字段?
对我的整体情况的任何其他帮助都会很棒,我对任何可以简化我的流程的建议都持开放态度(感觉我自己比我需要的更难,而且我正处于协作的地步感觉像是呼吸新鲜空气。)
答案 0 :(得分:3)
我只能关注你问题的前半部分。这是你展示了一些代码和我可以帮助你的代码。下半场对我来说是完全的迷雾。
因此,当您想要设计视图时,请考虑此视图需要显示/编辑的字段。并为它设计一个视图模型:
public class ChangeProfileViewModel
{
[Required]
public string Address { get; set; }
[Required]
public string City { get; set; }
}
然后让您的GET控制器操作应该呈现此视图填充视图模型:
public ActionResult ChangeProfile()
{
CustomProfile profile = CustomProfile.GetUserProfile(User.Identity.Name);
ChangeProfileViewModel model = new ChangeProfileViewModel
{
Address = profile.Address,
City = profile.City
};
return View(model);
}
然后设计相应的视图,该视图将强烈键入此视图模型:
@model ChangeProfileViewModel
@using (Html.BeginForm())
{
@Html.EditorForModel()
<button type="submit">OK</button>
}
最后你有一个POST控制器动作来处理这个表单的提交:
[HttpPost]
public ActionResult ChangeProfile(ChangeProfileViewModel model)
{
if (!Model.IsValid)
{
// there were validation errors => redisplay the view
return View(model);
}
// validation succeeded => process the results
CustomProfile profile = CustomProfile.GetUserProfile();
profile.Address = model.Address;
profile.City = model.City;
profile.Save();
return RedirectToAction("Profile");
}
现在我们在这里看到的是,在我们的GET和POST操作中,我们在域模型(CustomProfile
)和视图模型(ChangeProfileViewModel
)之间都有重复的映射代码。要解决此问题,我建议您使用AutoMapper。它可以简化您的GET操作:
public ActionResult ChangeProfile()
{
CustomProfile profile = CustomProfile.GetUserProfile(User.Identity.Name);
ChangeProfileViewModel model = Mapper.Map<CustomProfile, ChangeProfileViewModel>(profile);
return View(model);
}
或使用自定义操作过滤器来均匀:
[AutoMap(typeof(CustomProfile), typeof(ChangeProfileViewModel))]
public ActionResult ChangeProfile()
{
CustomProfile profile = CustomProfile.GetUserProfile(User.Identity.Name);
return View(profile);
}
和你的POST动作:
[HttpPost]
public ActionResult ChangeProfile(ChangeProfileViewModel model)
{
if (!Model.IsValid)
{
// there were validation errors => redisplay the view
return View(model);
}
// validation succeeded => process the results
CustomProfile profile = CustomProfile.GetUserProfile();
Mapper.Map<ChangeProfileViewModel, CustomProfile>(model, profile);
profile.Save();
return RedirectToAction("Profile");
}
了解视图模型的重要之处在于,您应始终对每个视图使用它们,并以这种方式设计它们,使它们仅包含此视图需要处理的特定信息。留待映射层处理域实体与视图模型之间的转换。