【问题标题】:Flash equivalent in ASP.NET MVC 3ASP.NET MVC 3 中的 Flash 等效项
【发布时间】:2011-04-07 12:43:58
【问题描述】:

ruby on rails 中有一个叫做'flash'的功能,你可以在'flash'中放入消息,重定向,消息在下一个动作中可用。

flash使用示例:

有一个控制器动作 Account.ChangePassword。如果密码更改成功,ChangePassword 将在 flash 中填充一条消息“密码更改成功”,然后重定向到 Account.Profile。在 Account.Profile 中,消息可用,因此可以显示在个人资料页面中。

在 ASP.NET MVC 3 中有类似的东西吗?

我知道我可以使用 tempdata 自己构建这个功能,但是 MVC 3 有内置的东西吗?

【问题讨论】:

  • 临时数据对上一个结果的 2 个下一个结果有效,并且永远不能再次使用。
  • Endy,你引用的帖子有一个非常好的实现,我在下面添加了一个更详细的版本:)
  • .net core 的好包github.com/lurumad/core-flash

标签: asp.net-mvc


【解决方案1】:

恩迪,

我从 tekpub 系列中“借用”了这个:

namespace System.Web.Mvc {
    public static class FlashHelpers {

        public static void FlashInfo(this Controller controller,string message) {
            controller.TempData["info"] = message;
        }
        public static void FlashWarning(this Controller controller, string message) {
            controller.TempData["warning"] = message;
        }
        public static void FlashError(this Controller controller, string message) {
            controller.TempData["error"] = message;
        }

        public static string Flash(this HtmlHelper helper) {

            var message = "";
            var className = "";
            if (helper.ViewContext.TempData["info"] != null) {
                message =helper.ViewContext.TempData["info"].ToString();
                className = "info";
            } else if (helper.ViewContext.TempData["warning"] != null) {
                message = helper.ViewContext.TempData["warning"].ToString();
                className = "warning";
            } else if (helper.ViewContext.TempData["error"] != null) {
                message = helper.ViewContext.TempData["error"].ToString();
                className = "error";
            }
            var sb = new StringBuilder();
            if (!String.IsNullOrEmpty(message)) {
                sb.AppendLine("<script>");
                sb.AppendLine("$(document).ready(function() {");
                //sb.AppendFormat("$('#flash').html('{0}');", message);
                sb.AppendFormat("$('#flash').html('{0}');", HttpUtility.HtmlEncode(message));
                sb.AppendFormat("$('#flash').toggleClass('{0}');", className);
                sb.AppendLine("$('#flash').slideDown('slow');");
                sb.AppendLine("$('#flash').click(function(){$('#flash').toggle('highlight')});");
                sb.AppendLine("});");
                sb.AppendLine("</script>");
            }
            return sb.ToString();
        }

    }
}

典型用法(在控制器内部):

public ActionResult Delete(int id, FormCollection collection)
{
    var item = _session.Single<UserActions>(x=>x.ID == id);
    try
    {
        _session.Delete<UserActions>(item);
        _session.CommitChanges();
        this.FlashInfo("UserAction deleted ...");
        return RedirectToAction("Index");
    }
    catch
    {
        this.FlashError("There was an error deleting this record");
        return View("Edit",item);
    }
}

css 也很简单:

.info
{
    background-color: #CCFFCC;
    border-top: 1px solid #FFCC66;
    border-bottom: 4px solid #FFCC66;
    padding: 6px;
    font-family: helvetica;
    font-size: 1.1em;
    text-align: center;
    border-top-color: #006600;
    border-bottom-color: #006600;
    font-weight: bold;
    color: #339933;
    cursor:pointer;
}
.warning
{
    background-color: #FFFF99;
    border-top: 1px solid #FFCC66;
    border-bottom: 4px solid #FFCC66;
    padding: 6px;
    font-family: helvetica;
    font-size: 0.9em;
    text-align: center;
    border-top-color: #CC9900;
    border-bottom-color: #CC9900;
    font-weight: bold;
    color: #663300;
    cursor:pointer;
}
.error
{
    background-color: #FFCC99;
    border-top: 1px solid #FFCC66;
    border-bottom: 4px solid #FFCC66;
    padding: 4px;
    font-family: helvetica;
    font-size: 1.1em;
    text-align: center;
    border-top-color: #800000;
    border-bottom-color: #800000;
    font-weight: bold;
    color: #990000;
    cursor:pointer;
}

在您的 site.master 中

<%=Html.Flash() %>
<body>
    <div id="flash" style="display: none">
    </div>
.... etc
</body>

享受...

