[WCF 学习笔记] 4. 消息操作
2009-01-17 14:58
471 查看
WCF 的一切都是围绕着 Message 进行,那么 Message 究竟是什么样子?
[ServiceContract]
public interface ICalculate
{
[OperationContract]
double Add(double a, double b);
}
public class CalculateService : ICalculate
{
public double Add(double a, double b)
{
Message msg = OperationContext.Current.RequestContext.RequestMessage;
Console.WriteLine(msg);
return a + b;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new BasicHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new BasicHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
Console.WriteLine(o.Add(1, 2));
}
}
输出
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://...">http://localhost:8080/calc</To>
<Action s:mustUnderstand="1" xmlns="http://...">http://tempuri.org/ICalculate/Add</Action>
</s:Header>
<s:Body>
<Add xmlns="http://tempuri.org/">
<a>1</a>
<b>2</b>
</Add>
</s:Body>
</s:Envelope>
事实上我们可以直接基于 Message Layer 进行编程,利用 OperationContract.Action 捕获特定 Action 的消息。
[ServiceContract]
public interface ICalculate
{
[OperationContract(Action = "Add", ReplyAction="Add")]
Message ProcessMessage(Message m);
}
public class CalculateService : ICalculate
{
public Message ProcessMessage(Message m)
{
Data d = m.GetBody<Data>();
Console.WriteLine(d.I);
return Message.CreateMessage(MessageVersion.Soap11, "Add", new Data(9999));
}
}
[DataContract]
public class Data
{
[DataMember]
public int I;
public Data(int i)
{
this.I = i;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new BasicHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(
new BasicHttpBinding(), "http://localhost:8080/calc");
IRequestChannel channel = factory.CreateChannel();
channel.Open();
Message request = Message.CreateMessage(MessageVersion.Soap11, "Add", new Data(1234));
Message reply = channel.Request(request);
Console.WriteLine("-------------------");
Console.WriteLine(reply);
channel.Close();
factory.Close();
}
}
输出:
1234
-------------------
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<Data xmlns="http://..." xmlns:i="http://...">
<I>9999</I>
</Data>
</s:Body>
</s:Envelope>
正
如上面所看到的,所有的调用都被转换成消息后发送。这也符合 SOA 的规范,完全隔离,清晰的边界。(调用
"m.GetBody<Data>()" 后,会导致 Message.State 变更,再次访问会出错,有关详细信息请参考 MSDN
文档。)
我们还可以使用 MessageContractAttribute / MessageHeaderAttribute
来控制消息格式,这比 DataContractAttribute
要更加灵活。我们可以设置消息标头、消息体,包括是否对其中某些进行签名和加密处理。
[ServiceContract]
public interface ICalculate
{
[OperationContract]
void Add(Data d);
}
public class CalculateService : ICalculate
{
public void Add(Data d)
{
Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage);
Console.WriteLine("----------------");
Console.WriteLine("{0}/{1}", d.a, d.b);
}
}
[MessageContract]
public class Data
{
[MessageHeader]
public double a = 1;
[MessageBodyMember]
public double b = 2;
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new BasicHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new BasicHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
Data d = new Data();
d.a = 1234;
d.b = 5678;
o.Add(d);
}
}
输出:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:a xmlns:h="http://tempuri.org/">1</h:a>
<To s:mustUnderstand="1" xmlns="http://s...">http://localhost:8080/calc</To>
<Action s:mustUnderstand="1" xmlns="http://...">http://tempuri.org/ICalculate/Add</Action>
</s:Header>
<s:Body>
<Data xmlns="http://tempuri.org/">
<b>2</b>
</Data>
</s:Body>
</s:Envelope>
----------------
1234/5678
有关 Message 更详细的信息,可以参考 MSDN (Microsoft Windows SDK) 文档。
[ServiceContract]
public interface ICalculate
{
[OperationContract]
double Add(double a, double b);
}
public class CalculateService : ICalculate
{
public double Add(double a, double b)
{
Message msg = OperationContext.Current.RequestContext.RequestMessage;
Console.WriteLine(msg);
return a + b;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new BasicHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new BasicHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
Console.WriteLine(o.Add(1, 2));
}
}
输出
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://...">http://localhost:8080/calc</To>
<Action s:mustUnderstand="1" xmlns="http://...">http://tempuri.org/ICalculate/Add</Action>
</s:Header>
<s:Body>
<Add xmlns="http://tempuri.org/">
<a>1</a>
<b>2</b>
</Add>
</s:Body>
</s:Envelope>
事实上我们可以直接基于 Message Layer 进行编程,利用 OperationContract.Action 捕获特定 Action 的消息。
[ServiceContract]
public interface ICalculate
{
[OperationContract(Action = "Add", ReplyAction="Add")]
Message ProcessMessage(Message m);
}
public class CalculateService : ICalculate
{
public Message ProcessMessage(Message m)
{
Data d = m.GetBody<Data>();
Console.WriteLine(d.I);
return Message.CreateMessage(MessageVersion.Soap11, "Add", new Data(9999));
}
}
[DataContract]
public class Data
{
[DataMember]
public int I;
public Data(int i)
{
this.I = i;
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new BasicHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(
new BasicHttpBinding(), "http://localhost:8080/calc");
IRequestChannel channel = factory.CreateChannel();
channel.Open();
Message request = Message.CreateMessage(MessageVersion.Soap11, "Add", new Data(1234));
Message reply = channel.Request(request);
Console.WriteLine("-------------------");
Console.WriteLine(reply);
channel.Close();
factory.Close();
}
}
输出:
1234
-------------------
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body>
<Data xmlns="http://..." xmlns:i="http://...">
<I>9999</I>
</Data>
</s:Body>
</s:Envelope>
正
如上面所看到的,所有的调用都被转换成消息后发送。这也符合 SOA 的规范,完全隔离,清晰的边界。(调用
"m.GetBody<Data>()" 后,会导致 Message.State 变更,再次访问会出错,有关详细信息请参考 MSDN
文档。)
我们还可以使用 MessageContractAttribute / MessageHeaderAttribute
来控制消息格式,这比 DataContractAttribute
要更加灵活。我们可以设置消息标头、消息体,包括是否对其中某些进行签名和加密处理。
[ServiceContract]
public interface ICalculate
{
[OperationContract]
void Add(Data d);
}
public class CalculateService : ICalculate
{
public void Add(Data d)
{
Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage);
Console.WriteLine("----------------");
Console.WriteLine("{0}/{1}", d.a, d.b);
}
}
[MessageContract]
public class Data
{
[MessageHeader]
public double a = 1;
[MessageBodyMember]
public double b = 2;
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(CalculateService));
host.AddServiceEndpoint(typeof(ICalculate), new BasicHttpBinding(),
"http://localhost:8080/calc");
host.Open();
});
ChannelFactory<ICalculate> factory = new ChannelFactory<ICalculate>(new BasicHttpBinding(),
"http://localhost:8080/calc");
ICalculate o = factory.CreateChannel();
Data d = new Data();
d.a = 1234;
d.b = 5678;
o.Add(d);
}
}
输出:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:a xmlns:h="http://tempuri.org/">1</h:a>
<To s:mustUnderstand="1" xmlns="http://s...">http://localhost:8080/calc</To>
<Action s:mustUnderstand="1" xmlns="http://...">http://tempuri.org/ICalculate/Add</Action>
</s:Header>
<s:Body>
<Data xmlns="http://tempuri.org/">
<b>2</b>
</Data>
</s:Body>
</s:Envelope>
----------------
1234/5678
有关 Message 更详细的信息,可以参考 MSDN (Microsoft Windows SDK) 文档。
相关文章推荐
- [WCF 学习笔记] 4. 消息操作
- [WCF 学习笔记] 3. 消息交换
- [学习笔记]Silverlight+WCF对数据库进行操作
- wcf RIA 学习笔记二 多对多关系操作
- WCF学习笔记之消息交换模式
- [WCF 学习笔记] 3. 消息交换
- linux UART 驱动学习笔记——用户如何操作硬件
- JavaWeb学习笔记-JDBC操作(2)[数据库的更新与查询]
- MongoDB学习笔记(五) MongoDB文件存取操作
- PHP学习笔记12:字符串操作
- MFC学习笔记3 Windows编程基础--DialogBox、回调、消息、控件
- Java学习笔记——File类文件管理及IO读写、复制操作
- (学习笔记)threshold —— opencv阈值操作
- 【Git 学习笔记】2.4 - 撤消操作
- vc++数据库操作的学习笔记
- Sharepoint学习笔记—ECMAScript对象模型系列-- 5、使用ECMA操作列表对象(list)
- MySQL学习笔记3——MySQL进阶操作
- WCF学习笔记(一):WCF Service Application和WCF Service Library的区别
- Python学习笔记3-文件的简单操作
- android开发学习笔记——sqlite操作