WCF c#中自定义类的传输问题

Posted

技术标签:

【中文标题】WCF c#中自定义类的传输问题【英文标题】:Problems with the transfer of custom class in WCF c# 【发布时间】:2019-10-17 02:25:37 【问题描述】:

我正在服务器和客户端之间传输数据。客户端很容易从服务器接收到常用的数据类型,例如int,但是如果您将自定义类传递给它,则会收到以下异常:

System.ServiceModel.CommunicationException:获取对http://127.0.0.1:8000/Service 的 HTTP 响应时出错。这可能是由于服务端点绑定不使用 HTTP 协议造成的。这也可能是由于 HTTP 请求上下文已被服务器中断(可能是由于服务被禁用)。有关详细信息,请参阅服务器日志。

我尝试了许多解决方案来解决这些问题,但没有任何帮助。 我在类字段中添加了 getter 和 setter,将 DataContract 等更改为 Serializable

自定义类

    namespace c_CardStrategy

    [DataContract]
    public class Card
    
        #region ПОЛЯ
        [DataMember]
        public string Name  get; set; 
        [DataMember]
        public string Effect  get; set; 
        [DataMember]
        public int ID  get; set; 
        [DataMember]
        public int Price  get; set; 
        [DataMember]
        public string EffText  get; set; 
        #endregion
        #region Конструктор
        public Card(int id, string name, string effect, int price, string efftext)
        
            Price = price;
            ID = id;
            Name = name;
            Effect = effect;
            EffText = efftext;
        
        public Card()
        
            Name = "";
            Effect = "";
            ID = 0;
            Price = 0;
            EffText = "";
        
        #endregion
    

    [DataContract]
    public class Moster_Card : Card
    
        [DataMember]
        public int? Health  get; set; 
        [DataMember]
        public int? Power  get; set; 

        public Moster_Card(int id, string name, int? health, int? power, string effect, int price, string efftext) : base(id, name, effect, price, efftext)
        
            Health = health;
            Power = power;
        
        public Moster_Card()
        
            Name = "";
            Effect = "";
            ID = 0;
            Price = 0;
            EffText = "";
            Health = 0;
            Power = 0;
        
    

    [DataContract]
    public class Spell_Card : Card
    
        [DataMember]
        public int? Charge  get; set; 

        public Spell_Card(int id, string name, string effect, int price, string efftext, int? charge) : base(id, name, effect, price, efftext)
        
            Charge = charge;
        
        public Spell_Card()
        
            Name = "";
            Effect = "";
            ID = 0;
            Price = 0;
            EffText = "";
            Charge = 0;
        
    






界面

    [ServiceContract]
        public interface IGame
        
            [OperationContract]
            Players GetPlayer(int grid);

            [OperationContract]
            List<Players> Players();

            [OperationContract]
            int GetTurn(int GameGrid);

            [OperationContract]
            void FindGame(Players Player);

            [OperationContract]
            object GetAllCards();

            [OperationContract]
            List<Card> GetDeckOnCode(string code_deck);

            [OperationContract]
            bool Checkuser(string login, string pass);

            [OperationContract]
            void WriteInLog(string Text);
        


