将消息传递到视图

时间:2017-11-14 18:02:43

标签: c# asp.net-mvc

我使用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();
}

1 个答案:

答案 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();
}