为什么我的控制器被调用两次?

发布于 2024-11-28 17:16:43 字数 4043 浏览 0 评论 0原文

这可能很简单,但我就是看不到。

我有我的 应用程序将数据发布到我的 WebService ()。 Sencha Touch js 代码如下所示。

var submitCommunicateCard = function () {
    console.log(rpc.views.Contact.CommunicateCard.getValues());
    Ext.Ajax.request({
        url: WebService('GetInTouch', 'CommunicateCard'), //http://webservice.example.com/GetInTouch/CommunicateCard
        method: 'post',
        params: {
            callback: 'foo', //temporary until I can better setup the callback.
            name: rpc.views.Contact.CommunicateCard.getValues().name,
            city: rpc.views.Contact.CommunicateCard.getValues().city
        }
    });
};

由于我需要“阻止”跨站点脚本问题,因此我必须编写一个添加适当标头的 ActionFilter

namespace WebService.Attributes
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();

            HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");

            string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
            {
                HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin");
            }
        }
    }
}

在我的控制器中,我从我的应用程序接收数据,如下所示。

    [AllowCrossSiteJsonAttribute]
    public JsonpResult CommunicateCard(CommunicateCardModel communicateCardModel)
    {
        CommunicateCardModel cc = null;
        string rqstMethod = System.Web.HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
        if (rqstMethod != "POST")
        {
            // Do stuff with the model


             return this.Jsonp(true);
        }
        else { 
            return this.Jsonp(false); 
        }
    }

您会发现我必须输入 if (rqstMethod != "POST") 因为“POST”中的模型是空白的,但“OPTIONS”中的模型不是。

这是正在传递的原始标头...(注意:这两个标头是成对传递的...即:控制器被调用两次。)

首次调用

选项 /GetInTouch/CommunicateCard HTTP/1.1
主机:webservice.example.com
引用者:http://192.168.3.138/
访问控制请求方法:POST
来源:http://192.168.3.138
用户代理:Mozilla/5.0(Macintosh;Intel Mac OS X 10_7_0)AppleWebKit/534.24(KHTML,如 Gecko)Chrome/11.0.696.71 Safari/534.24
访问控制请求标头:X-Requested-With、内容类型
接受:/
接受编码:gzip、deflate、sdch
接受语言:en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3

SECOND CALL (注意包含发布数据的最底行(不是包含在第一个调用中)callback=foo&name=Chester&city=Toronto)

POST /GetInTouch/CommunicateCard HTTP/1.1
主机:webservice.example.com
引用者:http://192.168.3.138/
内容长度:38
来源:http://192.168.3.138
X-Requested-With:XMLHttpRequest
用户代理:Mozilla/5.0(Macintosh;Intel Mac OS X 10_7_0)AppleWebKit/534.24(KHTML,如 Gecko)Chrome/11.0.696.71 Safari/534.24
内容类型:application/x-www-form-urlencoded;字符集=UTF-8
接受:/
接受编码:gzip、deflate、sdch
接受语言:en-US,en;q=0.8
接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.3

callback=foo&name=切斯特&city=多伦多

有什么办法可以防止多次调用我的控制器吗? (或者为什么我的控制器被调用两次?)

This is probably something simple, but I just can't see it.

I've got my application posting data to my WebService (). The Sencha Touch js code looks like this.

var submitCommunicateCard = function () {
    console.log(rpc.views.Contact.CommunicateCard.getValues());
    Ext.Ajax.request({
        url: WebService('GetInTouch', 'CommunicateCard'), //http://webservice.example.com/GetInTouch/CommunicateCard
        method: 'post',
        params: {
            callback: 'foo', //temporary until I can better setup the callback.
            name: rpc.views.Contact.CommunicateCard.getValues().name,
            city: rpc.views.Contact.CommunicateCard.getValues().city
        }
    });
};

Since I need to "thwart" my Cross Site Scripting problems, I've had to write an ActionFilter that adds the appropriate headers.

namespace WebService.Attributes
{
    public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            HttpContext.Current.Response.Cache.SetNoStore();

            HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Origin", "*");

            string rqstMethod = HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
            if (rqstMethod == "OPTIONS" || rqstMethod == "POST")
            {
                HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
                HttpContext.Current.Response.AppendHeader("Access-Control-Allow-Headers", "X-Requested-With, Accept, Access-Control-Allow-Origin");
            }
        }
    }
}

And in my controller, I'm receiving the data from my app as follows.

    [AllowCrossSiteJsonAttribute]
    public JsonpResult CommunicateCard(CommunicateCardModel communicateCardModel)
    {
        CommunicateCardModel cc = null;
        string rqstMethod = System.Web.HttpContext.Current.Request.Headers["Access-Control-Request-Method"];
        if (rqstMethod != "POST")
        {
            // Do stuff with the model


             return this.Jsonp(true);
        }
        else { 
            return this.Jsonp(false); 
        }
    }

