1

我让用户使用 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,不完全确定如何进行转换 - 一直失败)。

当我的用户从网站“结账”(他们一直在购物)时,他们会看到一个屏幕,允许他们输入最终信息,以便他们进行购买。我们称之为“订单页面”。这些详细信息包括姓名、地址、信用卡信息等。其中一些信息与网站个人资料页面中的信息相同。

我希望能够自动填充此订单页面中的一些详细信息(姓名、地址),同时将某些字段留空(信用卡 - 因此用户每次访问订单页面时都必须填写这些详细信息) .

Order 页面的工作方式如MVC Store Tutorial 所述。显示订单页面时,它使用以下方式显示表单:

@Html.EditorForModel()

这很棒,允许您编辑 Order 模型中指定的详细信息,并允许进行数据验证(姓名是必需的,地址是必需的,信用卡必须是数字,电子邮件格式正确等),但我不能弄清楚如何使用我的用户个人资料中的详细信息填充此订单页面中的特定字段。

我尝试构建一个仅使用我的个人资料中包含的信息的新 ViewModel,但我并不清楚需要什么,因为我没有得到我想要的最终结果。

我曾考虑仅使用订单模型作为我的个人资料信息,但这还不够,因为我希望两者都提供不同的信息。

我曾考虑将个人资料信息用作订单模型,但我希望我的用户能够灵活地将个人资料信息与他们用于实际下订单的任何信息分开存储。

我认为解决我的问题需要特别了解的是如何在使用 "@Html.EditorForModel()" 时自动填充特定字段?

对我的整体情况有任何其他帮助都会很好,我对任何可以简化我的流程的建议都持开放态度(感觉就像我让自己变得比我需要的更难,而且我正处于协作的地步一口清新的空气)。

4

1 回答 1

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

了解视图模型的重要一点是,您应该始终将它们用于每个视图,并以这样的方式设计它们,以便它们只包含该视图需要处理的特定信息。让映射层处理域实体和视图模型之间的转换。

于 2012-02-14T21:39:40.517 回答