【问题标题】:Dynamic proxy creation issues with maximum message size最大消息大小的动态代理创建问题
【发布时间】:2012-07-09 04:51:26
【问题描述】:

我正在创建 wcf 服务的 dyanminc 代理,而不使用 MetadataExchenge 类添加对客户端代码的引用。问题是当我加载小型 wcf 服务的元数据时,例如只有 1 或 2 个方法,代码对我来说很好,但是当我尝试加载具有大约 70 到 80 个方法的大型 wcf 服务的元数据时,我收到最大消息大小的错误其中一个端点已超过 65536...尽管我已将 wcf 配置中的所有大小变量都设置为最大值...我的客户端 web.config 文件中没有任何内容...我得到了所有运行时的绑定...有人可以帮忙吗?

【问题讨论】:

  • 您需要在客户端将 readerQuotas 设置为较大的值。您还可以通过编程方式设置 readerQuotas。
  • 如何设置 MetadataExchangeClient 类没有作为 readerQuota 的公共属性??
  • 您如何从客户端调用您的 WCF 服务?您是否在配置中定义了绑定,或者您是否通过代码创建绑定的实例
  • 不,我在客户端的 web 配置文件中没有任何东西都是在运行时生成的,我已经发布了代码顺便说一句

标签: .net wcf c#-4.0


【解决方案1】:

您在客户端 web.config 上没有任何东西,因为您正试图从代码中使用 Web 服务?

考虑到您正在使用 WsHttpBinding 来使用服务,请使用以下代码来增加 MaxRecievedMessageSize 属性。

System.ServiceModel.WSHttpBinding binding = new System.ServiceModel.WSHttpBinding(System.ServiceModel.SecurityMode.None);

// Increase the message size
binding.MaxReceivedMessageSize = 50000000;

System.ServiceModel.Description.MetadataExchangeClient mexClient = new System.ServiceModel.Description.MetadataExchangeClient(binding);
System.ServiceModel.Description.MetadataSet mexResult = mexClient.GetMetadata(new System.ServiceModel.EndpointAddress("http://someurl:someport/some"));

foreach (System.ServiceModel.Description.MetadataSection section in mexResult.MetadataSections)
{
                Console.WriteLine (section.Identifier);
                Console.WriteLine (section.Metadata.GetType());
                Console.WriteLine ();
}
Console.ReadLine();

如果这不能解决您的问题,请您发布代码以进行进一步分析。

【讨论】:

  • 嗨,我已经尝试过了,但出现了类似“内容类型应用程序/soap+xml;charset=utf-8 不受服务 http://##.##.# 支持的错误。 ###:8732/WCFTestService/Service1/?wsdl。客户端和服务绑定可能不匹配。”顺便说一句,我在 wcf 服务配置上使用 basicHttpBinding
  • 好的,我给出的示例使用了 WSHttpBinding。将其更改为使用 BasicHttpBinding。那么它会工作......
【解决方案2】:

您可以在客户端添加以下代码来设置 readerQuotas,如下所示:

            var binding = se.Binding as BasicHttpBinding;
            binding.MaxBufferSize = 2147483647;
            binding.MaxReceivedMessageSize= 2147483647;
            binding.MaxBufferPoolSize = 2147483647;
            XmlDictionaryReaderQuotas myReaderQuotas = new XmlDictionaryReaderQuotas();
            myReaderQuotas.MaxStringContentLength = 2147483647;
            myReaderQuotas.MaxNameTableCharCount = 2147483647;
            myReaderQuotas.MaxArrayLength= 2147483647;
            myReaderQuotas.MaxBytesPerRead= 2147483647;
            myReaderQuotas.MaxDepth=64;                
            binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);

上述代码需要在创建代理实例之前设置。

