从控制器到视图的成功信息

问题描述 投票:14回答:7

目标

我想在我的视图中显示一些用户被添加时的信息。

问题是,我想在我的视图中显示一些用户添加时的信息。

当我们的模型出现问题时,有一个方法(ModelState.AddModelError)来处理不成功的消息。但是,当事情进展顺利的时候,我们如何处理给用户的消息说他的操作是成功的呢?

我发现 这条 提供了一个解决方案,但大约三年过去了,我需要知道:有没有另一种方式,也许更成熟?不是说这不是,而是我们还在用这种方式处理成功的消息吗?

c# asp.net asp.net-mvc-4 notifications
7个回答
10
投票

有几种方法可以解决这个问题。你可以使用ViewBag。

ViewBag.SuccessMessage = "<p>Success!</p>";

然后在你的视图中,你可以把它渲染到页面上。

@ViewBag.SuccessMessage

我不喜欢ViewBag,所以我通常会创建一个ViewModel对象 来保存我的特定视图所需要的所有数据。而成功消息就是这样的数据。

public MyViewModel{
    public bool IsSuccess {get;set;}
}

然后在你的控制器中,你会把这个ViewModel传给你的强壮类型的视图。

[HttpPost]
public ActionResult Update(MyViewModel vm){
    //Glorious code!

   return View(vm)
}

最后,只需在你的视图中检查它,如果成功的话,就打印一条消息。

@if(vm.IsSuccess){
     <p>Here is an amazing success message!</p>
}

另外,你可以用TempData来代替,它的工作原理和ViewBag一样,但只持续到你的下一个请求结束,然后就会被丢弃。

TempData["SuccessMessage"] = "Success!";

13
投票

扩展自 布拉德-克里斯蒂的 回答我创建了一个NuGet包。浏览器它将通过内置的Bootstrap3支持为你做这些事情。这个包还支持多种通知类型(错误、警告、成功和信息)与预设的警报,并且很容易扩展。

该扩展支持同一类型和不同类型的请求的多个通知,非常优雅。

代码

NotificationExtensions.cs:

public static class NotificationExtensions
{
    private static IDictionary<String, String> NotificationKey = new Dictionary<String, String>
    {
        { "Error",      "App.Notifications.Error" }, 
        { "Warning",    "App.Notifications.Warning" },
        { "Success",    "App.Notifications.Success" },
        { "Info",       "App.Notifications.Info" }
    };


    public static void AddNotification(this ControllerBase controller, String message, String notificationType)
    {
        string NotificationKey = getNotificationKeyByType(notificationType);
        ICollection<String> messages = controller.TempData[NotificationKey] as ICollection<String>;

        if (messages == null)
        {
            controller.TempData[NotificationKey] = (messages = new HashSet<String>());
        }

        messages.Add(message);
    }

    public static IEnumerable<String> GetNotifications(this HtmlHelper htmlHelper, String notificationType)
    {
        string NotificationKey = getNotificationKeyByType(notificationType);
        return htmlHelper.ViewContext.Controller.TempData[NotificationKey] as ICollection<String> ?? null;
    }

    private static string getNotificationKeyByType(string notificationType)
    {
        try
        {
            return NotificationKey[notificationType];
        }
        catch (IndexOutOfRangeException e)
        {
            ArgumentException exception = new ArgumentException("Key is invalid", "notificationType", e);
            throw exception;
        }
    }
}

public static class NotificationType
{
    public const string ERROR = "Error";
    public const string WARNING = "Warning";
    public const string SUCCESS = "Success";
    public const string INFO = "Info";

}

_Notifications.cshtml:

@using YourApp.Extensions
@{
    var errorList = Html.GetNotifications(NotificationType.ERROR);
    var warningList = Html.GetNotifications(NotificationType.WARNING);
    var successList = Html.GetNotifications(NotificationType.SUCCESS);
    var infoList = Html.GetNotifications(NotificationType.INFO);
}
<!-- display errors -->
@if (errorList != null)
{
    <div class="alert alert-danger alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        @if(errorList.Count() > 1){
            <strong><span class="glyphicon glyphicon-remove"></span> There are @errorList.Count() errors: </strong>
            <ul>
                @foreach (String message in errorList)
                {
                    <li>@Html.Raw(message)</li>
                }
            </ul>
        }
        else{
            <strong><span class="glyphicon glyphicon-remove"></span> Error: </strong>
            @Html.Raw(errorList.First())
        }
    </div>
}

