none
Android不能象Windows桌面那样使用WCF吗? RRS feed

  • 问题

  • 最近在入门Android,用的是VS2017 社区版15.6.0,建立了非常简单的测试App,但在调用WCF代理请求数据时,总是提示错误:

    Unhandled Exception:

    System.ServiceModel.FaultException`1[[System.ServiceModel.ExceptionDetail, System.ServiceModel, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: 对操作“GetData”的请求消息正文进行反序列化时出现错误。OperationFormatter 遇到无效的消息正文。需要查找名称为“GetData”、命名空间为“http://tempuri.org/”的节点类型“Element”。找到名称为“GetDataAsync”、命名空间为“http://tempuri.org/”的节点类型“Element” 出现了

    共3个项目:WCF服务、.Net Standard代理类库、Android,基本上完全采用系统默认生成的代码

    WCF项目WcfService:

    1、App.config

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" />
      </system.web>
      <!-- 部署服务库项目时,必须将配置文件的内容添加到
     主机的 app.config 文件中。System.Configuration 不支持库的配置文件。 -->
      <system.serviceModel>
        <services>
          <service name="WcfService.Service1">
            <host>
              <baseAddresses>
                <add baseAddress = "http://10.0.0.18:8733/Design_Time_Addresses/WcfService/Service1/" />
              </baseAddresses>
            </host>
            <!-- Service Endpoints -->
            <!-- 除非完全限定,否则地址相对于上面提供的基址-->
            <endpoint address="" binding="basicHttpBinding" contract="WcfService.IService1">
              <!--
                  部署时,应删除或替换下列标识元素,以反映
                 用来运行所部署服务的标识。删除之后,WCF 将
                  自动推断相应标识。
              -->
              <identity>
                <dns value="10.0.0.18"/>
              </identity>
            </endpoint>
            <!-- Metadata Endpoints -->
            <!-- 元数据交换终结点供相应的服务用于向客户端做自我介绍。 -->
            <!-- 此终结点不使用安全绑定,应在部署前确保其安全或将其删除-->
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior>
              <!-- 为避免泄漏元数据信息,
              请在部署前将以下值设置为 false -->
              <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
              <!-- 要接收故障异常详细信息以进行调试,
              请将以下值设置为 true。在部署前设置为 false
              以避免泄漏异常信息 -->
              <serviceDebug includeExceptionDetailInFaults="True" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
      </system.serviceModel>

    </configuration>

    2、IService:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    namespace WcfService
    {
        // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
        [ServiceContract]
        public interface IService1
        {
            [OperationContract]
            string GetData(int value);
            [OperationContract]
            CompositeType GetDataUsingDataContract(CompositeType composite);
            // TODO: 在此添加您的服务操作
        }
        // 使用下面示例中说明的数据约定将复合类型添加到服务操作。
        // 可以将 XSD 文件添加到项目中。在生成项目后,可以通过命名空间“WcfService.ContractType”直接使用其中定义的数据类型。
        [DataContract]
        public class CompositeType
        {
            bool boolValue = true;
            string stringValue = "Hello ";
            [DataMember]
            public bool BoolValue
            {
                get { return boolValue; }
                set { boolValue = value; }
            }

            [DataMember]
            public string StringValue
            {
                get { return stringValue; }
                set { stringValue = value; }
            }
        }
    }

    3、Service:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    namespace WcfService
    {
        // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“Service1”。
        public class Service1 : IService1
        {
            public string GetData(int value)
            {
                return string.Format("You entered: {0}", value);
            }
            public CompositeType GetDataUsingDataContract(CompositeType composite)
            {
                if (composite == null)
                {
                    throw new ArgumentNullException("composite");
                }
                if (composite.BoolValue)
                {
                    composite.StringValue += "Suffix";
                }
                return composite;
            }
        }
    }

    .Net Standard类库WcfProxy:

    //------------------------------------------------------------------------------
    // <自动生成>
    //     此代码由工具生成。
    //     //
    //     对此文件的更改可能导致不正确的行为,并在以下条件下丢失:
    //     代码重新生成。
    // </自动生成>
    //------------------------------------------------------------------------------

    namespace WcfServiceProxy
    {
        using System.Runtime.Serialization;


        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
        [System.Runtime.Serialization.DataContractAttribute(Name="CompositeType", Namespace="http://schemas.datacontract.org/2004/07/WcfService")]
        public partial class CompositeType : object
        {

            private bool BoolValueField;

            private string StringValueField;

            [System.Runtime.Serialization.DataMemberAttribute()]
            public bool BoolValue
            {
                get
                {
                    return this.BoolValueField;
                }
                set
                {
                    this.BoolValueField = value;
                }
            }

            [System.Runtime.Serialization.DataMemberAttribute()]
            public string StringValue
            {
                get
                {
                    return this.StringValueField;
                }
                set
                {
                    this.StringValueField = value;
                }
            }
        }

        [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
        [System.ServiceModel.ServiceContractAttribute(ConfigurationName="WcfServiceProxy.IService1")]
        public interface IService1
        {

            [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetData", ReplyAction="http://tempuri.org/IService1/GetDataResponse")]
            System.Threading.Tasks.Task<string> GetDataAsync(int value);

            [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetDataUsingDataContract", ReplyAction="http://tempuri.org/IService1/GetDataUsingDataContractResponse")]
            System.Threading.Tasks.Task<WcfServiceProxy.CompositeType> GetDataUsingDataContractAsync(WcfServiceProxy.CompositeType composite);
        }

        [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
        public interface IService1Channel : WcfServiceProxy.IService1, System.ServiceModel.IClientChannel
        {
        }

        [System.Diagnostics.DebuggerStepThroughAttribute()]
        [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.0")]
        public partial class Service1Client : System.ServiceModel.ClientBase<WcfServiceProxy.IService1>, WcfServiceProxy.IService1
        {

        /// <summary>
        /// 实现此分部方法,配置服务终结点。
        /// </summary>
        /// <param name="serviceEndpoint">要配置的终结点</param>
        /// <param name="clientCredentials">客户端凭据</param>
        static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);

            public Service1Client() :
                    base(Service1Client.GetDefaultBinding(), Service1Client.GetDefaultEndpointAddress())
            {
                this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_IService1.ToString();
                ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
            }

            public Service1Client(EndpointConfiguration endpointConfiguration) :
                    base(Service1Client.GetBindingForEndpoint(endpointConfiguration), Service1Client.GetEndpointAddress(endpointConfiguration))
            {
                this.Endpoint.Name = endpointConfiguration.ToString();
                ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
            }

            public Service1Client(EndpointConfiguration endpointConfiguration, string remoteAddress) :
                    base(Service1Client.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
            {
                this.Endpoint.Name = endpointConfiguration.ToString();
                ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
            }

            public Service1Client(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
                    base(Service1Client.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
            {
                this.Endpoint.Name = endpointConfiguration.ToString();
                ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
            }

            public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
                    base(binding, remoteAddress)
            {
            }

            public System.Threading.Tasks.Task<string> GetDataAsync(int value)
            {
                return base.Channel.GetDataAsync(value);
            }

            public System.Threading.Tasks.Task<WcfServiceProxy.CompositeType> GetDataUsingDataContractAsync(WcfServiceProxy.CompositeType composite)
            {
                return base.Channel.GetDataUsingDataContractAsync(composite);
            }

            public virtual System.Threading.Tasks.Task OpenAsync()
            {
                return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
            }

            public virtual System.Threading.Tasks.Task CloseAsync()
            {
                return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
            }

            private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
            {
                if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService1))
                {
                    System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
                    result.MaxBufferSize = int.MaxValue;
                    result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
                    result.MaxReceivedMessageSize = int.MaxValue;
                    result.AllowCookies = true;
                    return result;
                }
                throw new System.InvalidOperationException(string.Format("找不到名称为“{0}”的终结点。", endpointConfiguration));
            }

            private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
            {
                if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IService1))
                {
                    return new System.ServiceModel.EndpointAddress("http://10.0.0.18:8733/Design_Time_Addresses/WcfService/Service1/");
                }
                throw new System.InvalidOperationException(string.Format("找不到名称为“{0}”的终结点。", endpointConfiguration));
            }

            private static System.ServiceModel.Channels.Binding GetDefaultBinding()
            {
                return Service1Client.GetBindingForEndpoint(EndpointConfiguration.BasicHttpBinding_IService1);
            }

            private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
            {
                return Service1Client.GetEndpointAddress(EndpointConfiguration.BasicHttpBinding_IService1);
            }

            public enum EndpointConfiguration
            {

                BasicHttpBinding_IService1,
            }
        }
    }

    Android项目WcfApp:

    MainActivity.cs:

    using Android.App;
    using Android.Widget;
    using Android.OS;
    using System;
    namespace WcfApp
    {
        [Activity(Label = "WcfApp", MainLauncher = true)]
        public class MainActivity : Activity
        {
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);

                // Set our view from the "main" layout resource
                SetContentView(Resource.Layout.Main);
                WcfServiceProxy.Service1Client client = new WcfServiceProxy.Service1Client();

    //下句报错

           string x = client.GetDataAsync(123).Result;
                Console.WriteLine(x);
            }
        }
    }

         

                                                                                                                                                                                                           


    韩立学



    2018年3月7日 6:08

全部回复

  • 推荐用Web API。

    xamrian 也可以用wcf,参考这里

    https://developer.xamarin.com/guides/cross-platform/application_fundamentals/web_services/walkthrough_working_with_WCF/

    Walkthrough - Working with WCF


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2018年3月8日 0:45
  • Hi,

    .Net Standard的代理类库是如何生成的?

    排除是不是Android相关的问题还是代理类库有问题,我建议建一个 Console Application 然后在这个App里面使用代理类库调用WCF服务,会报错么?

    Best Regards,

    Tao Zhou


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月8日 1:43
    版主
  • Hi,

    .Net Standard的代理类库是如何生成的?

    排除是不是Android相关的问题还是代理类库有问题,我建议建一个 Console Application 然后在这个App里面使用代理类库调用WCF服务,会报错么?

    Best Regards,

    Tao Zhou


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    谢谢您的回复!

    代理类库.NET Standard类库,利用系统的添加连接的服务:Microsoft WCF Web Service Reference Provider,按默认选项生成的。

    新建项目:Windows经典桌面——控制台应用——添加服务引用,运行是正常的。当然,它不能用上述.NET Standard类库生成的代理,否则,会报错:

    未能加载文件或程序集“System.ServiceModel.Primitives, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。
    我感到不可理解的是,为什么几乎全部采用系统默认方式,生成的项目及代码,会报错?微软自己都不支持自己?


    韩立学

    2018年3月8日 5:17
  • 推荐用Web API。

    xamrian 也可以用wcf,参考这里

    https://developer.xamarin.com/guides/cross-platform/application_fundamentals/web_services/walkthrough_working_with_WCF/

    Walkthrough - Working with WCF


    专注于.NET ERP/CRM开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    谢谢您的回复!

    我的方案中,Windows桌面程序采用的是WCF,因此,我希望Android也采用WCF,省事。

    您的这个例子,我看过,照它抄下来,也是这个错误,真见鬼了!


    韩立学

    2018年3月8日 5:21
  • >>能加载文件或程序集“System.ServiceModel.Primitives, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。

    对于这个错误,你需要在控制台程序中从NuGet里面安装下面的引用。

    System.ServiceModel.Http
    System.ServiceModel.Primitives

    Best Regards,

    Tao Zhou


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月9日 2:52
    版主
  • >>能加载文件或程序集“System.ServiceModel.Primitives, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a”或它的某一个依赖项。系统找不到指定的文件。

    对于这个错误,你需要在控制台程序中从NuGet里面安装下面的引用。

    System.ServiceModel.Http
    System.ServiceModel.Primitives

    Best Regards,

    Tao Zhou


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    谢谢您的回复!

    添加NuGet包后,运行正常。

    看来是Android有问题,但问题在哪呢?它困扰我多日了!

    项目版本是7.1(7.0也一样),USB连接手机测试,华为HUWEI BLN-AL20(Android 7.0 - API24),未用IIS。


    韩立学



    2018年3月9日 23:45
  • 在运行服务后,Android手机里面打开浏览器,是否能够访问WCF 服务的地址?

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月12日 1:48
    版主
  • 在运行服务后,Android手机里面打开浏览器,是否能够访问WCF 服务的地址?

    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    谢谢您的回复!

    手机浏览器能够访问,显示类似下面的网页(截图来自电脑,手机网页内容与此一致):


    韩立学



    2018年3月12日 4:01
  • https://developer.xamarin.com/guides/cross-platform/application_fundamentals/web_services/walkthrough_working_with_WCF/

    Walkthrough - Working with WCF

    我完全按照这个例子抄下来,都不行!也是请求消息反序列化错误。


    韩立学

    2018年3月12日 4:22
  • 我对于Xamarin开发Anorid不熟悉,建议你去下面的论坛。

    https://forums.xamarin.com/discussions/tagged/msdn/p1


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2018年3月13日 3:06
    版主
  • 问题解决了吗?我也是同一个问题
    2019年3月4日 9:35
  • 不可以吧
    2019年7月27日 9:13