只是为了好玩,我创建的工程相当多的TempData自己的自定义错误(消息)处理器,但与小的差异,这种处理器是可访问的遍布应用。
我不打算去解释代码每一个步骤,但总括起来,我用IHttpModule的火灾为每个请求和会话保存数据的方法。以下是代码,您可以随时编辑或提供改进建议。
的Web.config(定义模块)
<httpModules>
<add name="ErrorManagerModule" type="ErrorManagerNamespace.ErrorManager"/>
</httpModules>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ErrorManagerModule" type="ErrorManagerNamespace.ErrorManager"/>
</modules>
</system.webServer>
ErrorManager.cs(错误管理处理程序代码)
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(渲染错误的扩展方法)
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();
}
}
使用情况产生错误
// 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();
使用的渲染错误
// This will render all errors
<%= Html.RenderMessages() %>
// This will just render all errors with type "Error"
<%= Html.RenderMessages(ErrorManager.Type.Error) %>
这是一种奇怪的。在大多数情况下,缺少错误信息表示成功。成功消息在大多数情况下是冗余的。如果出现错误,你会保持在同一页面上,所以我想我仍然没有得到你想要做的逻辑。 –
我不同意,我认为告诉用户一个操作已经成功是非常重要的,否则用户可能会感到困惑。但我也明白你的意思,当失败时通知用户更重要。 –
已完成的所有可用性研究都不同意你的观点。这是一个非常强调的事情。如果没有问题,用户不希望被打扰。 –