如何在 ajax 客户端中使用作为 Windows 服务运行的 wcf 服务

Posted

技术标签:

【中文标题】如何在 ajax 客户端中使用作为 Windows 服务运行的 wcf 服务【英文标题】:How to consume wcf service running as windows service in ajax client 【发布时间】:2011-10-31 19:19:46 【问题描述】:

我创建了一个 WCF 服务,它托管在 Windows 服务中。当我通过解决方案资源管理器中的右侧客户端菜单将对该服务的 Web 引用添加到 asp.net Web 表单项目时,我可以访问该服务并添加对它的引用。

现在我想通过 AJAX 客户端访问该服务(即在 ASP.NET 项目中通过 ScriptManager 组件)并在计时器中调用该服务以获取连续的值流。

我从来没有在 AJAX 或 web 上工作过那么多,我没有在网上找到合适的例子。

我正在使用 WSHttpBinding。


我发布我的代码,以便您知道我做错了什么。

WCF 服务库代码:

ITestService.cs 代码....

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;

namespace TestServiceLibrary

    // NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in App.config.
    [ServiceContract(Namespace="TestServiceLibrary")]
    public interface ITestService
    
        [OperationContract]
        [WebGet]
        double Add(double n1, double n2);

        // TODO: Add your service operations here
    

TestService.cs 代码......

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace TestServiceLibrary

    // NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in App.config.
    public class TestService : ITestService
    
        public double Add(double n1, double n2)
        
            return n1 + n2;
        
    

TestServiceHost.cs(控制台应用程序代码)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using TestServiceLibrary;

namespace TestServiceHost

    class Program
    
        static void Main(string[] args)
        
            ServiceHost myhost = new ServiceHost(typeof(TestService));

            myhost.Open();

            while (System.Console.ReadKey().Key != System.ConsoleKey.Enter)
            
                //System.Threading.Thread.Sleep(100);
            

            myhost.Close();
        
    

app.config 的 XML 配置...在 wcf 服务库和 wcf 服务主机中相同(在本例中为控制台应用程序..)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's 
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service name="TestServiceLibrary.TestService" behaviorConfiguration="TestServiceLibrary.Service1Behavior">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:8731/TestServiceLibrary/TestService/" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint name="TestService_wsHttpBinding" address ="" binding="wsHttpBinding" contract="TestServiceLibrary.ITestService">
          <!-- 
              Upon deployment, the following identity element should be removed or replaced to reflect the 
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity 
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. --> 
        <!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="TestServiceLibrary.Service1Behavior">
          <!-- To avoid disclosing metadata information, 
          set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes, 
          set the value below to true.  Set to false before deployment 
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Web客户端(asp.net客户端,default.aspx)代码...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Simple AJAX Service Client Page</title>

    <script type="text/javascript">
    // <![CDATA[

    // This function creates an asynchronous call to the service
    function makeCall(operation)
        var n1 = document.getElementById("num1").value;
        var n2 = document.getElementById("num2").value;

        // If user filled out these fields, call the service
        if(n1 && n2)

            // Instantiate a service proxy
            var proxy = new TestServiceLibrary.ITestService();

            // Call correct operation on proxy       
            switch(operation)
                case "Add":
                    proxy.Add(parseFloat(n1), parseFloat(n2), onSuccess, onFail, null);            
                break;

            
        
    

    // This function is called when the result from the service call is received
    function onSuccess(mathResult)
        document.getElementById("result").value = mathResult;
    

    // This function is called if the service call fails
    function onFail()
        document.getElementById("result").value = "Error";
    

    // ]]>
    </script>

</head>
<body>
    <h1>
        Simple AJAX Service Client Page</h1>
    <p>
        First Number:
        <input type="text" id="num1" /></p>
    <p>
        Second Number:
        <input type="text" id="num2" /></p>
    <input id="btnAdd" type="button" onclick="return makeCall('Add');" value="Add" />
    <p>
        Result:
        <input type="text" id="result" /></p>
    <form id="mathForm" action="" runat="server">
    <asp:ScriptManager ID="ScriptManager" runat="server">
        <Services>
            <asp:ServiceReference Path="http://localhost:8732/TestServiceLibrary/TestService/" />
        </Services>
    </asp:ScriptManager>
    </form>
