.net remoting 框架简介http://www.g2host.cn/www/Article/Program/Net/200701/10786.html
How to monitor if Remote Objects have been deployed successfully
在调试
.Net Remoting
程序时,经常会出现一些莫名其妙的问题,
IDE
提示的异常信息有时也不一定正确。很多时候都是自己粗心,配置
configuration
文件上出了问题,包括
Client
和
Server
端的配置文件。另外,我感觉
.Net Remoting
中还有许多陷阱(
trap
),如前面
posting
《
SoapSuds工具的一些不足之处
》所提及的,不只这些,还有许多。如果陷入这些
trap
,而且又不知道的话,就麻烦了,调试半天也不知道问题在哪里。有空的时间,我准备花些时间整理一下
.Net Remoting
中的
trap
。
言归正传,这里看看如何检测
Remote Objects
是否部署成功。
Remote Objects
部署成功是第一步,否则
Client
端调用
Remote Objects
肯定会抛异常信息了。因此,如出现异常信息,首先检测
Remote Objects
是否成功部署在
Server
端。
下面根据激活类型分两种情况:
SAO
(服务端激活对象)和
CAO
(客户端激活对象)。
1
.
SAO
对象
对
SAO
对象而言,比较简单。根据
Server
端配置文件中
<wellknown>
节或
RemotingConfiguration.RegisterWellKnownServiceType()
方法中指定的
URL
,通过
IE
浏览器检测,如下所示:
http://<hostname>:<port>/<ApplicationName>/<URL>?wsdl
如果
IE
返回
WSDL
信息,则显示
Remote Objects
部署成功。其实只要看到
IE
有正确返回信息就行了,如果你了解
WSDL
(
Web Services Description Language
),可以进一步看看是否调用的
Remote Method
是否有出现。
需要注意的地方:
(
1
)如果
Remote Objects
部署在
IIS
中,
<ApplicationName>
则为虚拟目录名称(
Virtual Directory Name
),并且不要在
Web.Config
配置文件中设定
Application Name
。同时
Remote Objects
的
URL
需要以
soap
或
rem
为后缀名。
(
2
)如果
Remote Objects
不是部署在
IIS
中,则必须在
configuration
配置文件或者在代码中
RemotingConfiguration.Application=”<ApplicationName>”
来指定
ApplicationName
。
2
.
CAO
对象
对于
CAO
对象,和
SAO
对象不一样。需要如下的
URL
来测试:
http://<hostname>:<port>/<ApplicationName>/RemoteActivationService.rem?wsdl
后面是
RemoteActivationService.rem
,这点和
SAO
对象不一样。
需要注意的地方:
(
1
)在调用
CAO
对象时,需要在
Client
端的配置文件中
<client>
节指定
Remote Objects
的
url
属性。如何使用
.Net Remoting
的配置文件,可以参考《
.Net Remoting配置文件的用法》。
注:访问IIS元数据库失败
装了VS2005再装IIS,结果出了些小问题
访问IIS元数据库失败
思考可能是次序出了问题,解决
1、打开CMD,进入 C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727
2、输入 aspnet_regiis.exe -i
稍等片刻,注册成功就解决问题了。
2、输入 aspnet_regiis.exe -i
稍等片刻,注册成功就解决问题了。
接着还会出现“未能创建 Mutex”的问题
解决方法:
1、先关闭你的VS2005。
2、打开 C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files 找到你刚才调试的程序的名字的目录删除它。
3、关闭IIS服务器,重开一次。
4、用IE浏览一下你的程序,问题解决。
都是次序惹的祸,最好是先IIS 再VS2K5
最近项目开发中的传输数据是围绕Remoting而召开的,所以想把所有的数据实体都定义统一的格式,于是就写了一个基于DataTable的基类BaseModal,其他数据实体全部继承于它。此BaseModal基类还包括了一些其他的自有的属性,例如pageSize每页记录数、currentPage当前页码等等,代码如下:
1
2
文件描述#region 文件描述
3
// -------------------------------------------------------------------------------------------------
4
// 文 件 名:BaseModel.cs
5
// 创 建 者:李毅
6
// 创建日期:2006年06月13日
7
// 命名空间:Colorful.Model
8
// 类 型:BaseModel类
9
// 版 本:1.0.0
10
// 描 述:数据基本表
11
// -------------------------------------------------------------------------------------------------
12
#endregion
13
14
修改记录#region 修改记录
15
// -------------------------------------------------------------------------------------------------
16
// 修改日期:
17
// 修 改 者:
18
// 修 改 项:
19
// -------------------------------------------------------------------------------------------------
20
#endregion
21
22
using System;
23
using System.Data;
24
using System.Text;
25
using System.Runtime.Serialization;
26
27
namespace Colorful.Model
28

