初识wcf

WCF是构建和运行互联系统的一系列技术的总称,它是建立在Web Service架构上的一个全新的通信平台。你可以把它看成是.NET平台上的新一代的Web Service。WCF为我们提供了安全、可靠的的消息通信,也为我们提供了更好的可互操作性是的我们可以和其他的平台进行“交流”。

 

下面介绍两种方式建立wcf服务器端:

 

 

 

当使用方式二建立的服务端在本机上运行一点问题都没有,但当服务端移植到远程服务器上就会报异常

未经处理的异常: System.ServiceModel.Security.SecurityNegotiationException: 调用 方未由服务进行身份验证。

 

解决方案参考:https://blog.csdn.net/zxy13826134783/article/details/85267969

 

 

 

2020年6月12日补充

遇到的需求:

1  WCF服务端需要使用配置文件的方式启动,同时方便调试(即客户端启动调试时能进入WCF服务端调试)

2   数据格式需要传递实体对象

 

解决方案结构:

涉及到的DLL引用:

System.ServiceModel.dll

System.Runtime.Serialization.dll

 

一  WCF服务端配置

要实现方便调试(即客户端启动调试时能进入WCF服务端调试)的需求,需要新建一个空的ASP.NET网站项目

1.1  WCF服务端实体类:

namespace WpfApplication2
{
    public class CodeDterm
    {
        public int CodeDtErmId { set; get; }

        public string Name { set; get; }

        public string Description { set; get; }
    }
}

  

namespace WpfApplication2
{
    public class CodeDtErmValue
    {
        public int CodeDtErmId { set; get; }

        public int CodeId { set; get; }

        public int Code { set; get; }

        public string DisplayName { set; get; }
    }
}

1.2  查询Oracle数据库相关类(数据库的连接字符串对于的配置文件在后面),至于如何查询数据库数据,不是重点

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Windows;
using System.Data;

namespace WpfApplication2
{
    public class DapperHelper
    {
        private static string ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;


