【问题标题】:Changing method of connecting to server C#更改连接到服务器 C# 的方法
【发布时间】:2010-08-05 07:01:05
【问题描述】:

我需要更改我的 C# 应用程序连接到服务器的方式以发送请求并获得响应。我对 C# 不是很好,所以如果这个解释令人困惑,我深表歉意。目前,该程序似乎使用了一些使用 app.config 文件中的静态信息的魔法:

<configuration>
  <system.serviceModel>
    <client>
      <!-- important information here -->
    </client>
  </system.serviceModel>
</configuration>

我尝试更改 &lt;client&gt; 元素内的值,但这只会读取程序重启时的更改。

我想以不同的方式连接。这是我的设想:我可以访问 app.config 文件中的数据,将其存储在几个变量中,并允许用户根据需要更改值。当他们调整了适合他们的值时,他们点击了“连接”按钮,然后我用这段代码建立了连接。我试图找到这个问题的答案,但我找不到任何关于如何做到这一点的教程,所以任何链接也很感激。

(这个问题来自this question的答案)

感谢所有帮助,并提前致谢!

编辑

我的 Hoerster 的解决方案大部分都有效,但我遇到了一些错误,所以我更改了以下几行:

Uri calcService = new Uri("http://localhost:8000/ServiceModelSamples/Service/CalculatorService");

(使用直接 URI,因为我不想弄乱 app.config)

CalculatorClient.CalculatorClient calcClient = new CalculatorClient.CalculatorClient(calcBinding, calcEndpoint);

我有一个名为 CalculatorClient 的服务引用,因此我必须从该引用中实例化一个 CalculatorClient,因此是双“CalculatorClient”。

当我运行我的客户端(服务正在运行)时,我的客户端出现以下异常:

An unhandled exception of type 'System.ServiceModel.ProtocolException' occurred in mscorlib.dll

Additional information: Content Type text/xml; charset=utf-8 was not supported by service http://localhost:8000/ServiceModelSamples/Service/CalculatorService.  The client and service bindings may be mismatched.

我对此有点困惑,因为我没有接触任何 Reference.cs 代码。它悬停在我的 Reference.cs 中的以下行上:

return base.Channel.Add(n1, n2);

我觉得我真的很接近解决这个问题了,但我只是错过了一件事......

【问题讨论】:

  • 我将服务器/服务上的绑定更改为 BasicHttpBinding - 这可能就是您收到协议异常的原因。我将使用服务配置更新我的答案。

标签: c# .net


【解决方案1】:

嗯,听起来这里有两个问题:

  1. 如何在运行时更新 app.config(这是可能的,但不是自动的);并且,
  2. 如何在运行时根据 app.config 设置动态设置绑定和端点。

要在运行时更新您的 app.config,请致电 RefreshSection。因此,您可能希望将该调用连接到客户端按钮单击事件。

ConfigurationManager.RefreshSection("appSettings");
Console.WriteLine(ConfigurationManager.AppSettings["foo"]);

对于在运行时动态设置绑定和端点信息,这绝对是可能的。我根据MSDN Calculator Service 示例将一个简单的示例放在一起。 (为了简单起见,我使用 BasicHttpBinding 而不是 WSHttpBinding。)更新这是我对示例服务所做的唯一更改:

// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(
    typeof(ICalculator),
    new BasicHttpBinding(),
    "CalculatorService");

我采取的步骤是:

  1. 从 MSDN 代码示例创建服务并运行它(以便服务端点正在监听);
  2. 创建了一个基本的 C# 控制台应用程序并向我的服务添加了一个服务引用,以便它可以在我的客户端控制台应用程序中创建客户端引用类。 (它还创建了一个 app.config,但我没有使用它创建的任何 app.config 设置。);
  3. 编写了以下代码,用于设置我的自动生成的客户端代码将用于连接到服务的绑定和端点地址:

*

static void Main(string[] args) {
    //refresh the appSettings section
    ConfigurationManager.RefreshSection("appSettings");

    //this could come from app.configs appSettings (value = "http://localhost:8000/ServiceModelSamples/Service/CalculatorService")
    Uri calcService = new Uri(ConfigurationManager.AppSettings["uri"]);
    Binding calcBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
    EndpointAddress calcEndpoint = new EndpointAddress(calcService.AbsoluteUri);


    CalculatorClient calcClient = new CalculatorClient(calcBinding, calcEndpoint);
    double sum = calcClient.Add(10, 20);
    double difference = calcClient.Subtract(sum, 10);

    Console.WriteLine("10 + 20 = {0}", sum.ToString());
    Console.WriteLine("{0} - 10 = {1}", sum.ToString(), difference.ToString());

    Console.ReadLine();
}

