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 the use of flash:
There is a controller action Account.ChangePassword. If password change is successful, ChangePassword will fill flash with a message 'Password change successful', and then redirects to Account.Profile. In Account.Profile, the message is available so it can be displayed in the profile page.
Is there something equivalent in ASP.NET MVC 3?
I know I can build this feature myself using tempdata, but does MVC 3 have something built in?
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...
No, the TempData solution is what you are looking for.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With