【问题标题】:Problem adding string value to ViewBag from an MVC Action using TempData使用 TempData 从 MVC 操作将字符串值添加到 ViewBag 时出现问题
【发布时间】:2019-04-06 19:54:12
【问题描述】:

我继承了一个 MVC 项目,如果调用的操作正确完成,页面应该显示一条指示成功的消息。我遇到了一些麻烦,因为我对 MVC 和 Web 开发很陌生。

在 cshtml 文件中,我们在 MainWindow.cshtml 中有以下内容,它仅在 ViewBag 中存在名为“SavedMessage”的字符串且不为 null 或空的情况下以条件渲染表格:

@{ string actionResult = ViewBag.SavedMessage; }
@if (!string.IsNullOrEmpty(actionResult))
{
    <tr>
         <td>
             @actionResult
         </td>
    </tr>
}

在 Action 方法中,我尝试使用 TempData 对象将字符串值传输到生成视图的 Action:

public partial class ApproveController : Controller
{
    const string IDX_ACTIONRESULT = @"ActionResult";

    public ActionResult MyAction(FormCollection collection)
     {
         try
         {
             string result_success = @"Action completed successfully";
             //Do stuff
             TempData[IDX_ACTIONRESULT] = result_success;
             return RedirectToAction("MainWindow");
         }
         catch (Exception e)
         {
             Logger.reportException(e);
             throw e;
         }
     }
 }

在生成页面的Action中,我们将存储在TempData中的值加载到一个变量中,然后测试该变量是否包含任何内容(注意:这个相同的Action用于渲染页面是否用户刚刚登陆这里, 或者他们点击了按钮来执行 MyAction)。如果变量不为空,我们将它包含的任何内容加载到 ViewBag 中。

创建视图操作:

public partial class ApproveController : Controller
{
    public ActionResult MainWindow()
    {
        //Do Stuff
        var actionResult = TempData[IDX_ACTIONRESULT];
        if (actionResult != null)
        {
            Log.info("Action Result Message: " + actionResult);
            ViewBag.SavedMessage = actionResult;  
        }
        else
            Log.info("Action Result Message is NULL");


        return View();
    }
}

可能的线索: 当 MainWindow() 方法通过 MyAction() 的 Redirect 以外的方式调用时,我的日志显示 actionResult 为空,但是,当它通过 MyAction 的 Redirection 调用时(),actionResult 是一个空字符串。这让我相信 MyAction() 正在用 something 填充 TempData,但我不明白为什么它不包含我分配的字符串。有人看到这里有吸烟枪吗?

【问题讨论】:

  • 该控制器上是否有另一个名为 MyView 的方法接收参数?
  • 除了您在此处发布的方法之外,控制器中是否还有另一种称为CreateViewAction 的方法?此外,您应该使用string.IsNullOrWhiteSpace 而不是savedMessage != null &amp;&amp; savedMessage.Length &gt; 0
  • 是的,有一个方法叫做 CreateViewAction。实际上,我刚刚更新了问题以反映这一点。
  • 您是否阅读了我对重定向后实际用于渲染的视图的评论?
  • 好的,谢谢。我知道我正在查看正确的视图,因为我已经能够对其进行并确认其他小的更改。我在 CreateViewAction 方法中添加了一些日志记录,可以确认 SavedMessage 参数肯定为空,因此 cshtml 条件按预期工作。

标签: c# asp.net-mvc


【解决方案1】:
return RedirectToAction("CreateViewAction", new { @SavedMessage = savedMessage });

以上代码会将用户引导至CreateViewAction 页面,其中查询字符串中的消息。问题是用户可以在 URL 中看到消息,这有点难看。

在 ASP.NET MVC 页面之间传递数据的最简单方法是使用 TempData

public ActionResult MyAction(FormCollection collection)
{
    TempData["SuccessMessage"] = @"Action completed successfully";
    //Do stuff
    return RedirectToAction("CreateViewAction");
}

public ActionResult CreateViewAction()
{
    ViewBag.SavedMessage = TempData["SuccessMessage"] ?? "Successfully!!!";
    return View();
}

【讨论】:

  • 谢谢;所以我可以使用“??”运算符来处理 TempData["SavedMessage"] 不存在的情况,对吗?在您的示例中,“成功!!!”如果 TempData["SavedMessage"] 为空,是默认值吗?
  • 是的。如果为 null,则运算符采用默认值。
【解决方案2】:

这里使用的RedirectToAction 重载是:

protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues);

之前的开发者使用anonymous type 来创建路由值:

new { @SavedMessage = savedMessage }

代码正在重定向到一个名为MyViewAction,它接受一个名为SavedMessage 的参数。

您的控制器中必须有另一个方法看起来或多或少像这样:

public ActionResult MyView(string SavedMessage)
{
    //Maybe some code here
    ViewBag.SavedMessage = SavedMessage;
    return View();
}

该方法实际上会设置消息并执行视图。

更新:

阅读提供的附加信息后,您应该改用string.IsNullOrWhiteSpace

@if (!string.IsNullOrWhiteSpace(savedMessage))

其他一切都应该按照布局正常工作,这意味着您有一些其他代码在其他地方重定向在这部分执行之前

ViewBag.SavedMessage = SavedMessage;
return View();

或者您正在检查的视图不是用于呈现结果的视图。请注意,由于您正在重定向执行,因此使用的新视图文件将是 CreateViewAction.cshtml

【讨论】:

  • 谢谢!您的解决方案对我来说非常有意义,我实现了它,但是,cshtml 文件中的条件仍然解析为 false。我根据我的尝试更新了问题。我混淆了我的方法名称,所以我将“MyView”重命名为“CreateViewAction”,因为我现在意识到我指的是一个动作而不是一个视图
  • @MikeBruno:我更新了我的答案。请看一看。
  • 谢谢,我看到了。我认为您的意思是 string.IsNullOrEmpty。我确实尝试过,但得到了相同的结果。令人沮丧... @if (!string.IsNullOrEmpty(savedMessage))
  • @MikeBruno:不。我的意思是IsNullOrWhiteSpace。这是另一种方法。如果您使用的是旧版本,则可能无法使用它。
  • 如果您只是附加一个调试器并逐步执行调用,这应该很容易弄清楚。还要在视图上设置断点并验证 ViewBag 属性的值。注意拼写错误。
【解决方案3】:

RedirectToAction 方法正在调用控制器中的另一个方法并传入一个对象,该对象是该方法的路由值。

新的 {...} 创建一个匿名对象,因此不需要定义集合类型。

我的猜测是,该控制器中有另一种方法可以重新创建视图,并且应该将收到的参数分配给 ViewBag

【讨论】:

    猜你喜欢
    • 2019-04-12
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多