{
29
/**//// <summary>
30
/// 数据基本表
31
/// </summary>
32
[Serializable]
33
public class BaseModel : DataTable
34
{
35
protected int index; //记录当前行
36
protected int pageSize; //每页记录数
37
protected int currentPage; //当前页码
38
protected int pages; //总页数
39
protected long totalRecord; //总记录数
40
protected string description; //其他描述,及其辅助功能
41
42
public int PageSize#region public int PageSize
43
// -----------------------------------------------------------------------------------------
44
/**//// <summary>
45
/// 设置或者获取每页记录数
46
/// </summary>
47
public int PageSize
48
{
49
get
{ return pageSize; }
50
set
{ pageSize = value; }
51
}
52
// -----------------------------------------------------------------------------------------
53
#endregion
54
55
public int CurrentPage#region public int CurrentPage
56
// -----------------------------------------------------------------------------------------
57
/**//// <summary>
58
/// 设置或者获取当前页码
59
/// </summary>
60
public int CurrentPage
61
{
62
get
{ return currentPage; }
63
set
{ currentPage = value; }
64
}
65
// -----------------------------------------------------------------------------------------
66
#endregion
67
68
public int Pages#region public int Pages
69
// -----------------------------------------------------------------------------------------
70
/**//// <summary>
71
/// 设置或者获取总页数
72
/// </summary>
73
public int Pages
74
{
75
get
{ return pages; }
76
set
{ pages = value; }
77
}
78
// -----------------------------------------------------------------------------------------
79
#endregion
80
81
public long TotalRecord#region public long TotalRecord
82
// -----------------------------------------------------------------------------------------
83
/**//// <summary>
84
/// 设置或者获取总记录数
85
/// </summary>
86
public long TotalRecord
87
{
88
get
{ return totalRecord; }
89
set
{ totalRecord = value; }
90
}
91
// -----------------------------------------------------------------------------------------
92
#endregion
93
94
public string Description#region public string Description
95
// -----------------------------------------------------------------------------------------
96
/**//// <summary>
97
/// 其他描述
98
/// </summary>
99
public string Description
100
{
101
get
{ return description; }
102
set
{ description = value; }
103
}
104
// -----------------------------------------------------------------------------------------
105
#endregion
106
107
public string GUID#region public string GUID
108
// -----------------------------------------------------------------------------------------
109
/**//// <summary>
110
/// 设置或获取当前表记录ID
111
/// </summary>
112
public string GUID
113
{
114
get
115
{
116
return index == -1 ? "" : Rows[index]["GUID"].ToString();
117
}
118
set
119
{
120
if (index > -1)
121
{
122
Rows[index]["GUID"] = value;
123
}
124
}
125
}
126
// -----------------------------------------------------------------------------------------
127
#endregion
128
129
130
131
public BaseModel()#region public BaseModel()
132
// -----------------------------------------------------------------------------------------
133
/**//// <summary>
134
/// 构造函数
135
/// </summary>
136
public BaseModel()
137
{
138
index = -1;
139
pageSize = 20;
140
currentPage = 1;
141
pages = 1;
142
totalRecord = 0;
143
description = "";
144
145
Columns.Add("GUID", typeof(string));
146
}
147
// -----------------------------------------------------------------------------------------
148
#endregion
149
150
public bool MoveNext()#region public bool MoveNext()
151
// -----------------------------------------------------------------------------------------
152
/**//// <summary>
153
/// 向后移动一行
154
/// </summary>
155
public bool MoveNext()
156
{
157
if (index < Rows.Count - 1)
158
{
159
index++;
160
return true;
161
}
162
return false;
163
}
164
// -----------------------------------------------------------------------------------------
165
#endregion
166
167
public bool MovePre()#region public bool MovePre()
168
// -----------------------------------------------------------------------------------------
169
/**//// <summary>
170
/// 向前移动一行
171
/// </summary>
172
public bool MovePre()
173
{
174
if (index > 1)
175
{
176
index--;
177
return true;
178
}
179
return false;
180
}
181
// -----------------------------------------------------------------------------------------
182
#endregion
183
184
public bool GoToRow(int rowIndex)#region public bool GoToRow(int rowIndex)
185
// -----------------------------------------------------------------------------------------
186
/**//// <summary>
187
/// 转到指定行
188
/// </summary>
189
/// <param name="rowIndex">行号,0为第一行</param>
190
/// <returns>返回是否定位成功</returns>
191
public bool GoToRow(int rowIndex)
192
{
193
if (rowIndex > -1 && rowIndex < Rows.Count)
194
{
195
this.index = rowIndex;
196
return true;
197
}
198
return false;
199
}
200
// -----------------------------------------------------------------------------------------
201
#endregion
202
203
public bool GoToFirst()#region public bool GoToFirst()
204
// -----------------------------------------------------------------------------------------
205
/**//// <summary>
206
/// 转到首行
207
/// </summary>
208
/// <returns>返回是否定位成功</returns>
209
public bool GoToFirst()
210
{
211
if (Rows.Count > 0)
212
{
213
this.index = 0;
214
return true;
215
}
216
return false;
217
}
218
// -----------------------------------------------------------------------------------------
219
#endregion
220
221
public bool GoToLast()#region public bool GoToLast()
222
// -----------------------------------------------------------------------------------------
223
/**//// <summary>
224
/// 转到尾行
225
/// </summary>
226
/// <returns>返回是否定位成功</returns>
227
public bool GoToLast()
228
{
229
if (Rows.Count > 0)
230
{
231
this.index = Rows.Count - 1;
232
return true;
233
}
234
return false;
235
}
236
// -----------------------------------------------------------------------------------------
237
#endregion
238
239
public void Insert()#region public void Insert()
240
// -----------------------------------------------------------------------------------------
241
/**//// <summary>
242
/// 插入空行,并把空行当作当前行
243
/// </summary>
244
public void Insert()
245
{
246
Rows.Add(NewRow());
247
index = Rows.Count - 1;
248
}
249
// -----------------------------------------------------------------------------------------
250
#endregion
251
252
public void Delete()#region public void Delete()
253
// -----------------------------------------------------------------------------------------
254
/**//// <summary>
255
/// 删除当前行
256
/// </summary>
257
public void Delete()
258
{
259
if (index > -1)
260
{
261
Rows[index].Delete();
262
if (index == Rows.Count)
263
{
264
index = Rows.Count - 1;
265
}
266
}
267
}
268
// -----------------------------------------------------------------------------------------
269
#endregion
270
271
}
272
}
273
结果发现数据在放序列化的时候出错,发现原来是没有加入序列化和反序列化构造函数,虽然BaseModal继承于DataTable,并且加入了[Serializable]树序列化属性,但是要实现想继承序列化,还是要加入构造函数,于是加入:
结果编译,没有任何错误,但是类中的属性(pageSize等)值却获取不到,想了很久,发现其实道理跟前面有些类似,因为自己加入的属性根本就没有“告诉”序列化函数去处理,自然而然值就丢失了,于是修改函数如下:
OK,一切搞定了
FeedBack:


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

