Http POST请求不止一次到达服务器

时间:2016-08-22 22:02:23

标签: javascript c# asp.net iis asp.net-web-api

我开发了一个Web应用程序。 客户端 - Javascript / Typescript + AngularJS 服务器端 - c# - asp.net web api 2 IIS Express作为主机。

我注意到一个奇怪的问题,即POST requets不止一次到达服务器。例如,一个请求被多次发送的场景,每个特定文件夹电子邮件的请求被发送3次。我还在“网络”选项卡中看到这些请求已发送三次。

public class mailsService extends ImailsService{

    static instance : ImailsService;

    // Dictionary of folder -> emails
    public Folders;


    public mailsService(){
        var scope = this;
        myInterval = setInterval(function(){
                    // Making this request until getting a successful response - waiting for server to go up
            scope.webService.get("url to get my own place").success(data => {
                scope.myLocation = data;
                scope.isLocationInit = true;
                getAllMails();
                window.cleanInterval(myInterval);
            })
        }, 3000);
    }

    // This function happen on it's own when running the client code.
    // The service is a singleton therefore this code runs only once.
    public getAllMails() {
    if (!this.isLocationInit)
        return;
    var scope = this;
    scope.webService.get("url to get all folders").then(reponse => {
        var folders = response.data;

        for (var i = 1; i <= folders.length; i ++){
                return scope.get("url to get the mails inside specific folder").then(initMails.bind(null, i));
        }});
    }

    public initMails (folderId : number, response){
        mailsService.instance.Folders[folderId].push(response.data);
    }
}

public class webService extends IwebService {
    public get(url : string){
        return this.$http.get(url);
    }

    public post(url : string, data : any){
        return this.$http.post(url, data);
    }
}


// Server side:

// Cross-Origin requests
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class MailsController : ApiController 
{
    private IMailsService _mailsService;

    public MailsController(IMailsService service)
    {
        this._mailsService = service;
    }

    public IHttpActionResult GetAllFolders()
    {
        var result = _mailsService.GetAllFolders();
        if (result == null)
            return BadRequest("...");

        return Ok(result);
    }

    public IHttpActionResult GetFolderEmails(int folderId)
    {
        var result = _mailsService.GetFolderEmails(folderId);
        if (result == null)
            return BadRequest("...");

        return Ok(result);
    }
}

控制器拟合方法命中两次甚至更多,尽管从cliend侧代码只调用一次。

这是可以配置的吗? IIS奇怪的事情?我真的不知道从哪里开始寻找。

4 个答案:

答案 0 :(得分:2)

mailsService中,设置间隔计时器以每3秒调用一次Web服务。是否有可能在响应返回并且整个处理完成时,计时器已经勾选了一次或两次并再次触发了程序?您可以通过将间隔更改为更短和更长的值来测试,并查看它是否会影响对服务器的调用次数。

降低风险的一种方法是在调用window.clearInterval之前,在成功回拨函数的最开始时调用getAllMails

scope.webService.get("url to get my own place").success(data => {
    window.clearInterval(myInterval);
    scope.myLocation = data;
    scope.isLocationInit = true;
    getAllMails();
}

另一种解决方案是避免使用setInterval。您可以执行scope.webService.get并等待响应。如果出现错误,您可以在延迟后使用setTimeout

再次致电该服务
public mailsService() {
    var scope = this;
    (function callWebService () {
        scope.webService.get("url to get my own place")
            .success(data => {
                scope.myLocation = data;
                scope.isLocationInit = true;
                getAllMails();
            })
            .error(data => { 
                setTimeout(callWebService, 3000); 
            });
    })();
}

注意:我不熟悉Typescript,因此可能有更好的方法来实现它。

答案 1 :(得分:0)

我也没有评论工具,但我总是在发布表单后立即加载一个新的新页面,导致用户点击浏览器的后退按钮(他们经常这样做),您的表格将再次发送。如果您改为加载新页面,则表单将不会再次加载。不确定你的问题是否总是发生,即使是测试,在这种情况下,我想你需要发布更多的代码。

答案 2 :(得分:0)

这种情况在所有浏览器中都会发生吗?我最近看到一个带有空src属性的脚本标记导致Firefox看似多次加载页面。

答案 3 :(得分:0)

我在您发布的网络API代码中没有看到POST的候选人,也没有在您的javascript中看到POST调用。我错过了什么吗?

正如您所提到的例如,一个请求被多次发送的情况,每个特定文件夹电子邮件的请求被发送3次,我假设它是{{1多次调用的方法。原因是以下方法中的getAllMails()逻辑:

setInterval

有可能多次进行此调用 - 考虑这样一种情况,即public mailsService(){ var scope = this; myInterval = setInterval(function(){ // Making this request until getting a successful response - waiting for server to go up scope.webService.get("url to get my own place").success(data => { scope.myLocation = data; scope.isLocationInit = true; getAllMails(); window.cleanInterval(myInterval); }) }, 3000); } 的第一次调用(第0秒)需要6秒才能完成 - 这将最终进行ajax调用在第3秒和第6秒由于setInterval逻辑,因为setInterval仅在请求成功回调后被清除。

如果评论scope.webService.get("url to get my own place")中提到setInterval背后的逻辑,那么我建议您采用不同的方法。

我不确定你的服务器是什么,如果它是&#34;不是&#34;,但假设它在那个场景中返回一些错误代码(比如错误代码-1),那么呢检查错误回调,如果错误代码与&#34相关;服务器未启动&#34;,则再次调用相同的方法。类似的东西:

// Making this request until getting a successful response - waiting for server to go up