1

好吧,所以我花了 5 到 6 个小时来解决这个问题,但无济于事。我相信我正在使用 ASP.NET MVC 4 和 EF 5.0 使用 C#。这是我的问题:我的控制器中有一个方法将自定义类作为参数(这些名称已被糖果主题混淆:P)。ViewError 类如下所示:

public class ViewError<T> where T : class
{
    public T ModelObject { get; set; }
    public string Message { get; set; }

    public ViewError(string message, T modelObject)
    {
        Message = message;
        ModelObject = modelObject;
    }

    public ViewError()
    {
        Message = null;
        ModelObject = default(T);
    }
}

(它是通用的,所以我可以从代码中找出 ModelObject 是什么类型。不过,这无关紧要;我已经用通用的“对象”对其进行了测试,并且发生了同样的问题。)

控制器方法如下所示。它所做的只是询问谁在吃糖果,如果有 ViewError,它会显示消息。(视图有一段显示 ViewBag.Message)。

public ActionResult EatCandy(ViewError<EatCandyViewModel> error)
{
    ViewBag.BrandList = new SelectList(db.Brands, "ID", "Name");
    // If there's a notification, pass it to the view, along with the model
    if(error.Message != null)
    {
        ViewBag.Message = error.Message;
        return View(error.ModelObject);
    }
    return View();
}

在帖子上:

[HttpPost]
public ActionResult EatCandy(EatCandyViewModel viewModel)
{
    if(ModelState.IsValid)
    {
        CandyEater eater = (CandyEater)viewModel;
        db.CandyEaters.Add(eater);
        db.SaveDatabase(); // Custom convenience wrapper for SaveChanges()
        return RedirectToAction("ChooseCandyToEat", eater);
    }
    return View(viewModel);
}

很标准的东西。现在,在 ChooseCandyToEat 方法中,它会显示一个特定品牌的可食用糖果列表。如果该品牌没有任何可用的糖果,我希望它向 EatCandy 方法(通过 ViewError 对象)发送一个错误,告诉食客他们没有糖果可吃,并将模型发回以便食客没有不必再次输入他们的信息,只需选择不同品牌的糖果。

public ActionResult ChooseCandyToEat(CandyEater eater)
{
    // Get the list of candy associated with the brand.
    IEnumerable<Candy> candyList = db.Candies.Where(b => b.Brand == eater.DesiredBrand)
                                             .Where(e => !e.Eaten);
    // If the brand has no candy, return an error message to the view
    if(candyList.Count() == 0)
    {
        EatCandyViewModel viewModel = (EatCandyViewModel)eater;
        ViewError<EatCandyViewModel> viewError = new ViewError<EatCandyViewModel>("Oh noes! That brand has no candy to eat!", viewModel.Clone()); // This is a deep clone, but even if it wasn't, it would still be weird. Keep reading.
        return RedirectToAction("EatCandy", viewError);
    }
    return View(candyList);
}

根据我的理解,这应该都可以。现在这是奇怪的部分 - 我可以通过调试消息和 Watch 窗口(使用 Visual Studio)确认 ViewError 已正确创建并在其 ModelObject 中保存了 viewModel 的深层克隆(我必须将其转换回来,因为 EatCandy 方法需要一个 EatCandyViewModel 作为参数)。但是,当我向前一步并将 ViewError 传递给 EatCandy 时,其中的 ModelObject 为空!我最初认为这是因为它只将 viewModel 的引用传递给对象并且它正在收集垃圾,这就是我添加 Clone() 方法的原因。不过,该字符串也是一个引用类型,它的运行还不错。为什么不是对象?有人知道吗?

如果您需要更多信息,请询问。并且忽略这个数据库的荒谬——我故意混淆它,不仅仅是为了傻。

4

1 回答 1

0

这行不通。RedirectToAction 会导致浏览器出现 302,而浏览器无法承载复杂的模型。

有一些替代方案,您可以使用 TempData 来存储模型、执行重定向和检索数据。您甚至可以直接调用 EatCandy 操作而不是重定向,但是自动匹配视图将不起作用,您必须在 EatCandy 操作结束时强制使用“EatCandy”视图名称。

于 2013-07-26T16:35:40.403 回答