197

198

199

200

201

202

203


204

205


206

207

208

209

210



211

212



213

214

215

216

217

218

219

220

221


222

223


224

225

226

227

228



229

230



231

232

233

234

235

236

237

238

239


240

241


242

243

244

245



246

247

248

249

250

251

252


253

254


255

256

257

258



259

260



261

262

263



264

265

266

267

268

269

270

271

272

273

1
protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
#region protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
2
// -----------------------------------------------------------------------------------------
3
/**//// <summary>
4
/// 反序列化构造函数
5
/// </summary>
6
/// <param name="si">反序列化所需的全部数据</param>
7
/// <param name="context">目标描述</param>
8
protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
9
{
10
}
11
// -----------------------------------------------------------------------------------------
12
#endregion
13
14
public override void GetObjectData(SerializationInfo info, StreamingContext context)
#region public override void GetObjectData(SerializationInfo info, StreamingContext context)
15
// -----------------------------------------------------------------------------------------
16
/**//// <summary>
17
/// 序列化函数
18
/// </summary>
19
/// <param name="info">序列化所需的全部数据</param>
20
/// <param name="context">目标描述</param>
21
public override void GetObjectData(SerializationInfo info, StreamingContext context):base.GetObjectData(info, context)
22
{
23
}
24
// -----------------------------------------------------------------------------------------
25
#endregion


