在之前的WCF文章中,成功创建了本地部署与服务器部署,但是当我想要在Revit端实现读取数据库信息
于是创建了一个项目测试效果。
参考案例:
Revit二次开发高级应用(1)——利用wcf做简单的族库管理
Drive Revit through a WCF Service

代码

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using MySql.Data.MySqlClient;

namespace WcfMySqlService
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IMysqlInfo”。
[ServiceContract]
public interface IMysqlInfo
{
[OperationContract]
void DoWork();

[OperationContract]
DataSet GetDataSet(string tableName , string command);

[OperationContract]
MySqlDataReader GetReader(string tableName, string command);

[OperationContract]
MySqlConnection GetConnection(string tableName);

[OperationContract]
bool SetDataToMySql(string tableName,string command);

}
}

using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using MySql.Data.MySqlClient;

namespace WcfMySqlService
{
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“MysqlInfo”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 MysqlInfo.svc 或 MysqlInfo.svc.cs,然后开始调试。
public class MysqlInfo : IMysqlInfo
{
public void DoWork()
{
}

public DataSet GetDataSet(string tableName, string command)
{
string connector = $"server=localhost;port=3306;user=user;password=pwd;database={tableName}";
//using (MySqlConnection connection = new MySqlConnection(connector))
//{
try
{
MySqlConnection connection = new MySqlConnection(connector);
connection.Open();
MySqlDataAdapter adapter = new MySqlDataAdapter(command, connection);
DataSet set = new DataSet();
adapter.Fill(set, "item_info");
return set;
}
catch (Exception e)
{
Debug.Print(e.Message);
return null;
}
//finally
//{
// connection.Close();
//}
//}
}

public MySqlDataReader GetReader(string tableName, string command)
{
string connector = $"server=localhost;port=3306;user=user;password=pwd;database={tableName}";
using (MySqlConnection connection = new MySqlConnection(connector))
{
try
{
MySqlCommand cmd = new MySqlCommand()
{
Connection = connection,
CommandText = command
};
connection.Open();
MySqlDataReader reader = cmd.ExecuteReader();
cmd.Dispose();
return reader;
}
catch (Exception e)
{
Debug.Print(e.Message);
return null;
}
finally
{
connection.Close();
}
}
}

public MySqlConnection GetConnection(string tableName)
{
try
{
string connector = $"server=localhost;port=3306;user=user;password=pwd;database={tableName}";
MySqlConnection connection = new MySqlConnection(connector);
return connection;
}
catch (Exception e)
{
Debug.Print(e.Message);
return null;
}

}

public bool SetDataToMySql(string tableName, string command)
{
try
{
string connector = $"server=localhost;port=3306;user=user;password=pwd;database={tableName}";
MySqlConnection connection = new MySqlConnection(connector);
connection.Open();
MySqlCommand cmd = new MySqlCommand(command,connection);
var i = cmd.ExecuteNonQuery();
return i == 1 ? true : false;
}
catch (Exception e)
{
Debug.Print(e.Message);
return false;
}

}
}
}

web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>

<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1"/>
<httpRuntime targetFramework="4.6.1"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
-->
<directoryBrowse enabled="true"/>
</system.webServer>

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="CC7B13FFCD2DDD51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

```csharp
### 客户端
1. 添加引用项目

2.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using WcfLinkRevit.ServiceReference1;
using WcfServiceLibrary;
using IService1 = WcfServiceLibrary.IService1;

namespace WcfLinkRevit
{
    [Transaction(TransactionMode.Manual)]
    public class Class1:IExternalCommand
    {
        private static readonly object _object = new object();
        private IMysqlInfo m_server;
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            
            m_server = ChannelFactory<IMysqlInfo>.CreateChannel(new BasicHttpBinding(), 
                new EndpointAddress("http://120.27.124.206:8084/MysqlInfo.svc"));


            UIDocument uidoc = commandData.Application.ActiveUIDocument;
            var point = uidoc.Selection.PickPoint();
            if (point != null)
            {
                var set = m_server.GetDataSet("recheck_model", "select * from projectlist");
                StringBuilder builder = new StringBuilder("Revit -> Wcf -> Mysql");
                for (int i = 0; i < set.Tables[0].Columns.Count; i++)
                {
                    var name = set.Tables[0].Columns[i].ColumnName;
                    builder.AppendLine(name);
                }
                TaskDialog.Show("Wcf",builder.ToString());
                //TaskDialog.Show("Wcf", m_server.Subtract(20.00D, 10.02D).ToString());
            }


            return Result.Succeeded;
        }
    }
}
1
2
3
4
5
重点是:
```csharp
m_server = ChannelFactory<IMysqlInfo>.CreateChannel(new BasicHttpBinding(),
new EndpointAddress("http://localhost:port/MysqlInfo.svc"));

在这里插入图片描述

如果刚开始学习有些混乱,uri的位置一般就是引用服务的位置
在这里插入图片描述
上面网址就是uri地址

错误整理

错误一

"在 ServiceModel 客户端配置部分中,找不到引用协定“ServiceReference1.IMysqlInfo”的默认终结点元素。这可能是因为未找到应用程序的配置文件,或者是因为客户端元素中找不到与此协定匹配的终结点元素。"
但是我再调试时发现可以正常运行,搜索了一下与Revit相关的WCF案例发现整个搜索只有上面两个案例关于中间错误的信息基本没有阐述
之后去stackoverflow
看到了这个问题,已经有人解决问题,大家可以看看问题回复,下面作者对于这块有个自己的阐述,感觉挺不错的

错误二

服务 不支持内容类型 application/soap+xml; charset=utf-8。客户端和服务
code:

1
2
3
4
5
6
7
8
9
_mysqlInfo = ChannelFactory<IMysqlInfo>.CreateChannel(new WsHttpBinding(),
new EndpointAddress("http://127.0.0.1:8084/MysqlInfo.svc"));
```csharp

这是原来的客户端配置,因为这是想简单测试一下项目,所以binding没有设置全部应用的初始化设置
后来排查,发现是绑定协议这里的问题,客户端的绑定协议为:

![在这里插入图片描述](https://cdn.bimath.com/blog/pg/89b67eb223efe3cb7f89fcd21fcfbb6b.png#pic_center)
修改后的代码应该是:

_mysqlInfo = ChannelFactory.CreateChannel(new BasicHttpBinding(),
new EndpointAddress(“http://120.27.124.206:8084/MysqlInfo.svc“));
```csharp