Сообщение о успехе от контроллера к представлению

Цель

Я хочу отобразить в моем представлении некоторое сообщение, когда какой-либо пользователь добавлен.

Проблема

Когда что-то пойдет не так в нашей модели, существует метод (ModelState.AddModelError) для обработки неуспешных сообщений. Но, когда все идет хорошо, как мы можем обрабатывать сообщение пользователю, говорящее, что его действие было успешным?

Я нашел эту тему, которая предоставляет решение, но прошло около трех лет, и мне нужно знать: нет ли другого способа, возможно, более зрелого? Не то, чтобы этого не было, но мы все еще имеем дело с сообщениями об успехе таким же образом?

Ответ 1

Есть несколько способов обмануть этого кота. Вы можете использовать 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!";

Ответ 2

TempData - это не плохой способ передать одноразовые файлы в пользовательский интерфейс с целью уведомления пользователя. Большая их часть - они сохраняются между вызовами действий, но удаляются после их чтения. Таким образом, в случае просто раздачи сообщения "это сработало" он отлично работает.

Вы можете связать их несколькими способами, но я дам вам общий пример для вас:

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

Расширяясь от , я создал пакет NuGet, BootstrapNotifications, что сделает это для вас со встроенной поддержкой 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.

Ответ 4

Хорошим решением для этого является коллекция TempData. Его значения очищаются в конце запроса, что делает его идеальным для одноразовых сообщений, таких как информирование пользователя о том, что что-то было успешным.

контроллер

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

Вид

@TempData["Message"]

И да, это по-прежнему лучший подход.

Ответ 5

TempData

Использовать MVC TempData - TempData

Он доступен только для этого запроса страницы. Что идеально подходит для сообщений о успехах и т.д.

Ответ 6

Концептуально, я думаю, что ответ по-прежнему сохраняется. Если сообщение является неотъемлемой частью представления, оно должно быть частью ViewModel. TempData является ярлыком для передачи данных без изменения определения ViewModel, которое некоторые люди недовольны.