2017-11-14 4 views
0

Ich verwende Alertify.js, um Bestätigungsmeldungen usw. in meinen Ansichten anzuzeigen. Ich habe gekämpft, um eine gute Möglichkeit zu finden, die Nachricht vom Controller zur Ansicht zu übergeben.Übergeben von Nachrichten an die Ansicht

Ich habe ein Janky-Gefühl-Setup mit TempData, das funktioniert, aber nur, wenn ich eine Ansicht zurückgebe, anstatt eine Weiterleitung, die ziemlich nutzlos ist.

Ich wollte diese Funktion zunächst zu einem Basis-Viewmodel hinzufügen, aber RedirectToAction unterstützt keine Übergabe von Viewmodels.

Ich muss entweder die TempData länger herumliegen lassen oder einen anderen Prozess verwenden.

Was ich jetzt:

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; } 
} 

Verbrauch:

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 

bearbeiten
Die akzeptierte Antwort ist richtig, aber Tonnen von Refactoring zu vermeiden, habe ich nur noch einen anderen Filter meine Attribut, unten:

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(); 
} 
+2

TempData sollte Redirect funktionieren. Warum glaubst du, dass es nicht funktioniert? Können Sie den Code teilen, der isssue ist? – Shyju

+0

@Shyju Es funktioniert, wenn ich eine Ansicht zurückgebe, und nicht, wenn ich eine Weiterleitung zurückgebe. Ich denke, das Attribut weist diesen tempdata-Eintrag neu zu, wodurch der vorhandene Eintrag verloren geht, bevor er einer Ansicht übergeben wird. Ich weiß einfach nicht, wie ich das sonst tun soll. – Sinjai

Antwort

2

Mit Ihrem aktuellen Code wird die OnResultExecuting 2 mal im Zuge Ihrer Weiterleitung ausgeführt.

Lassen Sie uns sagen Sie so umleiten tun,

public ActionResult Save(SomeViewModel model) 
{ 
    AlertifyMessages.Add(AlertifyType.Success, "Yay!", Url.Action("Index")); 
    return RedirectToAction("Index"); 
} 
public ActionResult Index() 
{ 
    return View(); 
} 

Hier, wenn Sie ein Ergebnis aus der Save Aktionsmethode zurückzukehren, wird es die OnResultExecuting Methode Ihrer AlertifyMessages Filter führt Rechenblatt die AlertifyMessages Eigenschaftswert des Lese Controller und setzen Sie das auf TempData.

Jetzt, da es eine Umleitungsantwort ist, baut Ihr Browser eine neue GET-Anforderung an Index Aktion ausgeben, und für diese Aktion Methode auch, wird es den Code in OnResultExecuting ausführen und es wird versuchen, die AlertifyMessages Eigenschaft zu lesen und festgelegt, dass zu TempData. Aber jetzt hat Ihr AlertifyMessages keinen Wert, weil Sie das in Ihrer Index Aktionsmethode nicht festgelegt haben. Denken Sie daran, Http ist statusless. Der Aufruf der Indexaktionsmethode ist wie ein völlig neuer Aufruf und dieser Aufruf erstellt eine neue Instanz des Controllers.

Die Lösung besteht darin, den Eigenschaftswert AlertifyMessages neu zu initialisieren. Sie können es aus dem TempData lesen

public ActionResult Index() 
{ 
    AlertifyMessages = TempData["Alertify"] as AlertifyMessages; 
    return View(); 
} 
+2

Ich denke, es wäre hilfreich zu erklären, die umgeleitete Anfrage ist eine neue Controller-Instanz. – Jasen

Verwandte Themen