Сообщение о успехе от контроллера к представлению
Цель
Я хочу отобразить в моем представлении некоторое сообщение, когда какой-либо пользователь добавлен.
Проблема
Когда что-то пойдет не так в нашей модели, существует метод (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">×</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">×</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">×</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">×</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
, которое некоторые люди недовольны.