【讨论】:

    【解决方案3】:

    我生成 wcf 客户端的代码如下

     try
                {
    
    
                Uri mexAddress = new Uri("http://##.##.#.###:8732/WCFTestService/Service1/?wsdl");
                //MetadataSet metaSet1 = MEC.GetMetadata(new EndpointAddress(mexAddress));
                // For MEX endpoints use a MEX address and a 
                // mexMode of .MetadataExchange
                MetadataExchangeClientMode mexMode = MetadataExchangeClientMode.MetadataExchange;
    
                string contractName = "IVehicleservice";
                string operationName = "ProcessNotification";
                object[] operationParameters = new object[] { 1 };
    
                 //Get the metadata file from the service.
                MetadataExchangeClient mexClient = new MetadataExchangeClient(mexAddress, mexMode);
    
                mexClient.ResolveMetadataReferences = true;
                mexClient.MaximumResolvedReferences = 100;
    
                MetadataSet metaSet = mexClient.GetMetadata();
    
    
                // Import all contracts and endpoints
                WsdlImporter importer = new WsdlImporter(metaSet);
    
                Collection<ContractDescription> contracts =
                  importer.ImportAllContracts();
                ServiceEndpointCollection allEndpoints = importer.ImportAllEndpoints();
    
                // Generate type information for each contract
                ServiceContractGenerator generator = new ServiceContractGenerator();
                var endpointsForContracts =
           new Dictionary<string, IEnumerable<ServiceEndpoint>>();
    
                foreach (ContractDescription contract in contracts)
                {
                    generator.GenerateServiceContractType(contract);
                    // Keep a list of each contract's endpoints
                    endpointsForContracts[contract.Name] = allEndpoints.Where(
                        se => se.Contract.Name == contract.Name).ToList();
                }
    
                if (generator.Errors.Count != 0)
                    throw new Exception("There were errors during code compilation.");
    
                // Generate a code file for the contracts 
                CodeGeneratorOptions options = new CodeGeneratorOptions();
                options.BracingStyle = "C";
                CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("C#");
    
                // Compile the code file to an in-memory assembly
                // Don't forget to add all WCF-related assemblies as references
                CompilerParameters compilerParameters = new CompilerParameters(
                    new string[] { 
                        "System.dll", "System.ServiceModel.dll", 
                        "System.Runtime.Serialization.dll" });
                compilerParameters.GenerateInMemory = true;
    
                CompilerResults results = codeDomProvider.CompileAssemblyFromDom(
                    compilerParameters, generator.TargetCompileUnit);
    
                if (results.Errors.Count > 0)
                {
                    throw new Exception("There were errors during generated code compilation");
    
                }
                else
                {
                    // Find the proxy type that was generated for the specified contract
                    // (identified by a class that implements 
                    // the contract and ICommunicationbject)
                    Type clientProxyType = results.CompiledAssembly.GetTypes().First(
                        t => t.IsClass &&
                            t.GetInterface(contractName) != null &&
                            t.GetInterface(typeof(ICommunicationObject).Name) != null);
    
                    // Get the first service endpoint for the contract
                    ServiceEndpoint se = endpointsForContracts[contractName].First();
    
                    // Create an instance of the proxy
                    // Pass the endpoint's binding and address as parameters
                    // to the ctor
                    object instance = results.CompiledAssembly.CreateInstance(
                       clientProxyType.Name,
                        false,
                        System.Reflection.BindingFlags.CreateInstance,
                        null,
                        new object[] { se.Binding, se.Address },
                        CultureInfo.CurrentCulture, null);
    
                    // Get the operation's method, invoke it, and get the return value
    
                    //object retVal = instance.GetType().GetMethod(operationName).
                    //    Invoke(instance, operationParameters);
    
                    object retVal = instance.GetType().GetMethod(operationName).
                        Invoke(instance, operationParameters);
                    Console.WriteLine(retVal.ToString());
    
                    Console.ReadLine();
                }
            }
            catch(Exception ex)
            { 
    
            }
    

    【讨论】:

    • 你知道什么绑定与服务器上的端点相关联吗?是 basicHttpBinding 还是 wsHttpBinding 还是 netTcpBinding?
    • 假设您使用上面 cmets 中的 BasicHttpBinding 我发布了代码以编程方式设置 readerQuotas
    猜你喜欢
    • 2016-06-01
    • 2019-03-26
    • 2010-09-27
    • 2014-06-13
    • 2011-08-06
    • 1970-01-01
    • 2020-05-13
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多