服务器

    namespace c_CardStrategy
    
        [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
        public class GameServer : IGame
        
            private List<Players> listPlayers;
            private List<Game> Games;
            public hpartner_cgEntities context;
            ...
            public object GetAllCards()
            
                context = new hpartner_cgEntities();
                List<Card> Cards = new List<Card>();
                foreach(var Card in context.Cards)
                
                    int id = Card.Card_id;
                    string name = Card.Card_name;
                    int f = Card.Card_eff_id;
                    string eff;
                    switch (f)
                    
                        case 0:
                            eff = "None";
                            break;
                        case 1:
                            eff = "Taunt";
                            break;
                        case 2:
                            eff = "Charge";
                            break;
                        default:
                            eff = "None";
                            break;
                    
                    int price = Card.Card_price;
                    string efftext = Card.Card_eff_text;
                    int? Health = Card.Card_health;
                    int? Power = Card.Card_power;
                    int? Charge = Card.Charge;
                    if (Health != null)
                    
                        Cards.Add(new Spell_Card(id, name, eff, price, efftext, Charge));
                    
                    else
                    
                        Cards.Add(new Moster_Card(id, name, Health, Power, eff, price, efftext));
                    
                
                return Cards;
            
            ...
    
    

客户

    public partial class DecksWindow : Window
        
            private GameClient Client;
            public DecksWindow(GameClient client)
            
                InitializeComponent();
                Client = client;
            

            private void New_deck_Click(object sender, RoutedEventArgs e)
            
                Deck_list.Visibility = Visibility.Visible;
                List<Card> Cards = new List<Card>();
                try
                
                    Cards = Client.GetAllCards() as List<Card>;
                    foreach (Card Card in Cards)
                    
                        StackPanel Sp = new StackPanel();
                        Sp.Height = 170;
                        Sp.Width = 150;
                        Sp.Margin = new Thickness(0, 5, 5, 0);
                        Sp.Background = Brushes.Red;
                        Sp.Tag = Card.IDk__BackingField.ToString();
                        Sp.Uid = 2.ToString();
                        Deck_list.Children.Add(Sp);
                    
                
                catch (Exception ex)
                
                    tb.Text += ex.Message;
                
                //tb.Text = Client.Checkuser("Admin", "Admin").ToString();

            
        

配置客户端

    <configuration>
      <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
      </startup>
      <entityFramework>
        <defaultConnectionFactory type="mysql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6" />
        <providers>
          <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework" />
        </providers>
      </entityFramework>
      <connectionStrings>
        <add name="hpartner_cgEntities" providerName="System.Data.EntityClient" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=MySql.Data.MySqlClient;provider connection string=&quot;server=hpartnerlink.ru;user id=hpartner;password=M7gn46Wx3b;persistsecurityinfo=True;database=hpartner_cg&quot;" />
      </connectionStrings>
      <system.web>
        <httpRuntime maxRequestLength="262144"  executionTimeout="103600"/>
      </system.web>
      <system.serviceModel>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding_IGame" />
            <binding name="BasicHttpBinding_IGame1" />
          </basicHttpBinding>
        </bindings>
        <client>
          <endpoint address="http://127.0.0.1:8000/Service" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IGame" contract="GameServiceReference.IGame"
            name="BasicHttpBinding_IGame" />
          <endpoint address="http://0.0.0.0:8000/Service" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IGame1" contract="ServiceReference1.IGame"
            name="BasicHttpBinding_IGame1" />
        </client>
      </system.serviceModel>

配置服务器

    <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
      </startup>
      <entityFramework>
        <defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6" />
        <providers>
          <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework" />
        </providers>
      </entityFramework>
      <connectionStrings>
        <add name="hpartner_cgEntities" providerName="System.Data.EntityClient" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=MySql.Data.MySqlClient;provider connection string=&quot;server=hpartnerlink.ru;user id=hpartner;password=M7gn46Wx3b;persistsecurityinfo=True;database=hpartner_cg&quot;" />
      </connectionStrings>
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="debug">
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <services>
          <service name="MyServiceName" behaviorConfiguration="debug" />
        </services>
      </system.serviceModel>

【问题讨论】:

您的Card 类必须是DataContract,以便您可以在客户端看到class。每个属性也需要DataMember 属性。请注意,我从未在WCF 服务中使用过派生类,所以我不确定派生类是否也需要DataContract,但我相信它也应该拥有它。 @Franck,已经这样做了,但没有帮助[DataContract] public class Card #region ПОЛЯ [DataMember] public string Name get; set; [DataMember] public string Effect get; set; ... 我知道这对您的错误没有帮助。但是您的代码将需要它在客户端工作,因为您具有该对象的返回类型。如果类不是DataContractDataMember,它将不起作用。您的错误是与您的绑定有关的通信错误。您需要将您的 web.config 添加到帖子中,以便有人可以提供帮助。 @Franck,更新了主题,添加了配置。感谢您的提示 我怀疑你的服务器正在使用你的客户端正在使用的 basicHttpBinding。 【参考方案1】:

您可以在托管服务后访问 Web 服务的 WSDL 吗? 我怀疑配置可能太简单了。我建议您在服务器端应用以下配置。

  <system.serviceModel>
    <services>
      <service name="YourNamespace.GameServer " behaviorConfiguration="mybehavior">
        <endpoint address="http://localhost:8000/Service" binding="basicHttpBinding" contract="YourNamespace.IGame " ></endpoint>
        <endpoint address="http://localhost:8000/Service/mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
      </service>
    </services>    
    <behaviors>
      <serviceBehaviors>
        <behavior name="mybehavior">
          <serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

托管服务后,我们可以通过在浏览器地址栏中输入服务地址来访问服务信息。

http://localhost:8000/service

此外,我们在托管服务时可能需要管理权限。 如果问题仍然存在,请随时告诉我。

【讨论】:

以上是关于WCF c#中自定义类的传输问题的主要内容,如果未能解决你的问题,请参考以下文章

支持嵌套类型中自定义类的默认序列化

Qt中自定义类的方法

python中自定义函数类的引用(最全)

WCF,将数据传递给服务类的自定义授权

Jmeter中自定义JavaSamplerClient类的编写

UITableViewCell 中自定义 UIView 的 drawRect 行为错误