【发布时间】:2014-03-26 13:59:49
【问题描述】:
我避免使用默认的 ASP.NET 重定向错误的方法(正如许多人所做的那样)。干净的 AJAX 代码和 SEO 是其中的原因。
不过,我是用下面的方法来做的,看来我在转账中可能会丢失HttpContext.Current.Items?
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="401" />
<remove statusCode="403" />
<remove statusCode="404" />
<remove statusCode="500" />
<error statusCode="401" responseMode="ExecuteURL" path="/Account/SignIn" />
<error statusCode="403" responseMode="ExecuteURL" path="/Site/Forbidden" />
<error statusCode="404" responseMode="ExecuteURL" path="/Site/NotFound" />
<error statusCode="500" responseMode="ExecuteURL" path="/Site/Error" />
</httpErrors>
我以为它只是在幕后执行了Server.Transfer(),据我所知保留了Items。 (参见:Scope of HttpContext.Current.Items 和 http://weblog.west-wind.com/posts/2010/Jan/20/HttpContextItems-and-ServerTransferExecute)
但我还在“ExecuteURL”之前的Items 中捕获了一些内容,并在传输(或其他任何内容)之后检索/输出它,它似乎消失了。我看到它进入了Items 集合,我看到Count 提高到5,然后当检索到该值时,集合中只有2 个项目。
发生了什么事?
如果您想更多地了解我在做什么并推荐一个替代实现,我愿意接受。我正在使用它以一种不受竞争条件的方式将 ELMAH 错误 ID 推送到 ViewModel 中。 (即,我要替换的常见解决方法是仅显示最近的错误。)这是我的代码:
Global.asax
protected void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args) {
ElmahSupplement.CurrentId = args.Entry.Id;
}
void ErrorLog_Filtering(object sender, ExceptionFilterEventArgs e) {
if (ElmahSupplement.IsNotFound(e.Exception)) {
ElmahSupplement.LogNotFound((e.Context as HttpContext).Request);
e.Dismiss();
}
}
SiteController.cs
public virtual ActionResult Error() {
Response.StatusCode = 500;
return View(MVC.Site.Views.Error, ElmahSupplement.CurrentId);
}
ElmahSupplement.cs
public class ElmahSupplement {
// TODO: This is a rather fragile way to access this info
private static readonly Guid contextId = new Guid("A41A67AA-8966-4205-B6C1-14128A653F21");
public static string CurrentId {
get {
return
// Elmah 1.2 will fail to log when enumerating form values that raise RequestValidationException (angle brackets)
// https://code.google.com/p/elmah/issues/detail?id=217
// So this id could technically be empty here
(HttpContext.Current.Items[contextId] as string);
}
set {
HttpContext.Current.Items[contextId] = value;
}
}
public static void LogNotFound(HttpRequest request) {
var context = RepositoryProxy.Context;
context.NotFoundErrors.Add(new NotFoundError {
RecordedOn = DateTime.UtcNow,
Url = request.Url.ToString(),
ClientAddress = request.UserHostAddress,
Referrer = request.UrlReferrer == null ? "" : request.UrlReferrer.ToString()
});
context.SaveChanges();
}
public static bool IsNotFound(Exception e) {
HttpException he = e as HttpException;
return he != null && he.GetHttpCode() == 404;
}
}
【问题讨论】:
-
您的假设是错误的,ASP.NET MVC 不再使用 Server.Transfer,因此它的行为不像您预期的那样。 Server.Transfer 也不适用于 ASP.NET MVC,因为 MVC 是在异步管道上重建的。
-
Akash,你好像在做两个 cmets,但我理解他们说的是同一件事,所以也许我误解了?另外,虽然我当然相信你,但我并不真正理解 Server.Transfer 的问题。这不是在 MVC 处理程序的范围之外执行的吗?我想最重要的是,如果您对如何解决有任何建议,请提出。 18 小时,直到 +50 丢失。 :(
标签: asp.net asp.net-mvc elmah httpcontext server.transfer