【问题标题】:Invalid modelstate: how to return to view when I have dropdownlists?无效的模型状态:当我有下拉列表时如何返回视图?
【发布时间】:2014-11-03 17:27:51
【问题描述】:

我有 40 多个领域的大视野。其中一些字段是下拉列表,我用选择列表项列表填充。

我正在使用我的视图模型上的注释,以使其中一些成为必需的。

现在我想做ModelState.IsValid检查,如果有错误返回原来的视图。

问题是,如果我只是创建一个return View(model),我所有的下拉列表都会使网站崩溃,因为需要再次填充它们才能加载页面。

所以我的问题是:当模型状态无效时我如何处理返回。

我的控制器:

    public ActionResult CreateSelling(SellingAdViewModel model)
    {
        if (ModelState.IsValid)
        {
            SellingAdvert sellingAdvert = setSellingAd(model);

            var stored_advert = sellingAdvertService.Create(sellingAdvert);



            if (User != null && User.Identity.IsAuthenticated)
            {
                if (model.AcceptPartner)
                {
                    notifyPartner(stored_advert);
                }

                return RedirectToAction("Upgrade", "Ads", new { AdvertID = stored_advert.Id });
            }
            else
            {
                return RedirectToAction("ActivateAnonymous", "Ads", new { AdvertID = stored_advert.Id, anonymousId = model.UserId, AdvertType = "selling" });
            }
        }

        return View(model);
    }

我的视图模型(我有一个 SellingAdViewModel 派生自这个模型并添加了更多属性):

public class BasicAdViewModel
{
    public int SectorId { get; set; }
    public Guid UserId { get; set; }
    public bool IsAnonymousUser { get; set; }
    public int AdvertId { get; set; }

    [DisplayName("Titel:")]
    [Required(ErrorMessage = "Titel skal udfyldes")]

    public string Headline { get; set; }

    [DisplayName("Beskrivelse:")]
    [StringLength(50, ErrorMessage = "Beskrivelsen minimum fylde 50 karakterer")]
    public string Description { get; set; }

    [DisplayName("Søgeord:")]
    public string SearchWords { get; set; }


    [DisplayName("Undertitel:")]
    public string Subtitle { get; set; }

    [DisplayName("Type af drift")]
    public List<SelectListItem> OperationTypes { get; set; }

    [Required]
    public int SelectedOperationTypeId { get; set; }


    [Required]
    public int SelectedSectorId { get; set; }
    public IEnumerable<GroupedSelectListItem> Sectors { get; set; }
}

首先设置我的下拉列表:

我的模型有 List&lt;SelectListItem&gt; 属性,我通过几个辅助方法来填充它们:

  SellingAdViewModel model = new SellingAdViewModel()
            {
                BusinessEntityTypes = ModelListHelpers.GetBusinessEntityTypes(),
                FoundedYears = ModelListHelpers.GetFoundedYears(null),
                ReasonForSale = ModelListHelpers.GetReasonForSale(),
                RevenuePrediction = ModelListHelpers.GetRevenuePrediction(),
                RevenueStatus = ModelListHelpers.GetRevenueStatus(),
                OperationTypes = ModelListHelpers.GetOperationTypes(),
                Region = ModelListHelpers.GetRegions(),
                Turnover = ModelListHelpers.Turnovers(),
                OperatingIn = ModelListHelpers.OperatingIn(),
                AmountOfEmployees = ModelListHelpers.GetAmountOfEmployees()
            };

【问题讨论】:

  • 我通常将下拉列表放在 TempData 中,然后如果我的模型状态无效,我会从 tempdata 中获取它们并创建另一个 model.dropdown = (type)TempData["dropdown"];
  • 第一次如何填充下拉列表?在适当的地方使用ViewBag 做同样的事情。 (即,在行动中可能)。我这样做。 (在我看来,viewbag 项目作为 selectlistitems)
  • 我刚刚添加了我如何填充我的视图模型 :) 我在 HttpGet 调用中执行此操作,在那里我设置了 SelectListItems
  • 在你的控制器中创建一个私有方法(比如)private void ConfigureViewModel(SellingAdViewModel model) 填充所有选择,并在返回视图之前在 GET 方法和 POST 方法中调用它

标签: asp.net asp.net-mvc asp.net-mvc-4


【解决方案1】:

我建议你这个解决方案在你的 GET 操作期间将你的模型放在TempData 如果模型状态无效,你可以像这样进行分配

public ActionResult CreateSelling(SellingAdViewModel model)
{
    if (ModelState.IsValid)
    {
        SellingAdvert sellingAdvert = setSellingAd(model);

        var stored_advert = sellingAdvertService.Create(sellingAdvert);



        if (User != null && User.Identity.IsAuthenticated)
        {
            if (model.AcceptPartner)
            {
                notifyPartner(stored_advert);
            }

            return RedirectToAction("Upgrade", "Ads", new { AdvertID = stored_advert.Id });
        }
        else
        {
            return RedirectToAction("ActivateAnonymous", "Ads", new { AdvertID = stored_advert.Id, anonymousId = model.UserId, AdvertType = "selling" });
        }
    }

    model.YourList = TempData.Peek("YourList");
    return View(model);
}

【讨论】:

  • 这不是一个好的解决方案。如果用户刷新页面,则TempData 将为 null 并引发异常。至于建议的链接,它与此无关(除非 OP 想要为每个 SelectList 的每个 SelectListItem 属性呈现隐藏输入,这将是愚蠢的)
  • 不是这样,如果用户刷新页面,GET 操作将重新分配 TempData...
  • 不,这是不正确的。初始 GET 将值添加到 TempData。提交表单时,会从TempData 正确加载值并返回视图。如果用户现在刷新表单,它会转到 POST 方法(而不是 GET 方法),并且由于 TempData 仅在一个请求中存活,该值现在为 null 并引发异常。我建议你试一试。
  • 最终他可以尝试 TempData.Keep() 值
  • 是的,这是一种选择。 .Peek() 可能就足够了。 Peek vs Keep。我建议你编辑答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-07
  • 2015-10-27
  • 2018-11-04
  • 1970-01-01
  • 2012-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多