2

3


4

5

6

7

8

9



10

11

12

13

14


15

16


17

18

19

20

21

22



23

24

25

结果编译,没有任何错误,但是类中的属性(pageSize等)值却获取不到,想了很久,发现其实道理跟前面有些类似,因为自己加入的属性根本就没有“告诉”序列化函数去处理,自然而然值就丢失了,于是修改函数如下:
1
protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
#region protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
2
// -----------------------------------------------------------------------------------------
3
/**//// <summary>
4
/// 反序列化构造函数
5
/// </summary>
6
/// <param name="si">反序列化所需的全部数据</param>
7
/// <param name="context">目标描述</param>
8
protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
9
{
10
index = info.GetInt32("index");
11
pageSize = info.GetInt32("pageSize");
12
currentPage = info.GetInt32("currentPage");
13
pages = info.GetInt32("pages");
14
totalRecord = info.GetInt64("totalRecord");
15
description = info.GetString("description");
16
}
17
// -----------------------------------------------------------------------------------------
18
#endregion
19
20
public override void GetObjectData(SerializationInfo info, StreamingContext context)
#region public override void GetObjectData(SerializationInfo info, StreamingContext context)
21
// -----------------------------------------------------------------------------------------
22
/**//// <summary>
23
/// 序列化函数
24
/// </summary>
25
/// <param name="info">序列化所需的全部数据</param>
26
/// <param name="context">目标描述</param>
27
public override void GetObjectData(SerializationInfo info, StreamingContext context)
28
{
29
info.AddValue("index", index);
30
info.AddValue("pageSize", pageSize);
31
info.AddValue("currentPage", currentPage);
32
info.AddValue("pages", pages);
33
info.AddValue("totalRecord", totalRecord);
34
info.AddValue("description", description);
35
base.GetObjectData(info, context);
36
}
37
// -----------------------------------------------------------------------------------------
38
#endregion


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

OK,一切搞定了

