Silverlight动态跨域调用WCF Ria Service

Silverlight跨域调用服务层的WCF Ria Service,但有个不完美的地方:Silverlight客户端添加WCF Ria Service的服务引用是死的,部署的时候怎么办?也就是WCF Ria Service的地址必须是可配置的,动态的。

本文给出解决方案。Silverlight客户端添加WCF Ria Service的服务引用后,会自动生成一个ServiceReferences.ClientConfig文件,内容大致如下:

 
  1. <configuration>
  2.     <system.serviceModel>
  3.         <bindings>
  4.             <customBinding>
  5.                 <binding name="CustomBinding_SLEnalbedWcfService1">
  6.                     <binaryMessageEncoding />
  7.                     <httpTransport maxReceivedMessageSize="2147483647"
  8.  maxBufferSize="2147483647" />
  9.                 </binding>
  10.             </customBinding>
  11.         </bindings>
  12.         <client>
  13.             <endpoint address="http://localhost:7236/SLEnalbedWcfService1.svc"
  14.                 binding="customBinding" bindingConfiguration=
  15. "CustomBinding_SLEnalbedWcfService1"
  16.                 contract="ServiceReference1.SLEnalbedWcfService1" 
  17. name="CustomBinding_SLEnalbedWcfService1" />
  18.         </client>
  19.     </system.serviceModel>
  20. </configuration> 
<configuration>

    <system.serviceModel>

        <bindings>

            <customBinding>

                <binding name="CustomBinding_SLEnalbedWcfService1">

                    <binaryMessageEncoding />

                    <httpTransport maxReceivedMessageSize="2147483647"
 maxBufferSize="2147483647" />

                </binding>

            </customBinding>

        </bindings>

        <client>

            <endpoint address="http://localhost:7354/SLEnalbedWcfService1.svc"

                binding="customBinding" bindingConfiguration=
"CustomBinding_SLEnalbedWcfService1"

                contract="ServiceReference1.SLEnalbedWcfService1" 
name="CustomBinding_SLEnalbedWcfService1" />

        </client>

    </system.serviceModel>

</configuration> 

 里面就有写死的endpoint地址,如果我们要动态设置服务地址,这个文件必须要干掉。OK,首先在VS2010中删除这个文件,然后运行下,肯定报错,没关系,我们首先建立服务工具类:ServiceUtil.cs,代码如下:

 
  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11.  
  12. using SilverlightApplication1.ServiceReference1;
  13. using System.ServiceModel;
  14.  
  15. namespace SilverlightApplication1
  16. {
  17.     public class ServiceUtil
  18.     {
  19.         public static SLEnalbedWcfService1Client GetServiceClient()
  20.         {
  21.             BasicHttpBinding binding = new BasicHttpBinding(
  22.                 Application.Current.Host.Source.Scheme.Equals("https",
  23.  StringComparison.InvariantCultureIgnoreCase)
  24.                 ? BasicHttpSecurityMode.Transport : 
  25. BasicHttpSecurityMode.None);
  26.             binding.MaxReceivedMessageSize = int.MaxValue;
  27.             binding.MaxBufferSize = int.MaxValue;
  28.             return new SLEnalbedWcfService1Client(binding, new EndpointAddress(
  29.                 new Uri("http://localhost:7326/SLEnalbedWcfService1.svc*这个地址可以从配置文件读取*/, UriKind.Absolute))); //cross domain 
  30. "
  31. /
  32.             //new Uri(Application.Current.Host.Source, 
  33. "../SLEnalbedWcfService1.svc")));  //non-cross domain
  34.         }
  35.     }
  36. }
using System;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Ink;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

 
using SilverlightApplication1.ServiceReference1;

using System.ServiceModel;

 
namespace SilverlightApplication1

{

    public class ServiceUtil

    {

        public static SLEnalbedWcfService1Client GetServiceClient()

        {

            BasicHttpBinding binding = new BasicHttpBinding(

                Application.Current.Host.Source.Scheme.Equals("https",
 StringComparison.InvariantCultureIgnoreCase)

                ? BasicHttpSecurityMode.Transport : 
BasicHttpSecurityMode.None);

            binding.MaxReceivedMessageSize = int.MaxValue;

            binding.MaxBufferSize = int.MaxValue;

            return new SLEnalbedWcfService1Client(binding, new EndpointAddress(

                new Uri("http://localhost:7326/SLEnalbedWcfService1.svc*这个地址可以从配置文件读取*/, UriKind.Absolute))); //cross domain 
"
/
            //new Uri(Application.Current.Host.Source, 
"../SLEnalbedWcfService1.svc")));  //non-cross domain

        }

    }

}

然后用这个东东来实例化Service,代码:

 
  1. SLEnalbedWcfService1Client client =
  2.      ServiceUtil.GetServiceClient();
SLEnalbedWcfService1Client client =

     ServiceUtil.GetServiceClient();

运行一下,看看有没有错,如果有错,The remote server returned an error: NotFound. 看看原因在哪,然后看看是不是这个错误: The client and service bindings may be mismatched. 注意,跨域crossdomain.xml在服务端要有啊,或者clientaccesspolicy.xml也可以。

