15

目標

ユーザーが追加されたときに、ビューにメッセージを表示したいと思います。

問題

ModelState.AddModelErrorモデルで問題が発生した場合、失敗したメッセージを処理するメソッド ( ) があります。しかし、問題がなければ、ユーザーのアクションが成功したというメッセージをユーザーにどのように処理すればよいでしょうか?

解決策を提供するこのスレッドを見つけましたが、約 3 年が経過したので、知る必要があります。別の方法はありません。おそらくもっと成熟した方法ですか? そうではないというわけではありませんが、私たちは今でも同じように成功のメッセージを扱っていますか?

4

6 に答える 6

13

Brad Christie's answerから拡張して、組み込みの Bootstrap3 サポートでこれを行うNuGet パッケージBootstrapNotificationsを作成しました。このパッケージは、事前にスタイル設定されたアラートで複数の通知タイプ (エラー、警告、成功、および情報) もサポートしており、簡単に拡張できます。

この拡張機能は、同じタイプと異なるタイプのリクエストごとに複数の通知をエレガントにサポートします。

コード

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からダウンロードできます。

于 2014-01-15T19:32:09.610 に答える
11

TempDataユーザーに通知する目的で UI に 1 回限りの情報を渡すのは悪い方法ではありません。それらの優れた点は、アクション コール間で保持されますが、読み取られると削除されることです。したがって、「うまくいきました」というメッセージを渡すだけの場合は、うまく機能します。

それらをいくつかの方法で関連付けることができますが、理解を深めるために一般的な例を示します。

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 がページの上部に金色のバーを表示するのとほぼ同じです)。

于 2013-08-20T14:53:35.153 に答える
3

これに対する良い解決策は、TempDataコレクションです。その値はリクエストの最後にクリアされるため、何かが成功したことをユーザーに通知するような 1 回限りのメッセージに最適です。

コントローラ

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

意見

@TempData["Message"]

はい、これは現在でも最善のアプローチです。

于 2013-08-20T14:45:36.403 に答える
1
TempData

MVC TempData を使用 - TempData

そのページ リクエストでのみ使用できます。成功メッセージなどに最適です。

于 2013-08-20T14:44:36.887 に答える
0

概念的には、答えはまだ成り立っていると思います。メッセージがビューの不可欠な部分である場合は、ViewModel. TempData定義を変更せずにデータを渡すためのショートカットですが、ViewModel一部の人々は眉をひそめています。

于 2013-08-20T14:45:47.673 に答える