MVC4:服务器重新启动后,无法发布 ajax 内部服务器错误 500

Posted

技术标签:

【中文标题】MVC4:服务器重新启动后,无法发布 ajax 内部服务器错误 500【英文标题】:MVC4: After server restart, cannot post ajax internal server error 500 【发布时间】:2017-05-05 09:48:38 【问题描述】:

我正在构建一个 MVC 应用程序。它的行为很奇怪。如果我在我的开发服务器(Visual Studio 调试)上运行它,即使我通过更改 web.config 多次重新启动我的应用程序,它也运行良好,但是当我托管它时,它的行为很奇怪。

第一次加载,一切正常。我可以正常加载所有页面,通过 ajax 发布等,但是在我使用 HttpRuntime.UnloadAppDomain(); 重新启动服务器后,每次我通过 ajax 发布时,我总是得到 ​​p>

内部服务器错误 500

我不知道应用程序发生了什么,但我怀疑客户端(用户)缓存/cookie 出了问题。

我对接收帖子的控制器函数使用[ValidateJsonAntiForgeryToken] 属性。

[HttpPost]
[ValidateJsonAntiForgeryToken]
public JsonResult LoadPage(int id, string returnUrl, PageFormViewModel pageForm, string jsonFormModel)

这是处理 json 验证令牌的代码

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter

    public void OnAuthorization(AuthorizationContext filterContext)
    
        if (filterContext == null)
        
            throw new ArgumentNullException("filterContext");
        

        var httpContext = filterContext.HttpContext;
        var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
        AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
    

这是我发布它的示例:

var getURL = $('#GetURL').val();
var returnUrl = $('#ReturnUrl').val();
var pageId = $('#PageId').val();
var token = $('input[name="__RequestVerificationToken"]').val();
var headers = ;
headers['__RequestVerificationToken'] = token;

var thePageForm = pageForm;
var theFormModel = formModel;

$.ajax(
    type: 'POST',
    url: getURL,
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    async: false,
    headers: headers,
    data: JSON.stringify( id: pageId, returnUrl: returnUrl, pageForm: thePageForm, jsonFormModel: theFormModel ),
    success: function (model)  //Load the page 
    error: function()
);

我认为@html.AntiForgeryToken()。实际上我的申请有什么问题?如果问题是用户cookie仍然被系统接受但无效,那么如何在应用重启后重置用户cookie?

---------------

更新

看起来代码实际上是可以通过控制器动作的,所以验证令牌没有问题,但是当代码到达试图从数据库中检索数据的那一行时,就会发生这种情况

消息:建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确以及 SQL Server 是否配置为允许远程连接。 (提供者:SQL 网络接口,错误:26 - 错误定位服务器/指定的实例)

这是我的连接字符串:

Conn string:Data Source=ip address;Initial Catalog=the database name;Integrated Security=False;User ID=user;Password=the password;MultipleActiveResultSets=True

这是产生错误的代码:

PageViewModel model = new PageViewModel();
model.Page = dbPages.Pages.Where(m => m.Id == id).First();

如果我使用 Incognito 模式运行它,它运行良好。那么我的应用程序到底发生了什么?

-------

更新 2

经过进一步调试,我现在确定问题出在 cookie 上。

这些是 cookie:

    .ASPXAUTH ASP.NET_SessionId

我使用“InProc”作为我的会话状态,应该在应用程序回收/重启后重置,这是我的目标,但我不知道为什么应用程序重启后,cookie仍然存在.

所以我想要的是在服务器重新启动时使所有用户的会话无效。

解决方案是:

    获取所有用户的所有会话并使其失效 在 Application_End() 中注销所有登录用户

根据我的研究,这两种解决方案都是不可能的。请帮忙

【问题讨论】:

内部服务器错误 500,通常意味着您的 C# 代码中存在未经处理的异常。您可以在您的 LoadPage 控制器操作中设置一个断点吗? 我不能这样做,因为它是一个发布应用程序,如果我在我的开发服务器中这样做,没有错,没有错误。我认为 ajax 帖子没有通过我的控制器操作,因为我在我的 ajax 代码中放置了断点,它不会成功或错误。所以我建议令牌验证有问题。 如果我在隐身模式下运行它,问题就会消失。所以我认为 cookie 或缓存有问题。 发帖的时候能看到token的价值吗?它似乎来自 html:input[name="__RequestVerificationToken"]。您是否只在文件准备好后才发帖? 是的,我可以看到该值,它在 document.ready 中,这就是它在服务器重新启动之前工作正常的原因。 服务器重启后大约 20 分钟后它又可以正常工作了。所以我认为存在 cookie / 缓存问题。 @Alvin Stefanus 您是否希望会话在重新启动 IIS 后仍然存在?看看这个答案:***.com/questions/3515947/losing-session-state 【参考方案1】:

我认为,this 将帮助您设置每次应用程序池回收时触发的事件,然后this 将帮助您使该事件中的所有 cookie 过期。

【讨论】:

【参考方案2】:

AntiForgeryToken(存储在隐藏字段中)会在应用重启后发生变化,因此之前应用会话中使用的所有值(已经加载到浏览器的 HTML 中) 已过时。应用启动后需要刷新页面才能获取新的token值,否则所有ajax调用都会被拒绝! 还有一个名为“__RequestVerificationToken”的cookie用于存储该值,如果存在,您也需要删除它。

【讨论】:

【参考方案3】:

由于您在使用 cookie 时遇到问题,您可以使用此方法清除所有 cookie

string[] myCookies = Request.Cookies.AllKeys;
foreach (string cookie in myCookies)

  Response.Cookies[cookie].Expires = DateTime.Now.AddDays(-1);

你可以打电话给HttpRuntime.UnloadAppDomain()

cookie 之所以存在,是因为它们不在服务器端;-)

【讨论】:

【参考方案4】:

问题是服务器重启后cookie没有失效。

所以这就是我的工作:

每次服务器重启时,服务器都会创建一个cookie,保存应用程序启动的时间,然后将其传递给所有用户。

在 Global.asax "Application_BeginRequest" 中检查保存应用程序启动时间的 cookie,如果 cookie 保存较早的时间,则:

WebSecurity.Logout();
Roles.DeleteCookie();

删除所有麻烦的cookies。之后,用户被重定向到登录页面。

【讨论】:

以上是关于MVC4:服务器重新启动后,无法发布 ajax 内部服务器错误 500的主要内容,如果未能解决你的问题,请参考以下文章

MVC4 剑道项目 Ajax.BeginForm UpdateTargetId 问题

MVC 4:如何在 IIS 重启后保持会话和 cookie 仍然有效?

MVC4 和 IClientValidatable - 对服务器端验证的自动 AJAX 调用

重新启动后无法启动闪亮的服务器

上传大图像时网络连接中止后恢复或重新启动ajax请求?

grpc:服务器重新启动后大约 15 秒无法恢复连接