There is a feature called \'flash\' in ruby on rails where you can put a message in \'flash\', redirect, and the message is available in the next action.
Example of
I know there are several solutions out there, but I was looking for a pure C# solution. I like @TylerLong's solution the best, though I wanted to support multiple messages for each type. Plus, this is updated for ASP.NET MVC4, and being that there are no config file changes necessary, it would probably work for other versions of the MVC framework as well.
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;
}
}
}
MvcProject/Views/Shared/_Flash.cshtml
as a Partial:@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)
_Flash
partial in MvcProject/Views/Shared/_Layout.cshtml
@Html.Partial("_Flash")
This will cause the flash messages to be included in the web page.
The last piece of the puzzle is in your Controllers, which should now have a method called 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 });
}
}
I think this would make you happy. https://github.com/khalidabuhakmeh/MvcFlash
I want to upgrade Jim's answer to use MVC 3's new helper functions.
Helper functions make it easy to write functions that primarily return Html/javascript so you don't have to use string builder or string concatenation. It results in much cleaner code.
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;
}
}
}
Then you create the ASP.NET App_Code folder and create a .cshtml file there (Flash.cshtml probably) and paste in the following code
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>
}
}
This is doing what the Flash function was doing before but in a much cleaner way.
Rest of the things stay the same as in Jim's answer except the way you call it. Instead of using @Html.Flash(), you need to call it like so:
@Flash.FlashMessage(TempData)
Please note that Flash in the above line is the name of the .cshtml file in the App_Code folder.
Hope it helps.
Endy,
I 'borrowed' this from the tekpub series:
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();
}
}
}
typical usage (inside controller):
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);
}
}
the css is pretty straightfwd too:
.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;
}
and in your site.master
<%=Html.Flash() %>
<body>
<div id="flash" style="display: none">
</div>
.... etc
</body>
enjoy...
I've written an example of Rails style Flash messages for ASP.NET using cookies and JavaScript on the client, with source code & example.
Usage
Add a reference to the two JavaScript files: jquery.cookie.js
(standard jQuery cookie plugin) and jQuery.flashMessage.js
Reference the _Flash.cshtml
partial within your main layout view. This will determine where the flash messages appear.
@Html.Partial("_Flash")
Add the FlashMessageExtensions.cs
static extension method class to your website.
Within your MVC controllers simply use the .Success("message to show")
and the corresponding Error
, Warning
or Information
extension methods on ActionResult
to set the flash cookie on the response. Remember to add the necessary using statement to use these methods from flash extension class above.
[HttpPost]
public ActionResult Create()
{
return RedirectToAction("Index").Success("Message shown to user after redirect");
}
By default the flash message will fade out after 3 seconds or if the user clicks on it. The fade-out delay is configurable by setting the timeout option when configuring the JavaScript flash plugin, or can be disabled be setting it to 0.
I refactored Imran's answer to make the code shorter:
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>
}
}
CSS code borrowed from twitter bootstrap
/* 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;
}
usage inside controller:
this.Flash("Huston, we have an error!!", FlashEnum.Error);
usage inside layout (or other cshtml file):
@Flash.FlashMessage(TempData)