我使用Alertify.js在我的观看中显示确认消息等。我一直在努力寻找一种从控制器传递消息的好方法。
我有一个使用TempData工作的janky-feeling设置,但是只有当我返回一个视图而不是重定向时,这是非常无用的。
我最初要将此功能添加到基本视图模型,但RedirectToAction
不支持传递视图模型。
我要么需要更长时间地使用TempData,要么完全使用不同的过程。
我现在使用的是:
public class AlertifyMessages
{
public List<AlertifyMessage> Messages { get; private set; } = new List<AlertifyMessage>();
public void Add(AlertifyType type, string message, string callbackUrl = null)
{
Messages.Add(new AlertifyMessage(type, message, callbackUrl));
}
}
public class AlertifyMessage
{
public AlertifyType Type { get; set; }
public string Message { get; set; }
public string CallbackUrl { get; set; }
public AlertifyMessage(AlertifyType type, string message, string callbackUrl)
{
Type = type;
Message = message;
CallbackUrl = callbackUrl;
}
}
public enum AlertifyType
{
Log,
Error,
Success
}
/// <summary>
/// Applies Alertify messages to TempData after action method runs
/// <para>Can only be used with <see cref="BaseController"/></para>
/// </summary>
public class AlertifyAttribute : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
BaseController bc = (BaseController)context.Controller;
bc.TempData["Alertify"] = bc.AlertifyMessages;
}
}
[Alertify]
public class BaseController : Controller
{
public BaseController()
{
AlertifyMessages = new AlertifyMessages();
}
public AlertifyMessages AlertifyMessages { get; set; }
}
用法:
public class MyController : BaseController
{
public ActionResult Index()
{
AlertifyMessages.Add(AlertifyType.Success, "Yay!", Url.Action("Index"));
return View(/*new ViewModel()*/);
}
}
// Then loop through and display messages in view using TempData
修改
接受的答案是正确的,但为了避免大量的重构,我只是在我的属性中添加了另一个过滤器,如下所示:
private const string alertify = "Alertify";
public override void OnActionExecuting(ActionExecutingContext context)
{
BaseController bc = (BaseController)context.Controller;
bc.Messages = (bc.TempData[alertify] == null) ? new AlertifyMessages() : (AlertifyMessages)bc.TempData[alertify];
// Faster? Better? Harder? Stronger?
//bc.Messages = (AlertifyMessages)bc.TempData[alertify] ?? new AlertifyMessages();
}
答案 0 :(得分:2)
使用当前代码,OnResultExecuting
将在重定向过程中执行2次。
假设你正在做这样的重定向,
public ActionResult Save(SomeViewModel model)
{
AlertifyMessages.Add(AlertifyType.Success, "Yay!", Url.Action("Index"));
return RedirectToAction("Index");
}
public ActionResult Index()
{
return View();
}
当您从Save
操作方法返回结果时,它将执行AlertifyMessages过滤器的OnResultExecuting
方法,该方法读取控制器的AlertifyMessages
属性值并将其设置为TempData的。
现在,由于它是重定向响应,因此您的浏览器会向Index
操作发出新的GET请求。对于该操作方法,它也将执行OnResultExecuting
内的代码并尝试阅读AlertifyMessages
属性并将其设置为TempData
。但是现在您的AlertifyMessages
没有任何价值,因为您没有在Index
操作方法中设置该值。 记住Http是无国籍的。这里的索引操作方法调用就像一个全新的调用,该调用将创建一个新的控制器实例。
解决方案是重新初始化AlertifyMessages
属性值。您可以从TempData
public ActionResult Index()
{
AlertifyMessages = TempData["Alertify"] as AlertifyMessages;
return View();
}