</body>
</html>

我在 ajax 中通过 asp.net 访问 web 服务时遇到的错误是 Microsoft JScript 运行时错误:'TestServiceLibrary' is undefined

请仔细阅读此代码并帮助我找出问题所在。谢谢大家的回复。

【问题讨论】:

MSDN 上有一个简单的示例可能会有所帮助:msdn.microsoft.com/en-us/library/bb410778.aspx Preet@ 感谢您的链接,我已经了解了在此示例中,项目托管在 iis 中,但我的服务托管在 Windows 服务中。 @coolcake - 托管服务的位置无关紧要。只要您的客户端具有适当的配置,它就应该能够连接到服务并进行操作。 Tim@ 我能找到任何使用 Windows 服务中托管的 wcf 服务库和用 asp.net ajax 编写的客户端的示例吗? 【参考方案1】:

看起来问题出在我的服务托管和我正在使用的端点上。

我应该在控制台应用程序中修改我的服务托管以使用 WebServiceHost 而不是 ServiceHost,然后只有 ajax 客户端可以与我的服务通信。我应该使用 webHttpBinding 而不是 wsHttpBinding。

所以webHosting的代码如下。

using (var host = new WebServiceHost(
  typeof(TestService)))

    // Start listening for messages
    host.Open();

    Console.WriteLine("Press any key to stop the service.");
    Console.ReadKey();

    // Close the service
    host.Close();

我的控制台的xml配置是

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <services>
      <service
          name="TestServiceLibrary.TestService"
          behaviorConfiguration="">
        <endpoint address="http://localhost:8732/TestService"
           binding="webHttpBinding"
           bindingConfiguration=""
           name="TestService_WebHttp"
           contract="TestServiceLibrary.ITestService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

现在,当我进行此更改时,我可以通过 ie 调用我的服务,即在 http://localhost:8732/TestService/Add?n1=20&n2=20 中使用以下 url 和它返回的结果如下&lt;double xmlns="http://schemas.microsoft.com/2003/10/Serialization/"&gt;40&lt;/double&gt;

我终于找到了解决问题的方法。我使用 JSON 作为数据通信方式,接收数据的脚本如下:

<script type="text/javascript">
    $("#mybutton").click(function () 


        $.getJSON("http://localhost:8732/TestService/Add", null, function (result) 


        );

    );     
</script>

【讨论】:

为什么我在浏览器中打开 localhost:8732/TestService 我得到:找不到端点。【参考方案2】:

使用诸如 firebug 之类的工具来确定请求发生了什么。 WSHttpBinding 默认是安全的。检查您的安全设置。首先尝试没有安全性,以确保它不是安全问题。

【讨论】:

Chandermani@ 不幸的是,我没有那么多的网络调试技能,因为我最近几天都在弄脏我的手。我会试试你的建议。 这样会更好。现在,它在很大程度上是一个猜谜游戏,有可用的信息。一旦您提供有关错误的更多详细信息,人们就可以更好地帮助您。【参考方案3】:

您是否尝试过从 AJAX 客户端连接到服务?如果是这样,您是否遇到任何错误?

如果没有看到代码,可能会有很多事情,就像 Chandermani 所说的那样。

我还没有使用 WCF 完成 AJAX,但是查看 Preet 推荐的文章,我建议检查(如果您还没有)您的 AJAX 客户端是否具有文章中的必要代码。

您的服务操作是否使用 [WebGet] 修饰?

您是否正确设置了 AJAX 客户端的配置文件?服务的配置文件是否设置正确?

【讨论】:

Tim@ 谢谢你的帮助。我已经在下面的页面中发布了代码。请帮我找出问题。

以上是关于如何在 ajax 客户端中使用作为 Windows 服务运行的 wcf 服务的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AJAX 或类似的东西在 Django 中使用 Python 脚本?

我应该使用 JSON 还是 AJAX 作为响应数据?

如何在带有 AJAX 的客户端中使用 JWT

如何使用 Ajax 在 Django 中更新 modelForm

如何使用 Json 数据作为参数进行 Jquery Ajax 调用?

如何在 AJAX 调用中获取 JavaScript 变量作为 Laravel 路由名称