OK,如果你没有问题了,那就达到我们的目的了。注意:刚开始我们还是要添加web service引用的,否则得不到服务端WCF Ria Service接口类型,我们能动态配置的仅仅是服务端地址。(如果你WCF Ria Service的接口,svc名字等等都改了,那就要重新编译了。)

现在我们测试一下动态配置服务地址,假设我们的WCF Ria Service 移到另一个地址了。

如何模拟:在WCF Ria Service 的web application的项目属性里面的web属性页,修改一下port即可。

我们原来是自动分配的,7344端口,现在我们改为7355端口,svc地址也修改了。看看能不能动态调用WCF Ria Service呢。自己看看就ok了。

另:ServiceUtil类可以用generic(泛型)和反射 改良一下(老外原文):

 
  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11. using System.Reflection;
  12. using System.ServiceModel;
  13. namespace SilverlightApplication1
  14. {
  15.     /// <summary>
  16.     /// sample:
  17.     /// var client = ServiceUtil<serviceNamespace.SLEnalbedWcfService1Client>.GetInstance(ServiceType.Service1svc);
  18.     /// </summary>
  19.     /// <typeparam name="T"></typeparam>
  20.     public class ServiceUtil<T> where T : class
  21.     {
  22.         /// <summary>
  23.         /// Service types
  24.         /// </summary>
  25.         public enum ServiceType
  26.         {
  27.             Service1svc
  28.         }
  29.         /// <summary>  
  30.         /// Create a service instance
  31.         /// </summary>  
  32.         /// <param name="serviceType"></param>  
  33.         /// <returns></returns>  
  34.         public static T GetInstance(ServiceType serviceType)
  35.         {
  36.             T _instance = null;
  37.             string serviceUri = GetServiceAddress(serviceType);
  38.             if (string.IsNullOrEmpty(serviceUri)) return null;
  39.             object[] paras = new object[2];
  40.             BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
  41.             binding.MaxBufferSize = int.MaxValue;
  42.             binding.MaxReceivedMessageSize = int.MaxValue;
  43.             EndpointAddress address = new EndpointAddress(new Uri(serviceUri, UriKind.Absolute));
  44.             paras[0] = binding;
  45.             paras[1] = address;
  46.             ConstructorInfo constructor = null;
  47.             try
  48.             {
  49.                 Type[] types = new Type[2];
  50.                 types[0] = typeof(System.ServiceModel.Channels.Binding);
  51.                 types[1] = typeof(System.ServiceModel.EndpointAddress);
  52.                 constructor = typeof(T).GetConstructor(types);
  53.             }
  54.             catch (Exception)
  55.             {
  56.                 return null;
  57.             }
  58.             if (constructor != null)
  59.                 _instance = (T)constructor.Invoke(paras);
  60.             return _instance;
  61.         }
  62.         /// <summary>  
  63.         /// Get service address
  64.         /// </summary>  
  65.         /// <param name="serviceType"></param>  
  66.         /// <returns></returns>  
  67.         public static string GetServiceAddress(ServiceType serviceType)
  68.         {
  69.             return "http://localhost:7354/SLEnalbedWcfService1.svc";//get from app.config is also ok
  70.         }
  71.     }
  72. }
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Reflection;
using System.ServiceModel;

namespace SilverlightApplication1
{
    /// <summary>
    /// sample:
    /// var client = ServiceUtil<serviceNamespace.SLEnalbedWcfService1Client>.GetInstance(ServiceType.Service1svc);
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ServiceUtil<T> where T : class
    {
        /// <summary>
        /// Service types
        /// </summary>
        public enum ServiceType
        {
            Service1svc
        }

        /// <summary>  
        /// Create a service instance
        /// </summary>  
        /// <param name="serviceType"></param>  
        /// <returns></returns>  
        public static T GetInstance(ServiceType serviceType)
        {
            T _instance = null;
            string serviceUri = GetServiceAddress(serviceType);
            if (string.IsNullOrEmpty(serviceUri)) return null;

            object[] paras = new object[2];
            BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
            binding.MaxBufferSize = int.MaxValue;
            binding.MaxReceivedMessageSize = int.MaxValue;
            EndpointAddress address = new EndpointAddress(new Uri(serviceUri, UriKind.Absolute));

            paras[0] = binding;
            paras[1] = address;

            ConstructorInfo constructor = null;

            try
            {
                Type[] types = new Type[2];
                types[0] = typeof(System.ServiceModel.Channels.Binding);
                types[1] = typeof(System.ServiceModel.EndpointAddress);

                constructor = typeof(T).GetConstructor(types);
            }
            catch (Exception)
            {
                return null;
            }

            if (constructor != null)
                _instance = (T)constructor.Invoke(paras);

            return _instance;
        }

        /// <summary>  
        /// Get service address
        /// </summary>  
        /// <param name="serviceType"></param>  
        /// <returns></returns>  
        public static string GetServiceAddress(ServiceType serviceType)
        {
            return "http://localhost:7354/SLEnalbedWcfService1.svc";//get from app.config is also ok
        }
    }

}

原文地址:www.cnblogs.com/Mainz/archive/2011/02/22/1961381.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值