【问题标题】:ViewBag property not getting set when get action is called调用 get 操作时未设置 ViewBag 属性
【发布时间】:2019-04-11 18:47:40
【问题描述】:

在 MVC 项目中,首先是 EF DB,我使用 ViewBag 属性在下拉列表中显示值列表。这是我的 get 方法和 post 方法。-

[ HttpGet]
        public ActionResult Create()
        {

            using (var context = new AdventureWorksEntities())
            {
    ViewBag.Colors = new SelectList(context.Products.Select(a => 
    a.Color).Distinct().ToList());
            }

            return View();

 [HttpPost]
        [ActionName("Create")]
        public ActionResult CreatePost()
        {
            var producttocreate = new Product();
        try
            {
                UpdateModel(producttocreate);
                if (ModelState.IsValid)
                {
                    using (var context = new AdventureWorksEntities())
                    {
                        context.Products.Add(producttocreate);
                        context.SaveChanges();
                    }
                    return RedirectToAction("Index");
                }
                return View(producttocreate);
            }
            catch(Exception e)
            {
                return View(producttocreate);
            }

    }

这里的属性 ViewBag.Colors 是有问题的属性。当我在 Post 上遇到异常时,我想传递模型并再次返回相同的 Create 视图。但是,即使每次调用 Create Get 方法时我都有设置 ViewBag.Colors 的代码,但它没有被设置,并且在渲染 Create View 时出现错误 -

具有键“Color”的 ViewData 项属于“System.String”类型,但必须属于“IEnumerable”类型

我确实在其他一些帖子中发现此异常的原因是 ViewBag.Colors 为 null ,但我不明白为什么。为什么从 Post Action 方法调用 View 时没有设置它?对此有什么解决办法?

【问题讨论】:

  • 那么,您的代码在初始页面加载时工作,但是当您尝试提交表单并返回相同的视图时出现异常?下拉菜单是表单上的必填字段吗?
  • M12 Bennett - 是的,它适用于初始页面加载。当我发布数据时,如果发布成功,我想返回一个索引视图,如果它不成功,我希望它返回相同的视图。正是在这一点上,我希望 ViewBag.Colors 再次在 GET 方法中设置,因为它在代码中,但它设置为 null。
  • M12 Bennett - 关于问题的另一部分,不是它不是必填字段,如在模型类中的属性上没有应用必填属性。
  • 好的,明白了。需要明确的是,如果post不成功,它不会回到HttpGet方法。它将保留在 HttpPost 方法中,这意味着您必须在 HttpPost 方法中再次设置ViewBag.Colors。过去我也遇到过这种情况,我通常在方法开始时就设置它。不过这取决于你。

标签: c# asp.net-mvc viewbag selectlistitem


【解决方案1】:

之前

return View(producttocreate);

这样做

ViewData["Colors"] = new SelectList(_context.Products, "Id", "Color", ColorId);

【讨论】:

  • Faith Alac - 你的意思是,在 Post Action Method 中再次设置 viewdata 或 ViewBag 吗?我不明白为什么我会要求这样做。在 Get Action Method 中我正在设置它,所以当我从 Post Action Method 内部调用该方法时,为什么它仍然为空?
  • 首先你在公共 IActionResult Create() 中选择然后 [HttpPost] 你需要知道选择的值。
  • 我想唯一的办法就是在 Post 方法中再次填充 ViewBag 。虽然做 RedirectToAction() 的 quiqs 答案也是正确的。但是由于我使用了这个建议,我将其标记为答案。
【解决方案2】:

ViewBag.Colors 为 null 的原因是,当 POST 中出现错误时,您不会重定向到 (GET) Create 操作。相反,您将模型发送回视图,绕过 (GET) Create 操作,因此不会填充 ViewBag。如果您使用RedirectToAction("Create"); 而不是View(producttocreate),则会再次填充 ViewBag.Colors。

【讨论】:

  • quiqs - 如果是这样,我会尝试 RedirectToAction("Create"}。但是当我编写 View(model) 时会调用哪个方法?
  • 我试过 RedirectToAction("Create") ,它不是我想要的。它正在清除所有字段,另外,我有一个 CustomValidation,那个消息没有来。我希望我输入的字段是完整的。
  • View() 是方法。这个方法的作用是,如果没有传递参数,它会寻找一个与封闭动作同名的视图来显示你的对象。如果提供了视图的名称,它会查找具有该名称的视图。如果您想保留 ModelState,那么 @FaithAlac 已经得到您的答案。在 ModelState.IsValid 失败后和返回视图之前在您的 POST 中填充 ViewBag。
  • '它寻找与显示对象的封闭操作同名的视图' - 是的,我确实想要,因为我想留在创建视图中。关于在 POST 之前填充 ViewBag ,我的犹豫是我已经在 GET 方法中填充它,所以到处都这样做看起来很奇怪。但是,如果这是唯一的解决方案,那么我会问当 POST 失败时该怎么办。我看到的每个教程都使用这种方式,为什么他们不面临这个问题?换句话说 - 创建 ViewModel 是保存这些值的唯一选择吗?
  • ViewBag 的生命周期从控制器到视图、视图到控制器或控制器到控制器。这是单程旅行。在那之后,它就不复存在了。这就是为什么您需要在 POST 中再次填充它,但前提是您需要相同的视图,需要保留 ModelState 中的值,并向用户显示错误,所有这些都是您想要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
相关资源
最近更新 更多