webabcd - 专注于asp.net

ASP.NET
从现在开始 一切都不晚
posts - 148, comments - 3912, trackbacks - 308, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理
[源码下载]


化零为整WCF(7) - 消息处理(使用消息传输优化机制 - MTOM)


作者:webabcd


介绍
WCF(Windows Communication Foundation) - 消息处理:MTOM(Message Transmission Optimization Mechanism) - 消息传输优化机制。本文以web方式上传大文件为例。


示例
1、服务
IMtom.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ServiceModel;
using System.IO;

namespace WCF.ServiceLib.Message
{
    
/// <summary>
    
/// IMtom接口
    
/// </summary>

    [ServiceContract]
    
public interface IMtom
    
{
        
/// <summary>
        
/// 上传文件
        
/// </summary>
        
/// <param name="path">文件目标路径</param>
        
/// <param name="fileData">文件字节数组</param>

        [OperationContract]
        
void UploadFile(string path, byte[] fileData);
    }

}


Mtom.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ServiceModel;
using System.IO;

namespace WCF.ServiceLib.Message
{
    
/// <summary>
    
/// Mtom类
    
/// </summary>

    public class Mtom : IMtom
    
{
        
/// <summary>
        
/// 上传文件
        
/// </summary>
        
/// <param name="path">文件目标路径</param>
        
/// <param name="fileData">文件字节数组</param>

        public void UploadFile(string path, byte[] fileData)
        
{
            FileStream fs 
= new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
            fs.Write(fileData, 
0, fileData.Length);
            fs.Flush();
            fs.Close();
        }

    }

}




2、宿主

Mtom.svc
<%@ ServiceHost Language="C#" Debug="true" Service="WCF.ServiceLib.Message.Mtom" %>

Web.config
<?xml version="1.0"?>
<configuration>
  
<system.serviceModel>
    
<services>
      
<!--name - 提供服务的类名-->
      
<!--behaviorConfiguration - 指定相关的行为配置-->
      
<service name="WCF.ServiceLib.Message.Mtom" behaviorConfiguration="MessageBehavior">
        
<!--address - 服务地址-->
        
<!--binding - 通信方式-->
        
<!--contract - 服务契约-->
        
<!--bindingConfiguration - 指定相关的绑定配置-->
        
<endpoint address="" binding="wsHttpBinding" contract="WCF.ServiceLib.Message.IMtom" bindingConfiguration="MtomBindingConfiguration" />
      
</service>
    
</services>
    
<behaviors>
      
<serviceBehaviors>
        
<behavior name="MessageBehavior">
          
<!--httpGetEnabled - 使用get方式提供服务-->
          
<serviceMetadata httpGetEnabled="true" />
          
<serviceDebug includeExceptionDetailInFaults="true"/>
        
</behavior>
      
</serviceBehaviors>
    
</behaviors>
    
<bindings>
      
<wsHttpBinding>
        
<!--messageEncoding - 指定用 MTOM 还是 Text 对 SOAP 消息编码-->
        
<!--maxReceivedMessageSize - 在采用此绑定配置的通道上可接收的最大消息大小(单位:字节)-->
        
<!--receiveTimeout - 在传输引发异常之前可用于完成读取操作的时间间隔-->
        
<binding name="MtomBindingConfiguration" messageEncoding="Mtom" maxReceivedMessageSize="1073741824" receiveTimeout="00:10:00">
          
<!--maxArrayLength - 配额控制:允许的最大数组长度-->
          
<readerQuotas maxArrayLength="1073741824" />
        
</binding>
      
</wsHttpBinding>
    
</bindings>
  
</system.serviceModel>
</configuration>


3、客户端
Mtom.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Mtom.aspx.cs"
    Inherits
="Message_Mtom" Title="消息处理(使用消息传输优化机制 - MTOM)" 
%>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
    
<p>
        MTOM(Message Transmission Optimization Mechanism) - 消息传输优化机制
    
</p>
    
<div>
        
<ul>
            
<li>可以指定用 MTOM 还是 Text 对 SOAP 消息编码</li>
            
<li>抓soap消息的时候可以用tcpTrace</li>
            
<li>用17,766,901字节大小的文件测试:Text编码(soap大小:31,591,929字节);MTOM编码(soap大小:23,696,066字节)</li>
        
</ul>
    
</div>
    
<div>
        源文件:
        
<asp:FileUpload ID="file" runat="server" />
        
&nbsp;
        上传路径:
        
<asp:TextBox ID="txtDestination" runat="server" Text="C:\"></asp:TextBox>
        
&nbsp;
        
<asp:Button ID="btnUpload" runat="server" Text="上传" OnClick="btnUpload_Click" />
    
</div>
</asp:Content>

Mtom.aspx.cs
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.ServiceModel.Channels;
using System.IO;

public partial class Message_Mtom : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    
{

    }


    
protected void btnUpload_Click(object sender, EventArgs e)
    
{
        var proxy 
= new MessageSvc.Mtom.MtomClient();

        var length 
= file.PostedFile.ContentLength;
        var bytes 
= new byte[length];
        file.PostedFile.InputStream.Read(bytes, 
0, length);

        
try
        
{
            proxy.UploadFile(
                txtDestination.Text 
+ Path.GetFileName(file.PostedFile.FileName), 
                bytes);
            Page.ClientScript.RegisterStartupScript(
typeof(Page), "js""alert('上传成功');"true);
        }

        
catch (Exception ex)
        
{
            Page.ClientScript.RegisterStartupScript(
typeof(Page), "js""alert('" + ex.ToString() + "');"true);
        }


        proxy.Close();
    }

}