应该这样做。因此,您可以从配置文件(或用户条目)中读取 Binding 和 EndpointAddress 构造函数的参数,并且可以根据需要设置其他 Binding 和 EndpointAddress 属性。

希望这会有所帮助。如果还有其他问题,请告诉我,我会相应地更新我的答案。

更新 2(现在使用 WSHttpBinding!!) 我对此进行了更新,以包括使用 WSHttpBinding(具有消息级安全性)作为第二个示例。使用 WCF 处理安全性有很多不同的方法,MSDN 有一个很好的指南,可以根据您的场景相应地配置您的安全性。这是该页面的link

所以我更新的例子和上面基本一样,只是客户端创建了一个WSHttpBinding而不是BasicHttpBinding,并指定了消息级别的安全性作为SecurityMode。

static void Main(string[] args)
{
    //refresh the appSettings section
    ConfigurationManager.RefreshSection("appSettings");

    //this could come from app.configs appSettings (value = "http://localhost:8000/ServiceModelSamples/Service/CalculatorService")
    Uri calcService = new Uri(ConfigurationManager.AppSettings["uri"]);

    //create the WsHttpBinding and set some security settings for the transport...
    WSHttpBinding calcBinding = new WSHttpBinding(SecurityMode.Message);
    EndpointAddress calcEndpoint = new EndpointAddress(calcService.AbsoluteUri);


    CalculatorClient calcClient = new CalculatorClient(calcBinding, calcEndpoint);
    double sum = calcClient.Add(10, 20);
    double difference = calcClient.Subtract(sum, 10);

    Console.WriteLine("10 + 20 = {0}", sum.ToString());
    Console.WriteLine("{0} - 10 = {1}", sum.ToString(), difference.ToString());

    Console.ReadLine();
}

我在服务器上所做的唯一区别是我在添加服务端点时指定了 WSHttpBinding。同样,我选择了绑定默认值,但上面的 MSDN 链接将描述如何根据您的安全需求配置服务器。

// Step 3 of the hosting procedure: Add a service endpoint.
selfHost.AddServiceEndpoint(
    typeof(ICalculator),
    new WSHttpBinding(),
    "CalculatorService");

我希望这会有所帮助!请记住,您可以在 WCF 配置中执行的任何操作都可以在代码中执行。配置设置和代码之间存在 1:1 的关系(基本上,配置中的所有内容都会转换为您可以使用的某个 WCF 类)。

祝你好运!如果还有其他问题,请告诉我。

【讨论】:

  • 我已经得到了这个大部分工作,但有几个 cmets - 首先,我尝试了第一个 #1,但它没有工作(这是我链接到的另一个主题)这对我的需求来说太不灵活了。据说这无论如何都是一个糟糕的解决方案,因为它需要我的可执行文件以管理员权限运行。我也尝试了您的解决方案,但遇到了一些问题 - 请参见上文。感谢您的持续帮助! +
  • 我更新了答案以显示我对服务端点实现所做的更改。抱歉,如果我不清楚这一点 - 并不意味着混淆。我想让它超级简单。
  • 我认为您没有完全理解我的问题。我已经设置了一个服务主机,我可以通过使用服务引用和 app.config 文件的客户端连接到它。我想要的是能够连接到这种类型的任何服务主机just通过给我的客户它的URI。您的方法在 app.config 文件的端点中查找 URI,这不适用于此方法,因为我的客户端应用程序不知道存在哪些端点 - 端点 URI 将由用户输入。跨度>
  • 我从 app.config 中读取的 URI 只是我认为您正在尝试做的一个示例 - 所以也许我不明白这一点。但该 URI 不必来自 app.config - 它可以来自自定义 XML 文件、数据库、用户键入的文本框等。只需使用输入源创建 Uri - Uri calcService = new Uri(txtUri.Text);。如果我还是不明白,我很抱歉。
  • 或者你可以这样做,直接用字符串设置端点 -- EndpointAddress calcEndpoint = new EndpointAddress(txtUri.Text);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多