FeedBack:
2006-08-29 18:16 |
blockhead
刚看到一个夏桅 (xia4 wei2)提供的的技巧,在加入自定义字段,可以不用自己一个个加入,如夏桅所说:
根据我的experiance,需要自己实现ISerializable接口的情形,往往是因为“大部分字段可以自动序列化(比如int、string),而少数字段不支持序列化(比如Thread、WaitHandle),但这些字段对于对象又是必不可少的”的需求。也就是说,这些不支持序列化的字段在反序列化后仍不允许为空时,你得自己控制序列化/反序列化行为,在反序列化构造函数重新建立它们的实例。
这里的问题是,大部分字段都可以自动序列化的;但是为了少数几个不支持序列化的字段,却需要编写代码为所有字段都进行手工的序列化 — 这些代码不但冗繁,而且容易出错(比如忘掉了处理某个字段)。我一直希望能自己参与自动序列化/反序列化的行为,比如在自动反序列化之后,运行时能自动调用一段我自己的代码,处理那些不支持序列化的字段。
class SerializationHelper
...{
public static void Serialize(object obj, SerializationInfo info, StreamingContext context)
...{
MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), context);
foreach(FieldInfo field in members)
...{
info.AddValue(field.Name, field.GetValue(obj), field.FieldType);
}
}
public static void Deserialize(object obj, SerializationInfo info, StreamingContext context)
...{
MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), context);
foreach(FieldInfo field in members)
...{
field.SetValue(obj, info.GetValue(field.Name, field.FieldType));
}
}
}
下面是利用了这个SerializationHelper的自定义序列化方案:
[Serializable]
class Person : ISerializable
...{
// public field
public string Name = "Vista Xia";
// private field
private int age = 23;
// public property (no use in serialization)
public int Age
...{
get ...{ return age; }
set ...{ age = value; }
}
[NonSerialized]
public string Award;
// event/delegate
public event EventHandler Birthday;
public Person()
...{
Award = "MVP";
}
protected Person(SerializationInfo info, StreamingContext context)
...{
SerializationHelper.Deserialize(this, info, context);
Award = "MVP";
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
...{
SerializationHelper.Serialize(this, info, context);
如有不明白处,请查看夏桅 (xia4 wei2)的Blog
http://blog.joycode.com/sunmast/ 回复 更多评论
根据我的experiance,需要自己实现ISerializable接口的情形,往往是因为“大部分字段可以自动序列化(比如int、string),而少数字段不支持序列化(比如Thread、WaitHandle),但这些字段对于对象又是必不可少的”的需求。也就是说,这些不支持序列化的字段在反序列化后仍不允许为空时,你得自己控制序列化/反序列化行为,在反序列化构造函数重新建立它们的实例。
这里的问题是,大部分字段都可以自动序列化的;但是为了少数几个不支持序列化的字段,却需要编写代码为所有字段都进行手工的序列化 — 这些代码不但冗繁,而且容易出错(比如忘掉了处理某个字段)。我一直希望能自己参与自动序列化/反序列化的行为,比如在自动反序列化之后,运行时能自动调用一段我自己的代码,处理那些不支持序列化的字段。
class SerializationHelper
...{
public static void Serialize(object obj, SerializationInfo info, StreamingContext context)
...{
MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), context);
foreach(FieldInfo field in members)
...{
info.AddValue(field.Name, field.GetValue(obj), field.FieldType);
}
}
public static void Deserialize(object obj, SerializationInfo info, StreamingContext context)
...{
MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), context);
foreach(FieldInfo field in members)
...{
field.SetValue(obj, info.GetValue(field.Name, field.FieldType));
}
}
}
下面是利用了这个SerializationHelper的自定义序列化方案:
[Serializable]
class Person : ISerializable
...{
// public field
public string Name = "Vista Xia";
// private field
private int age = 23;
// public property (no use in serialization)
public int Age
...{
get ...{ return age; }
set ...{ age = value; }
}
[NonSerialized]
public string Award;
// event/delegate
public event EventHandler Birthday;
public Person()
...{
Award = "MVP";
}
protected Person(SerializationInfo info, StreamingContext context)
...{
SerializationHelper.Deserialize(this, info, context);
Award = "MVP";
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
...{
SerializationHelper.Serialize(this, info, context);
如有不明白处,请查看夏桅 (xia4 wei2)的Blog
http://blog.joycode.com/sunmast/ 回复 更多评论