【问题标题】:How to auto-populate specific fields when using @Html.EditorForModel() to build a form?使用@Html.EditorForModel() 构建表单时如何自动填充特定字段?
【发布时间】:2012-02-14 20:36:11
【问题描述】:

我让用户使用 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()

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

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

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

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

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

对我的整体情况有任何其他帮助都会很好,我非常愿意接受任何可以简化我的流程的建议(感觉就像我让自己变得比我需要的更难,而且我正处于协作的地步感觉就像呼吸新鲜空气)。

【问题讨论】:

    标签: asp.net-mvc razor auto-populate editorformodel


    【解决方案1】:

    我只能听懂你问题的前半部分。这是您展示了一些代码并且我可以帮助您的一个。下半场对我来说是一片迷雾。

    因此,当您要设计视图时,请考虑该视图需要显示/编辑的字段。并为其设计一个视图模型:

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

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

    【讨论】:

    • 感谢您的快速回复。我在这个时间睡觉,所以我必须在早上尝试一下,但看起来你给了我一个更全面的 ViewModel 视图。至于我原来的帖子缺乏理解,我分两次写(一次在我接到一个冗长的电话之后),这可能是在我的小树林里,我可能会修改。当我有更多时间专注于您为我提供的内容时,我会更新。
    • 我能够正确地自动填充我的字段。谢谢你。但是,我无法让 AutoMapper 在我的两个模型之间进行映射(引发了“异常”),当我回到项目的这一部分来改进事情时,我可能会更深入地了解它。再次感谢您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多