<!-- display warnings -->
@if (warningList != null)
{
    <div class="alert alert-warning alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        @if(warningList.Count() > 1){
            <strong><span class="glyphicon glyphicon-warning-sign"></span> There are @warningList.Count() warnings: </strong>
            <ul>
                @foreach (String message in warningList)
                {
                    <li>@Html.Raw(message)</li>
                }
            </ul>
        }
        else{
            <strong><span class="glyphicon glyphicon-warning-sign"></span> Warning: </strong>
            @Html.Raw(warningList.First())
        }
    </div>
}

<!-- display success -->
@if (successList != null)
{
    <div class="alert alert-success alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        @if(successList.Count() > 1){
            <strong><span class="glyphicon glyphicon-ok"></span> There are @successList.Count() successful notifications: </strong>
            <ul>
                @foreach (String message in successList)
                {
                    <li>@Html.Raw(message)</li>
                }
            </ul>
        }
        else{
            <strong><span class="glyphicon glyphicon-ok"></span> Success! </strong>
            @Html.Raw(successList.First())
        }
    </div>
}

<!-- display success -->
@if (infoList != null)
{
    <div class="alert alert-info alert-dismissable">
        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
        @if(infoList.Count() > 1){
            <strong><span class="glyphicon glyphicon-info-sign"></span> There are @infoList.Count() notifications: </strong>
            <ul>
                @foreach (String message in infoList)
                {
                    <li>@Html.Raw(message)</li>
                }
            </ul>
        }
        else{
            <strong><span class="glyphicon glyphicon-info-sign"></span> </strong>
            @Html.Raw(infoList.First())
        }
    </div>
}

要查看所有这些代码以及如何使用它,你可以从以下地方下载一个完整的工作演示。github.


10
投票

TempData 是一个不错的方式,可以把一次性的东西交给UI,以达到通知用户的目的。它们最大的优点是它们会在动作调用之间持续存在,但一旦被读取就会被删除。所以,在只是交接一个 "成功了 "的消息的情况下,它的效果非常好。

你可以用几种方式来绑定它们,但我将给你一个通用的例子来让你去做。

public static class NotificationExtensions
{
    private const String NotificationsKey = "MyApp.Notifications";

    public static void AddNotification(this ControllerBase controller, String message)
    {
        ICollection<String> messages = controller.TempData[NotificationsKey] as ICollection<String>;
        if (messages == null)
        {
            controller.TempData[NotificationsKey] = (messages = new HashSet<String>());
        }
        messages.Add(message);
    }

    public static IEnumerable<String> GetNotifications(this HtmlHelper htmlHelper)
    {
        return htmlHelper.ViewContext.Controller.TempData[NotificationsKey] as ICollection<String> ?? new HashSet<String>();
    }
}

现在在你的操作中,你可以调用 this.AddNotification("User successfully added!"); 在你的视图中,你可以使用......或类似的东西来显示它们。

@foreach (String notification in Html.GetNotifications())
{
    <div class="notification">
        <p>@notification/p>
        <i class="icon-close"></i>
    </div>
}

(......或类似的东西),它可以有效地放置在你的主视图中,并作为一般的通知方法,用于任何行动的执行。几乎就像StackOverflow在某些事件期间在页面顶部有金条一样)。


3
投票

一个很好的解决方案是 TempData 集合,它的值会在请求结束时被清空。 它的值会在请求结束时被清除,这使得它成为一次性消息的理想选择,比如通知用户某事成功了。

控制器

TempData["Message"] = "Operation successful!";

查看

@TempData["Message"]

是的,这仍然是目前最好的方法。


1
投票
TempData

使用MVC TempData - 温度数据

它只适用于该页面的请求。 这对于成功信息等来说是完美的。


0
投票

从概念上来说,我认为答案还是成立的。 如果消息是视图的一个组成部分,那么它应该属于 ViewModel. TempData 是传递数据的快捷方式,无需修改 ViewModel 定义,有些人对此嗤之以鼻。

© www.soinside.com 2019 - 2024. All rights reserved.