Web.config
<?xml version="1.0"?>
<configuration>
  
<system.serviceModel>
    
<client>
      
<!--address - 服务地址-->
      
<!--binding - 通信方式-->
      
<!--contract - 服务契约-->
      
<!--bindingConfiguration - 指定相关的绑定配置-->
      
<!--behaviorConfiguration - 指定相关的行为配置-->
      
<!--endpoint address="http://localhost:3502/ServiceHost/Message/Mtom.svc" binding="wsHttpBinding" contract="MessageSvc.Mtom.IMtom" bindingConfiguration="MtomBindingConfiguration" behaviorConfiguration="MtomEndpointBehavior" /-->
      
<endpoint address="http://localhost:3502/ServiceHost/Message/Mtom.svc" binding="wsHttpBinding" contract="MessageSvc.Mtom.IMtom" bindingConfiguration="MtomBindingConfiguration" />
    
</client>
    
<bindings>
      
<wsHttpBinding>
        
<!--messageEncoding - 指定用 MTOM 还是 Text 对 SOAP 消息编码-->
        
<!--sendTimeout - 在传输引发异常之前可用于完成写入操作的时间间隔-->
        
<binding name="MtomBindingConfiguration" messageEncoding="Mtom" sendTimeout="00:10:00">
          
<!--maxArrayLength - 配额控制:允许的最大数组长度-->
          
<readerQuotas maxArrayLength="1073741824" />
        
</binding>
      
</wsHttpBinding>
    
</bindings>
    
<behaviors>
      
<endpointBehaviors>
        
<behavior name="MtomEndpointBehavior">
          
<!--clientVia - 创建传输通道的 URI (tcpTrace抓soap的时候用)-->
          
<clientVia viaUri="http://localhost:8888/ServiceHost/Message/Mtom.svc" />
        
</behavior>
      
</endpointBehaviors>
    
</behaviors>
  
</system.serviceModel>
</configuration>


运行结果:
上传文件后提示上传成功



OK
[源码下载]

Feedback

#1楼    回复  引用    

2008-04-17 18:12 by 陈禹辰 [未注册用户]
太强了,学习中...

#2楼    回复  引用    

2008-04-17 23:40 by 黑白 [未注册用户]
兄弟最近发文又多了啊,呵呵,支持

#3楼 [楼主]   回复  引用  查看    

2008-04-18 07:49 by webabcd      
@黑白
:)
稍微不忙的话就会写写东西

#4楼 [楼主]   回复  引用  查看    

2008-04-18 07:49 by webabcd      
@陈禹辰
:)
学以致用

#5楼    回复  引用  查看    

2008-04-18 09:38 by jillzhang      
非常好,如果能上传抓包效果就更好了,能看清MTOM编码和Text的编码的异同

#6楼 [楼主]   回复  引用  查看    

2008-04-18 13:01 by webabcd      
@jillzhang
:)
呵呵
写了的,可能太隐蔽了
用17,766,901字节大小的文件测试:Text编码(soap大小:31,591,929字节);MTOM编码(soap大小:23,696,066字节)

#7楼    回复  引用  查看    

2008-04-18 16:01 by jillzhang      
@webabcd
:) ,不好意思,没看见。写的挺好

#8楼 [楼主]   回复  引用  查看    

2008-04-18 18:01 by webabcd      
@jillzhang
:)
确实是不好找,我喜欢把说明之类的东西都放到代码里

#9楼    回复  引用    

2008-04-20 20:41 by 黑白 [未注册用户]
这段看不懂啊,麻烦兄弟解释一下
<!--clientVia - 创建传输通道的 URI (tcpTrace抓soap的时候用)-->
<clientVia viaUri="http://localhost:8888/ServiceHost/Message/Mtom.svc" />
谢了

#10楼    回复  引用  查看    

2008-04-20 23:56 by jillzhang      
<clientVia>用于指定消息的路由,在WCF的传输过程中,本来有两个角色
C - S (Client - Server),不指定clientVia,则消息直接由c<--->s,而clientVia则改变了消息的路经,在c,s间添加了一个路由(route),此时消息的传递就成了c<--->r<----->s,正因如此,在r处才能截获到消息内容

#11楼 [楼主]   回复  引用  查看    

2008-04-21 08:11 by webabcd      
@黑白
:)
就是像jillzhang所说的

@jillzhang
热心人啊

#12楼    回复  引用    

2008-04-21 22:57 by 黑白 [未注册用户]
那这里为什么要用clientVia啊,感觉没什么用

#13楼 [楼主]   回复  引用  查看    

2008-04-22 07:43 by webabcd      
@黑白
是抓soap包的时候用的
以便测试mtom编码和text编码

#14楼    回复  引用    

2008-06-18 22:36 by wengqian [未注册用户]
写得不错 我不太喜欢 写代码 我是看了你的代码 再去用
Service configuration editor 的 你如用 这个东东解释 可能更容易接受

#15楼 [楼主]   回复  引用  查看    

2008-06-19 08:27 by webabcd      
@wengqian
确实,实际开发中使用editor要方便很多
但是,我觉得学习过程中还是手写配置文件比较好