jQuery POST 到 .NET HttpListener 并再次返回

问题描述 投票:0回答:5

我有一段 JavaScript 代码,它使用 jQuery.post 将一些数据发送到使用 HttpListener 的 .NET 应用程序。

这是js:

$.post("http://localhost:8080/catch", { name: "John", time: "2pm" },
    function(data) { 
        alert(data);
    });

和 C#:

HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;

StreamReader reader = new StreamReader(request.InputStream);
string s2 = reader.ReadToEnd();
Console.WriteLine("Data received:" + s2);

// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();

post请求发出正常,.NET应用程序读取数据正常,但JS代码似乎没有得到响应。触发 jQuery.post 的回调函数,但 data 始终未定义。为简洁起见,我在上面省略了一些 C#,其中我为侦听器设置了前缀。

有什么想法为什么我无法在客户端取回数据吗?

编辑:我应该补充一点,当我在运行 HttpFox 的情况下运行 JS 时,我得到 Http 代码 200,'NS_ERROR_DOM_BAD_URI',我认为这与我的目标“http://localhost:8080/catch”有关,但是当我在 Firefox 中点击该资源时,我得到了很好的 HTML 响应,并且它注册为 GET, 200。

编辑:我将响应简化为“喵”,这就是 fiddler 给我的完整响应:

HTTP/1.1 200 OK
Content-Length: 4
Content-Type: text/html
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 15 Apr 2011 12:58:49 GMT

meow
c# javascript http
5个回答
1
投票

不要忘记同源政策限制。除非您的 javascript 托管在

http://localhost:8080
上,否则您将无法向此 URL 发送 AJAX 请求。也不允许使用不同的端口号。如果您希望此功能正常工作,您需要将 javascript 文件托管在由
http://localhost:8080
提供的 HTML 页面上。或者让您的服务器发送 JSONP 但这仅适用于 GET 请求。

备注:确保通过将服务器上的一次性资源包装在 using 语句中来正确处置服务器上的一次性资源,否则服务器可能会开始泄漏网络连接句柄。


1
投票

不要忘记通过关闭响应来释放资源。

对响应调用 Close 将强制通过底层套接字发送响应,然后释放其所有一次性对象。

在您的示例中,仅在输出流上调用 Close 方法。这将通过套接字发送响应,但不会处置与响应相关的任何资源,其中包括您引用的输出流。

// Complete async GetContext and reference required objects
HttpListenerContext Context = Listener.EndGetContext(Result);
HttpListenerRequest Request = Context.Request;
HttpListenerResponse Response = Context.Response;

// Process the incoming request here

// Complete the request and release it's resources by call the Close method
Response.Close();

0
投票

我没有看到内容类型的设置。将内容类型设置为

text/html

response.ContentType = "text/html";

0
投票

可以大大简化代码的编写。只需使用这个:

        // Construct a response.
        string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
        context.Response.Write(responseString);

不需要

OutputStream
或大部分其他代码。如果您确实有理由使用它,请注意您实际上不应该关闭
OutputStream
。当您使用
Resopnse.OutputStream
时,您正在检索对它的引用,但您并没有取得所有权。它仍然属于
Response
对象所有,并且在请求结束时处置
Response
时将正确关闭。


0
投票

致所有未来的读者

请添加响应标头。这个非常重要。现代浏览器不会完全阻止跨域请求。这意味着当您从浏览器中输入 http://localhost:13000 时,您会从 httplistener 服务器获得 html 响应,但是当您尝试从 jQuery ajax 调用 http://localhost:13000 时,您将不会获得任何响应,除非您包括下面的标题。

response.Headers.Add("Access-Control-Allow-Origin", "*");在你的 httplistener 上。

请参考

使用 HttpListener 与 Angular 的 $http.post 而不是 jQuery.Ajax

“Access-Control-Allow-Origin”标头如何工作?

HttpListener C#


class Program
    {
        static void Main(string[] args)
        {
           HTTPServerAsync httpServerAsync = new HTTPServerAsync();
        }
    }

 class HTTPServerAsync
    {
        public HTTPServerAsync()
        {
            StartServer();
        }
        public static void StartServer()
        {
            HttpListener listener = new HttpListener();
            const int port = 13000;
            //listener.Prefixes.Add("http://112.1.1.2:" + port + "/");
            listener.Prefixes.Add("http://localhost:" + port + "/");
            listener.Start();
            StartServerAsync(listener).ContinueWith(task => { });
            
        }
        private static void ProcessClient(HttpListenerContext context)
        {
            try
            {
                var request = context.Request;
                string dataFromServer;
                using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
                {
                    dataFromServer = reader.ReadToEnd();
                }
                Console.WriteLine("Got command: {0}", dataFromServer);

                string responseText = "<HTML><BODY><table border=\"1\"><tr><td> Hello world!</td></tr></table></BODY></HTML>"; //"Hello";
                byte[] buf = Encoding.UTF8.GetBytes(responseText);

                Console.WriteLine(context.Request.Url);

            
                var response = context.Response;
                response.ContentLength64 = buf.Length;
                response.Headers.Add("Access-Control-Allow-Origin", "*");
                response.Headers.Add("Access-Control-Allow-Methods", "POST, GET");
                response.StatusCode = 200;
                response.StatusDescription = "OK";
                response.OutputStream.Write(buf, 0, buf.Length);
                response.OutputStream.Close();

            }
            catch (WebException)
            {
                Console.WriteLine("Error reading string, closing..");
                return;
            }
        }
        private static async Task StartServerAsync(HttpListener listener)
        {
            while (true)
            {
                Console.WriteLine("Waiting for client.. ");
                var context = await listener.GetContextAsync();
                Console.WriteLine("Client connected!");
                // ReSharper disable once CSharpWarnings::CS4014
                //Task.Factory.StartNew(() => StartServerAsync(listener));
                ProcessClient(context);
                //await StartServerAsync(listener);
            }
            listener.Close();
        }
    }



jQuery Client AJAX call to above httplistener 

<script>
    $(window).on('load', function () {

        $("#getDataBtn").on('click', function () {

            $.ajax({

                url: "http://localhost:13000",
                type: "GET",
                beforeSend: function () {

                },
                success: function (response, status) {
                    alert(response);
                },
                error: function (error, status) {
                    alert(error);
                }
            })

        })
    });
</script>

 <button class="btn btn-primary" id="getDataBtn">Get Data</button>
© www.soinside.com 2019 - 2024. All rights reserved.