You'll see that I had to put if (rqstMethod != "POST") because the model from the "POST" is blank, but the model from the "OPTIONS" is not.

Here are the raw headers being passed... (note: these two headers are being passed in pairs... ie: the controller is being called twice.)

FIRST CALL

OPTIONS /GetInTouch/CommunicateCard HTTP/1.1
Host: webservice.example.com
Referer: http://192.168.3.138/
Access-Control-Request-Method: POST
Origin: http://192.168.3.138
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.71 Safari/534.24
Access-Control-Request-Headers: X-Requested-With, Content-Type
Accept: /
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

SECOND CALL (notice the very bottom line that contains the posted data (which is not contained within the first call) callback=foo&name=Chester&city=Toronto)

POST /GetInTouch/CommunicateCard HTTP/1.1
Host: webservice.example.com
Referer: http://192.168.3.138/
Content-Length: 38
Origin: http://192.168.3.138
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.71 Safari/534.24
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: /
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

callback=foo&name=Chester&city=Toronto

Is there any way to prevent multiple calls to my controller? (or why IS my controller being called twice?)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

霞映澄塘 2024-12-05 17:16:43

事实证明,它是通过从我的 Sencha Touch 应用程序进行 JSONP 调用来修复的。
Ext.util.JSONP.request

// 这是错误的,不要使用此代码进行 JSONP 调用

var submitCommunicateCard = function () {
    console.log(rpc.views.Contact.CommunicateCard.getValues());
    Ext.Ajax.request({
        url: WebService('GetInTouch', 'CommunicateCard'), //http://webservice.example.com/GetInTouch/CommunicateCard
        method: 'post',
        params: {
            callback: 'foo', //temporary until I can better setup the callback.
            name: rpc.views.Contact.CommunicateCard.getValues().name,
            city: rpc.views.Contact.CommunicateCard.getValues().city
        }
    });

// 这是正确的

var submitCommunicateCard = function () {
    console.log("Outbound Data Object:");
    console.log(rpc.views.Contact.CommunicateCard.getValues());
    Ext.util.JSONP.request({
        url: WebService('GetInTouch', 'CommunicateCard'),
        method: 'post',
        callbackKey: 'callback',

        params: {
            name: rpc.views.Contact.CommunicateCard.getValues().name,
            city: rpc.views.Contact.CommunicateCard.getValues().city
        },
        callback: function (result) {
            console.log("Inbound Data Object:");
            console.log(result);
            // Handle error logic
            if (result.success === true) {
                Ext.Msg.alert("Sent!", "Thank you, your message has been sent!", Ext.emptyFn);
                rpc.views.Contact.CommunicateCard.reset();
            } else {
                Ext.Msg.alert("Oops!", "looks like something went wrong, please try again.", Ext.emptyFn);
            }
        }
    });
};

Turns out it was fixed by making a JSONP call from my Sencha Touch app.
Ext.util.JSONP.request

// THIS IS WRONG, DON'T USE THIS CODE TO MAKE JSONP CALLS

var submitCommunicateCard = function () {
    console.log(rpc.views.Contact.CommunicateCard.getValues());
    Ext.Ajax.request({
        url: WebService('GetInTouch', 'CommunicateCard'), //http://webservice.example.com/GetInTouch/CommunicateCard
        method: 'post',
        params: {
            callback: 'foo', //temporary until I can better setup the callback.
            name: rpc.views.Contact.CommunicateCard.getValues().name,
            city: rpc.views.Contact.CommunicateCard.getValues().city
        }
    });

// THIS IS RIGHT

var submitCommunicateCard = function () {
    console.log("Outbound Data Object:");
    console.log(rpc.views.Contact.CommunicateCard.getValues());
    Ext.util.JSONP.request({
        url: WebService('GetInTouch', 'CommunicateCard'),
        method: 'post',
        callbackKey: 'callback',

        params: {
            name: rpc.views.Contact.CommunicateCard.getValues().name,
            city: rpc.views.Contact.CommunicateCard.getValues().city
        },
        callback: function (result) {
            console.log("Inbound Data Object:");
            console.log(result);
            // Handle error logic
            if (result.success === true) {
                Ext.Msg.alert("Sent!", "Thank you, your message has been sent!", Ext.emptyFn);
                rpc.views.Contact.CommunicateCard.reset();
            } else {
                Ext.Msg.alert("Oops!", "looks like something went wrong, please try again.", Ext.emptyFn);
            }
        }
    });
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文