【讨论】:

  • 是的,对此感到羞耻。它有点工作正常,但如果能超出这个限制就好了。如果您愿意,可以做一些功课:)
  • @jimtollan 你指的是什么 tekpuk 视频?
  • guanome - 我得回头看看它是哪一个,上面没有书签:(。如果我找到它,我会和参考一起回来
  • 感谢此代码。对任何使用它的人来说只是一个小评论 - 如果您为一个请求设置了多个消息,则需要多个请求来刷新队列,因此您可能希望首先处理错误级别的项目。
【解决方案2】:

不,TempData 解决方案正是您要找的。​​p>

【讨论】:

  • 需要注意的是,默认情况下 TempData 存储在 Session State 中,如果您在农场环境中并且没有使用进程外会话状态,则无法保证用户会看到消息。
【解决方案3】:

我想升级 Jim 的答案以使用 MVC 3 的新辅助函数。

帮助函数使编写主要返回 Html/javascript 的函数变得容易,因此您不必使用字符串构建器或字符串连接。它会产生更简洁的代码。

FlashHelpers.cs:

namespace System.Web.Mvc {

    public static class FlashHelpers {

        public static void FlashInfo(this Controller controller,string message) {
            controller.TempData["info"] = message;
        }
        public static void FlashWarning(this Controller controller, string message) {
            controller.TempData["warning"] = message;
        }
        public static void FlashError(this Controller controller, string message) {
            controller.TempData["error"] = message;
        }
    }
}

然后创建 ASP.NET App_Code 文件夹并在其中创建一个 .cshtml 文件(可能是 Flash.cshtml)并粘贴以下代码

App_Code/Flash.cshtml:

@helper FlashMessage(TempDataDictionary tempData){
    var message = "";
    var className = "";
    if (tempData["info"] != null)
    {
        message = tempData["info"].ToString();
        className = "flashInfo";
    }
    else if (tempData["warning"] != null)
    {
        message = tempData["warning"].ToString();
        className = "flashWarning";
    }
    else if (tempData["error"] != null)
    {
        message = tempData["error"].ToString();
        className = "flashError";
    }
    if (!String.IsNullOrEmpty(message))
    {
        <script type="text/javascript">
            $(document).ready(function() {
            $('#flash').html('@message');
            $('#flash').toggleClass('@className');
            $('#flash').slideDown('slow');
            $('#flash').click(function(){$('#flash').toggle('highlight')});
            });
        </script>
    }
}

这与 Flash 功能之前所做的相同,但方式更简洁。

除了您称呼它的方式外,其余内容与吉姆的答案相同。您需要像这样调用它,而不是使用@Html.Flash():

@Flash.FlashMessage(TempData)

请注意,上一行中的 Flash 是 App_Code 文件夹中的 .cshtml 文件的名称。

希望对你有帮助。

【讨论】:

    【解决方案4】:

    我重构了 Imran 的答案以使代码更短:

    Helpers/FlashHelper.cs

    namespace System.Web.Mvc
    {
        public enum FlashEnum
        {
            Success = 1,
            Info = 2,
            Warning = 3,
            Error = 4
        }
        public static class FlashHelper
        {
            public static void Flash(this Controller controller, string message, 
                FlashEnum type = FlashEnum.Success)
            {
                controller.TempData[string.Format("flash-{0}", 
                    type.ToString().ToLower())] = message;
            }
        }
    }
    

    App_Code/Flash.cshtml

    @helper FlashMessage(System.Web.Mvc.TempDataDictionary tempData)
    {
        var flash = tempData.Where(item => item.Key.StartsWith("flash-"))
            .Select(item => 
                new { Message = item.Value, ClassName = item.Key }).FirstOrDefault();
        if (flash != null)
        {
        <script type="text/javascript">
            $(function () {
                var $flash = $('<div id="flash" style="display:none;">');
                $flash.html('@flash.Message');
                $flash.toggleClass('flash');
                $flash.toggleClass('@flash.ClassName');
                $('body').prepend($flash);
                $flash.slideDown('slow');
                $flash.click(function () { $(this).slideToggle('highlight'); });
            });
        </script>
        }
    }
    

    从 twitter bootstrap 借来的 CSS 代码

    /* Styles for flash messages
    -----------------------------------------------------------*/
    
    .flash
    {
        padding: 8px 35px 8px 14px;
        margin-bottom: 18px;
        border: 1px solid;
    }
    
    .flash-success
    {
        color: #468847;
        background-color: #DFF0D8;
        border-color: #D6E9C6;
    }
    
    .flash-info
    {
        color: #3A87AD;
        background-color: #D9EDF7;
        border-color: #BCE8F1;
    }
    
    .flash-warning
    {
        color: #C09853;
        background-color: #FCF8E3;
        border-color: #FBEED5;
    }
    
    .flash-error
    {
        color: #B94A48;
        background-color: #F2DEDE;
        border-color: #EED3D7;
    }
    

    在控制器内部使用:

    this.Flash("Huston, we have an error!!", FlashEnum.Error);
    

    在布局(或其他 cshtml 文件)内使用:

    @Flash.FlashMessage(TempData)
    

    【讨论】:

    • +1 泰勒,这个话题有它自己的生命。又短又甜!! :-)
    • 泰勒,我有一个可能有用的小修改,所以希望您不介意我将您的答案更改为住宿,如果不满意,请随时回复。
    • 我发现助手可以访问 ViewContext,所以你不必传入 TempData。您可以在帮助程序中使用它: var tempData = htmlHelper.ViewContext.TempData;然后视图中的调用就变成了:@Html.FlashMessage()
    【解决方案5】:

    我知道有几种解决方案,但我一直在寻找纯 C# 解决方案。我最喜欢@TylerLong 的解决方案,尽管我想支持每种类型的多条消息。另外,这是针对 ASP.NET MVC4 更新的,由于不需要更改配置文件,它可能也适用于其他版本的 MVC 框架。

    特点

    • 纯 C# 解决方案
    • 使用 View Helpers、Partials 和 Controller 类的扩展方法
    • 应该与 MVC 框架的多个版本兼容
    • 每种类型支持多条消息
    • 您的 Web.config 文件没有配置更改

    1) 创建MvcProject/Helpers/FlashHelper.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace MvcProject.Helpers
    {
        public enum FlashLevel
        {
            Info = 1,
            Success = 2,
            Warning = 3,
            Danger = 4
        }
    
        public static class FlashHelper
        {
            public static void Flash(this Controller controller, string message, FlashLevel level)
            {
                IList<string> messages = null;
                string key = String.Format("flash-{0}", level.ToString().ToLower());
    
                messages = (controller.TempData.ContainsKey(key))
                    ? (IList<string>)controller.TempData[key]
                    : new List<string>();
    
                messages.Add(message);
    
                controller.TempData[key] = messages;
            }
        }
    }
    

    2) 将MvcProject/Views/Shared/_Flash.cshtml 创建为部分:

    @helper FlashMessage(System.Web.Mvc.TempDataDictionary tempData)
    {
        <div class="flash-messages">
        @foreach (FlashLevel level in (FlashLevel[]) Enum.GetValues(typeof(FlashLevel)))
        {
            string type = level.ToString().ToLower();
            string key = "flash-" + type;
    
            if (tempData.ContainsKey(key))
            {
                IList<string> messages = (IList<string>)tempData[key];
    
                foreach (string message in messages)
                {
                    <p class="alert alert-@type" role="alert">@message</p>
                }
            }
        }
        </div>
    }
    
    @FlashMessage(TempData)
    

    3) 在MvcProject/Views/Shared/_Layout.cshtml 中渲染_Flash 部分

    @Html.Partial("_Flash")
    

    这将导致网页中包含 Flash 消息。

    4) 在控制器中添加 Flash 消息

    最后一块拼图在你的控制器中,它现在应该有一个名为Flash(string message, FlashLevel level)的方法:

    using MvcProject.Helpers;
    
    public class FoosController : Controller
    {
        public ActionResult Edit(int id, FooViewModel model)
        {
            // ...
            this.Flash("Foo was updated", FlashLevel.Success);
            this.Flash("Another success message!", FlashLevel.Success);
            this.Flash("But there was a slight problem...", FlashLevel.Warning);
    
            return RedirectToAction("Edit", new { id = id });
        }
    }
    

    【讨论】:

    • 这个答案还没有得到足够的爱。 :)
    • 如果您将类从“flash-{0}”更改为“alert alert-{0}”并且不使用主要级别或错误级别,这对引导程序非常有效。不需要额外的 .flash-messages css。
    • @thelem:我采纳了您的建议并更新了我的答案。谢谢!
    【解决方案6】:

    我在客户端使用 cookie 和 JavaScript 为 ASP.NET 编写了 Rails 样式的 Flash 消息示例,并附有源代码和示例。

    用法

    添加对两个 JavaScript 文件的引用:jquery.cookie.js(标准 jQuery cookie 插件)和jQuery.flashMessage.js

    在主布局视图中引用 _Flash.cshtml 部分。这将确定 Flash 消息出现的位置。

    @Html.Partial("_Flash")
    

    将FlashMessageExtensions.cs静态扩展方法类添加到您的网站。

    在您的 MVC 控制器中,只需在 ActionResult 上使用 .Success("message to show") 和相应的 Error、Warning 或 Information 扩展方法即可在响应中设置 flash cookie。请记住添加必要的 using 语句以使用上述 flash 扩展类中的这些方法。

    [HttpPost]
    public ActionResult Create()
    {
        return RedirectToAction("Index").Success("Message shown to user after redirect");
    }
    

    默认情况下,Flash 消息将在 3 秒后或用户点击后淡出。淡出延迟可以通过在配置 JavaScript flash 插件时设置 timeout 选项来配置,或者可以将其设置为 0 来禁用。

    【讨论】:

    • 这种基于 cookie 的方法允许您使用常见的Post/Redirect/Get (PRG) 模式来帮助避免某些重复的表单提交。
    • 这是这里最被低估的答案。为 TempData 争论的人忘记了以下场景:如果您有两个应用程序服务器怎么办?并且请求在它们之间被轮询?临时数据不起作用!这是要走的路!非常感谢您的回答
    【解决方案7】:

    这是 MvcContrib 2.0 中一个非常需要的功能 - 我不确定它是否达到了 3.0。我个人在执行PRG = Post-Redirect-Get 时将其保留在会话中一小段时间。

    【讨论】:

    • TempData 正是这样做的(在 Session 中短暂保留一个值,然后在第一次使用后弹出它)。
    【解决方案8】:

    我想这会让你开心。 https://github.com/khalidabuhakmeh/MvcFlash

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 1970-01-01
      • 2010-09-17
      相关资源
      最近更新 更多