简体   繁体   English

C#类实例保存字符串引用但不包含对象引用

[英]C# Class Instance Holding String Reference But Not Object Reference

Alright, so I have spend LITERALLY five or six hours working on this to no avail. 好吧,所以我花了整整五个或六个小时来解决这个问题。 I'm working in C# with ASP.NET MVC 4 and EF 5.0, I believe. 我相信,我正在使用ASP.NET MVC 4和EF 5.0在C#中工作。 Here's my problem: I have a method in my controller takes a custom class as a parameter (these names have been candy-themed obfuscated :P). 这是我的问题:我的控制器中有一个方法采用自定义类作为参数(这些名称已被糖果主题混淆了:P)。 The ViewError class looks like so: 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);
    }
}

(It's a generic so I can figure out what type the ModelObject is from within the code. It's irrelevant, though; I've already tested it taking a generic 'object' and the same problem happens.) (这是通用的,因此我可以从代码中找出ModelObject的类型。不过这是不相关的;我已经使用通用的“对象”对其进行了测试,并且发生了相同的问题。)

The controller method looks like this. 控制器方法如下所示。 All it does is ask who is eating the candy, and if there's a ViewError, it displays the message. 它所做的只是询问谁在吃糖果,如果有ViewError,它会显示该消息。 (The view has a paragraph that displays the ViewBag.Message). (该视图有一个段落,显示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();
}

On the post: 在帖子上:

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

Pretty standard stuff. 很标准的东西。 Now, in the ChooseCandyToEat method, it brings up a list of candy available to eat of a specific brand. 现在,在ChooseCandyToEat方法中,它会弹出一个特定品牌可食用的糖果列表。 If that brand doesn't have any available candy, I want it to send an error back to the EatCandy method (via ViewError object) telling that eater that they have no candy to eat, and send the model back so that the eater doesn't have to type in their info again, merely select a different brand of candy. 如果该品牌没有可用的糖果,我希望它将错误发送回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);
}

According to my understanding, this should all work. 根据我的理解,这都应该起作用。 Now here's the weird part - I can confirm, through debug messages and the Watch window (using Visual Studio) that the ViewError is created properly and holds a deep clone of the viewModel in its ModelObject (I have to convert it back because the EatCandy method expects an EatCandyViewModel as a parameter). 现在这是一个很奇怪的部分-我可以通过调试消息和“监视”窗口(使用Visual Studio)确认ViewError是否已正确创建并在其ModelObject中保留了ViewModel的深层克隆(我必须将其转换回来,因为EatCandy方法期望将EatCandyViewModel作为参数)。 However, when I step forward and the ViewError is passed to EatCandy, the ModelObject within it is null! 但是,当我前进并将ViewError传递给EatCandy时,其中的ModelObject为null! I originally thought this was because it only passed a reference of viewModel into the object and it was getting garbage collected, which is why I added the Clone() method. 我最初以为这是因为它仅将viewModel的引用传递给对象,并且正在收集垃圾,这就是为什么我添加了Clone()方法的原因。 The string, which is also a reference type, is getting through okay, though. 字符串,它也是一个引用类型,但是通过了。 Why isn't the object? 为什么不是物体? Does anyone know? 有人知道吗?

If you need more info, just ask. 如果您需要更多信息,请询问。 And disregard the ridiculousness of this database - I obfuscated it intentionally, not just to be silly. 并且无视此数据库的荒谬性-我故意对其进行混淆,而不仅仅是愚蠢。

This won't work. 这行不通。 RedirectToAction results in a 302 to the browser which just is not capable of carrying complicated models. RedirectToAction导致浏览器无法访问302,而该浏览器无法承载复杂的模型。

There are some alternatives, you could use the TempData to store the model, do the redirect and retrieve the data. 有一些替代方法,您可以使用TempData来存储模型,进行重定向并检索数据。 You could probably even call the EatCandy action directly instead of redirecting, however the auto matching the view won't work and you'd have to force the "EatCandy" view name at the end of the EatCandy action. 您甚至可以直接调用EatCandy操作而不是重定向,但是自动匹配视图将不起作用,并且您必须在EatCandy操作结束时强制使用“ EatCandy”视图名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM