Solo per divertimento, ho creato il mio gestore di errore personalizzato (messaggio) che funziona come TempData, ma con la piccola differenza che questo gestore è accessibile in tutta l'applicazione.
Non ho intenzione di spiegare ogni singolo passaggio del codice, ma per sommare tutto, ho usato IHttpModule per sparare un metodo per ogni richiesta e Session per salvare i dati. Di seguito è riportato il codice, sentiti libero di modificare o dare suggerimenti per miglioramenti.
web.config (Definizione di modulo)
<httpModules>
<add name="ErrorManagerModule" type="ErrorManagerNamespace.ErrorManager"/>
</httpModules>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ErrorManagerModule" type="ErrorManagerNamespace.ErrorManager"/>
</modules>
</system.webServer>
ErrorManager.cs (codice direttore di gestore di errore)
public class ErrorManager : IRequiresSessionState, IHttpModule
{
private const string SessionKey = "ERROR_MANAGER_SESSION_KEY";
public enum Type
{
None,
Warning,
Success,
Error
}
/*
*
* Public methods
*
*/
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.AcquireRequestState += new EventHandler(Initiliaze);
}
public static IList<ErrorModel> GetErrors(ErrorManager.Type type = Type.None)
{
// Get all errors from session
var errors = GetErrorData();
// Destroy Keep alive
// Decrease all errors request count
foreach (var error in errors.Where(o => type == ErrorManager.Type.None || o.ErrorType == type).ToList())
{
error.KeepAlive = false;
error.IsRead = true;
}
// Save errors to session
SaveErrorData(errors);
//return errors;
return errors.Where(o => type == ErrorManager.Type.None || o.ErrorType == type).ToList();
}
public static void Add(ErrorModel error)
{
// Get all errors from session
var errors = GetErrorData();
var result = errors.Where(o => o.Key.Equals(error.Key, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
// Add error to collection
error.IsRead = false;
// Error with key is already associated
// Remove old error from collection
if (result != null)
errors.Remove(result);
// Add new to collection
// Save errors to session
errors.Add(error);
SaveErrorData(errors);
}
public static void Add(string key, object value, ErrorManager.Type type = Type.None, bool keepAlive = false)
{
// Create new error
Add(new ErrorModel()
{
IsRead = false,
Key = key,
Value = value,
KeepAlive = keepAlive,
ErrorType = type
});
}
public static void Remove(string key)
{
// Get all errors from session
var errors = GetErrorData();
var result = errors.Where(o => o.Key.Equals(key, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
// Error with key is in collection
// Remove old error
if (result != null)
errors.Remove(result);
// Save errors to session
SaveErrorData(errors);
}
public static void Clear()
{
// Clear all errors
HttpContext.Current.Session.Remove(SessionKey);
}
/*
*
* Private methods
*
*/
private void Initiliaze(object o, EventArgs e)
{
// Get context
var context = ((HttpApplication)o).Context;
// If session is ready
if (context.Handler is IRequiresSessionState ||
context.Handler is IReadOnlySessionState)
{
// Load all errors from session
LoadErrorData();
}
}
private static void LoadErrorData()
{
// Get all errors from session
var errors = GetErrorData().Where(o => !o.IsRead).ToList();
// If KeepAlive is set to false
// Mark error as read
foreach (var error in errors)
{
if (error.KeepAlive == false)
error.IsRead = true;
}
// Save errors to session
SaveErrorData(errors);
}
private static void SaveErrorData(IList<ErrorModel> errors)
{
// Make sure to remove any old errors
HttpContext.Current.Session.Remove(SessionKey);
HttpContext.Current.Session.Add(SessionKey, errors);
}
private static IList<ErrorModel> GetErrorData()
{
// Get all errors from session
return HttpContext.Current.Session[SessionKey]
as IList<ErrorModel> ??
new List<ErrorModel>();
}
/*
*
* Model
*
*/
public class ErrorModel
{
public string Key { get; set; }
public object Value { get; set; }
public bool KeepAlive { get; set; }
internal bool IsRead { get; set; }
public Type ErrorType { get; set; }
}
HtmlHelperExtension.cs (un metodo di estensione per il rendering degli errori)
public static class HtmlHelperExtension
{
public static string RenderMessages(this HtmlHelper obj, ErrorManager.Type type = ErrorManager.Type.None, object htmlAttributes = null)
{
var builder = new TagBuilder("ul");
var errors = ErrorManager.GetErrors(type);
// If there are no errors
// Return empty string
if (errors.Count == 0)
return string.Empty;
// Merge html attributes
builder.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);
// Loop all errors
foreach (var error in errors)
{
builder.InnerHtml += String.Format("<li class=\"{0}\"><span>{1}</span></li>",
error.ErrorType.ToString().ToLower(),
error.Value as string);
}
return builder.ToString();
}
}
Uso per la creazione di errori
// This will only be available for one request
ErrorManager.Add("Key", "An error message", ErrorManager.Type.Error);
// This will be available for multiple requests
// When error is read, it will be removed
ErrorManager.Add("Key", "An error message", ErrorManager.Type.Error, true);
// Remove an error
ErrorManager.Remove("AnotherKey");
// Clear all error
ErrorManager.Clear();
Uso per il rendering errori
// This will render all errors
<%= Html.RenderMessages() %>
// This will just render all errors with type "Error"
<%= Html.RenderMessages(ErrorManager.Type.Error) %>
Questo è un po 'strano. Nella maggior parte dei casi, la mancanza di un messaggio di errore indica il successo. I messaggi di successo sono ridondanti nella maggior parte dei casi. Se c'è un errore rimarrai sulla stessa pagina, quindi credo di non avere ancora la logica di quello che stai cercando di fare. –
Non sono d'accordo, penso sia molto importante informare l'utente che un'azione è riuscita, altrimenti l'utente può essere confuso. Ma capisco anche cosa intendi, è più importante informare l'utente quando fallisce. –
Tutti gli studi di usabilità che sono stati fatti non sono d'accordo con te. È una cosa molto stressata. Gli utenti non vogliono essere disturbati se non c'è un problema. –