• Silverlight有限支持WCF的binding问题


    这是最近遇到的一个小问题。情况是这样的:

    1.我们有一个网站,是用.NET Framework 3.5编写的,里面有一些WCF的服务。作为演示,我下面有一个范例服务

    合约

    using System.ServiceModel;
    
    namespace WebApplication1
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            void DoWork();
    
            [OperationContract]
            string Helloworld();
        }
    }
    

    服务

    namespace WebApplication1
    {
        // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
        public class Service1 : IService1
        {
            public void DoWork()
            {
            }
    
    
            public string Helloworld()
            {
                return "hello,world";
            }
        }
    }
    

    2.我们需要在一个新的Silverlight应用程序中访问这些WCF服务,但是无论我们选择Silverlight的版本是3.0,还是4.0(注意,这不是.NET Framework的版本),都无法完成服务引用。

    具体的症状就是,添加引用之后,Silverlight无法正确生成那个配置文件

    image

    会有两个警告

    image

    具体的信息是

    Warning    2    Custom tool warning: No endpoints compatible with Silverlight 3 were found. The generated client class will not be usable unless endpoint information is provided via the constructor.    d:\temp\WebApplication1\SilverlightApplication1\Service References\DataModel\Reference.svcmap    1    1    SilverlightApplication1

    然后,我们去看那个生成的配置文件的话,会看到一片空白

    image

    这样的问题要怎么解决呢?我们首先要把问题找到,从上面的错误消息,它的意思应该是说,不支持目前提供的EndPoint。

    那么,服务端到底使用了什么样的EndPoint呢

    我们转到web应用程序中的web.config文件,可以看到如下的设置

        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="WebApplication1.Service1Behavior">
                        <serviceMetadata httpGetEnabled="true" />
                        <serviceDebug includeExceptionDetailInFaults="false" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="WebApplication1.Service1Behavior"
                    name="WebApplication1.Service1">
                    <endpoint address="" binding="wsHttpBinding" contract="WebApplication1.IService1">
                        <identity>
                            <dns value="localhost" />
                        </identity>
                    </endpoint>
                    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                </service>
            </services>
        </system.serviceModel>

    也就是说,默认情况下,.NET Framework 3.5提供的WCF,是使用wsHttpBinding的。难道是Silverlight不支持这种EndPoint吗?

    为了做测验,我们可以将其修改为相对简单的basicHttpBinding

        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="WebApplication1.Service1Behavior">
                        <serviceMetadata httpGetEnabled="true" />
                        <serviceDebug includeExceptionDetailInFaults="false" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="WebApplication1.Service1Behavior"
                    name="WebApplication1.Service1">
                    <endpoint address="" binding="basicHttpBinding" contract="WebApplication1.IService1">
                        <identity>
                            <dns value="localhost" />
                        </identity>
                    </endpoint>
                    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                </service>
            </services>
        </system.serviceModel>


    然后,我们再去Silverlight中添加引用看看是否能解决问题

    image

    我们发现,这次成功了,ClientConfig中也正确生成了WCF的配置,并且通过如下的代码可以完成服务的调用

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.ServiceModel;
    
    namespace SilverlightApplication1
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                var proxy = new DataModel.Service1Client();
                proxy.Endpoint.Address = new EndpointAddress(new Uri(Application.Current.Host.Source, "../Service1.svc"));
    
    
                proxy.HelloworldCompleted += (o, a) =>
                {
                    MessageBox.Show(a.Result);
                };
    
    
                proxy.HelloworldAsync();
                
            }
        }
    }
    

    好的,看起来问题是解决了,也就是说Silverlight只支持使用basicHttpBinding?如果我们非要改成wsHttpBinding ,行不行呢?

    我尝试将clientconfig文件修改为

    <configuration>
        <system.serviceModel>
            <client>
                <endpoint address="http://localhost:2514/Service1.svc" binding="wsHttpBinding" contract="DataModel.IService1"
                    name="BasicHttpBinding_IService1" />
            </client>
        </system.serviceModel>
    </configuration>
    

    并且将服务端的web.config,也修改为

        <system.serviceModel>
            <behaviors>
                <serviceBehaviors>
                    <behavior name="WebApplication1.Service1Behavior">
                        <serviceMetadata httpGetEnabled="true" />
                        <serviceDebug includeExceptionDetailInFaults="false" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <services>
                <service behaviorConfiguration="WebApplication1.Service1Behavior"
                    name="WebApplication1.Service1">
                    <endpoint address="" binding="wsHttpBinding" contract="WebApplication1.IService1">
                        <identity>
                            <dns value="localhost" />
                        </identity>
                    </endpoint>
                    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
                </service>
            </services>
        </system.serviceModel>

    运行程序的结果是,会报告如下的错误

    image

    也就是说,确实不支持wsHttpBinding

     

    关于这一点,有兴趣的朋友,也可以参考一下微软官方的文档说明

    http://msdn.microsoft.com/en-us/library/cc896571(v=VS.95).aspx

    【又及】

    在Silverlight中,最简单易用的服务是RIA Service,关于这一点,我已经写过很多文章介绍。

    那么,RIA Service是使用什么binding呢?

    请参考下面这篇文章

    http://weblogs.asp.net/fredriknormen/archive/2009/11/27/wcf-ria-services-binding-deep-dive.aspx

  • 相关阅读:
    从多渠道打包与友盟统计有这一篇就够了
    多渠道打包
    studio构建错误Element uses-permission#android.permission.ACCESS_NETWORK_STATE at AndroidManifest.xml:38:5-79 dupli
    ADB命令与monkey
    正则表达式和文本挖掘(Text Mining)
    一步一步教你使用Git
    Android常见开源解决方案
    Android Intent到底能做些什么
    支付宝集成
    Theano 学习三 conv2d
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/2084524.html
Copyright © 2020-2023  润新知