        /// <summary>
        /// 获取读取器
        /// </summary>
        /// <returns></returns>
        public static OracleDataReader GetReader(string sql) {
            OracleConnection conn = new OracleConnection(ConnectionString);
            OracleCommand cmd = new OracleCommand(sql, conn);
            try
            {
                conn.Open();
                return cmd.ExecuteReader(CommandBehavior.CloseConnection);
            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCFService
{
    public class CodeDtermService
    {
        public List<CodeDterm> GetCodeDterm(string KeyWord) {
            string sql = "";
            if (KeyWord.Length==0)
            {
                sql = "select CodeDtErmId,Name,Description from Concept.Codedterm";
            }
            else
            {
                sql = "select CodeDtErmId,Name,Description from Concept.Codedterm where Description like '%{0}%'";
            }
            
            sql = string.Format(sql, KeyWord);

            List<CodeDterm> CodeDtermList = null;
            OracleDataReader reader = null;
            try
            {
                reader = DapperHelper.GetReader(sql);
                CodeDtermList = new List<CodeDterm>();
                while (reader.Read())
                {
                    CodeDtermList.Add(new CodeDterm() {

                         CodeDtErmId=Convert.ToInt32(reader["CodeDtErmId"]),
                         Name=reader["Name"].ToString(),
                         Description=reader["Description"].ToString()
                    });

                }
                return CodeDtermList;
            }
            catch (Exception)
            {

                throw;
            }
            finally {
                if (reader != null)
                {
                    reader.Close();
                }
            }
           
          
        }
    }
}
using Oracle.ManagedDataAccess.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCFService
{
    public class CodeDtErmValueService
    {
        public List<CodeDtErmValue> CodeDtErmValueById(string CodeDtErmId)
        {
            string sql = "select CodeDtErmId,CodeId,Code,DisplayName from Concept.codedtermvalue where codedtermid='{0}'";
            sql = string.Format(sql, CodeDtErmId);
            List<CodeDtErmValue> CodeDtermErmList = null;
            OracleDataReader reader = null;
            try
            {
                reader = DapperHelper.GetReader(sql);
                CodeDtermErmList = new List<CodeDtErmValue>();
                while (reader.Read())
                {
                    CodeDtermErmList.Add(new CodeDtErmValue()
                    {

                        CodeDtErmId = Convert.ToInt32(reader["CodeDtErmId"]),
                        Code = Convert.ToInt32(reader["Code"]),
                        CodeId = Convert.ToInt32(reader["CodeId"]),
                        DisplayName = reader["DisplayName"].ToString()
                    });

                }
                return CodeDtermErmList;
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }


        }
    }
}

 

1.3 WCF服务契约接口及实现的服务

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace WCFService
{
    [ServiceContract]
    interface ICodedterm
    {
        [OperationContract]
        CodeDterm GetCodeDterm(string KeyWord);
        [OperationContract]
        List<CodeDtErmValue> CodeDtErmValueById(string CodeDtErmId);
        [OperationContract]
        string TestMethod();
    }
    public class CodedtermService : ICodedterm
    {
        public List<CodeDtErmValue> CodeDtErmValueById(string CodeDtErmId)
        {
            return new CodeDtErmValueService().CodeDtErmValueById(CodeDtErmId);
        }

        public CodeDterm GetCodeDterm(string KeyWord)
        {
            return new CodeDtermService().GetCodeDterm(KeyWord)[0];
        }

        public string TestMethod()
        {
            return "调用成功";
        }
    }
}

1.4  新建一个后缀为svc的文件CodeERM.svc,名字随意起,并编辑如下:

1.5  配置文件Web.config编写如下:

<?xml version="1.0" encoding="utf-8"?>
<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2"/>
    <httpRuntime targetFramework="4.5.2"/>
  </system.web>


  <connectionStrings>
    <add name="ConnectionString" connectionString= "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.18.99.228)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=S12)));Persist Security Info=True;User ID=apps;Password=jetsun"/>
  </connectionStrings>


  <system.serviceModel>
    
       <bindings>
      <wsHttpBinding>
        <binding name="NoneSecurity"
          maxBufferPoolSize="12000000" maxReceivedMessageSize="12000000" useDefaultWebProxy="false">
          <readerQuotas maxStringContentLength="12000000" maxArrayLength="12000000"/>
          <security mode="None"/>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="WCFService.CodedtermService" behaviorConfiguration="TestBehavior">
        
        <endpoint address  = "" binding="wsHttpBinding" contract="WCFService.ICodedterm"></endpoint>

      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="TestBehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>



</configuration>

其中

1.6  设置WCF服务的端口(鼠标右键项目,选择属性,弹出对话框如下图):

1.7  把该项目设为启动项目并点击调试后,在浏览器中输入:http://localhost:8090//CodeERM.svc

出现下图界面,表示WCF服务建立成功

 

 

二  客户端调用WCF服务

方式有两种:

1  自己编写代码,但这种方式貌似传递的数据不能为实体类对象,只能传递系统确定的值类型数据,如字符串、数值型和byte数组

2  鼠标右键添加服务引用的方式,具体操作参考文章前面部分,测试发现可以传递实体类对象、List<实体类对象>

 

方式1  自己编写代码的方式

2.1  客户端服务契约接口(WCFClient类库中编写)

using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;


namespace WCFClient
{
    [ServiceContract]
    interface ICodedterm
    {
        [OperationContract]
        CodeDterm GetCodeDterm(string KeyWord);
        [OperationContract]
        List<CodeDtErmValue> CodeDtErmValueById(string CodeDtErmId);
        [OperationContract]
        string TestMethod();
    }

}

2.2  调用WCF服务(WCFClient类库中编写)

namespace WCFClient
{
    
    public class CodeDtErmManager
    {
        EndpointAddress address;
        WSHttpBinding binding;

        WCFClient.ICodedterm channel;
        ChannelFactory<WCFClient.ICodedterm> factory;

        public CodeDtErmManager()
        {
            address = new EndpointAddress("http://localhost:8090/CodeERM.svc");
            binding = new WSHttpBinding();
            //binding.Security.Mode = SecurityMode.None;
            factory = new ChannelFactory<WCFClient.ICodedterm>(binding, address);
            channel = factory.CreateChannel();
        }

        public string TestMethod() {
            return channel.TestMethod();
        }
    }
}

 

 

2.3  调用测试(Test控制台中编写)

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            WCFClient.CodeDtErmManager manager = new WCFClient.CodeDtErmManager();

            Console.WriteLine(manager.TestMethod());
            Console.ReadKey();
        }
    }
}

测试结果如下图:

 

 

方式2:添加服务引用的方式:

 

WCFClient类库不用,直接在Test控制台项目添加http://localhost:8090//CodeERM.svc服务引用

 

测试调用如下:

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceReference2.CodedtermClient client = new ServiceReference2.CodedtermClient();
            Console.WriteLine(client.TestMethod());
            ServiceReference2.CodeDterm codeDterm=client.GetCodeDterm("史");
            Console.WriteLine(codeDterm.CodeDtErmId+"\t"+codeDterm.Description);
            Console.ReadKey();
        }
    }
}

调用结果如下:

但是如果服务的返回的数据类型为List<实体对象>,则客户端调用后返回的是数组,如   实体对象[]

 

 

 

 

常见问题:

 

问题1:当发生这样的异常:

    已经超过传入消息的最大消息大小配额。若要增加配额,请使用相应绑定元素上的MaxReceivedMessageSize

解决方案:这时客户端接收到的数据长度大于默认的长度了,这时需要增加客户端的接收数据的长度,通过配置文件操作

App.config配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_ICodedterm" maxBufferPoolSize="12000000" maxReceivedMessageSize="12000000"/>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8090/CodeERM.svc" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_ICodedterm" contract="ServiceCodeERM.ICodedterm"
                name="WSHttpBinding_ICodedterm">
                <identity>
                    <userPrincipalName value="zhangxiangyu@hissoft.com" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

 

核心配置,把下面的数值改大一点:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxy2847225301

测试使用

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值