zoukankan      html  css  js  c++  java
  • ASP.NET MVC路由扩展:链接和URL的生成

    ASP.NET 路由系统通过注册的路由表旨在实现两个“方向”的路有功能,即针对入栈请求的路由和出栈URL的生成。前者通过调用代表全局路由表的RouteCollection对象的GetRouteData方法实现,后者则依赖于RouteCollection的GetVirtualPathData方法,而最终还是落在继承自RouteBase的路由对象的同名方法的调用上。为了编程的方面,ASP.NET MVC为了设计了HtmlHelper和UrlHelper这两个帮助类,我们可以通过调用它们的ActionLink/RouteLink和Action/RouteUrl根据注册的路有规则生成链接或者URL。从本质上讲,HtmlHelper/UrlHelper实现的对URL的生成最终还是依赖于上面所说的GetVirtualPathData方法。

    目录 
    一、UrlHelper V.S. HtmlHelper 
    二、UrlHelper.Action V.S. HtmlHelper.ActionLink 
    三、实例演示:创建一个RouteHelper模拟UrlHelper的URL生成逻辑 
    四、UrlHelper.RouteUrl V.S. HtmlHelper.RouteLink

    一、UrlHelper V.S. HtmlHelper

    在介绍如果通过HtmlHelper和UrlHelper来生成链接或者URL之前,我们来先来看看它们的基本定义。从下面给出的代码片断我们可以看出UrlHelper对象实际上对一个表示请求上下文的RequestContext和路由对象集合的RouteCollection对象的封装。它们分别对应于只读属性RequestContext和RouteCollection,并且在构造函数中被初始化。如果在构造UrlHelper的时候没有指定RouteCollection对象,那么通过RouteTable的静态属性Routes表示的全局路有表将直接被使用。

       1: public class UrlHelper
       2: {
       3:     //其他成员
       4:     public UrlHelper(RequestContext requestContext);
       5:     public UrlHelper(RequestContext requestContext, RouteCollection routeCollection);
       6:  
       7:     public RequestContext RequestContext { get; }
       8:     public RouteCollection RouteCollection { get;}
       9: }

    再来看看如下所示的HtmlHelper的定义,它同样具有一个表示路由对象集合的RouteCollection属性。和UrlHelper一样,如果在构造函数没有显示指定,那么RouteTable的静态属性Routes表示的RouteCollection对象将会用于初始化该属性。

       1: public class HtmlHelper
       2: {
       3:     //其他成员
       4:     public HtmlHelper(ViewContext viewContext, IViewDataContainer viewDataContainer);
       5:     public HtmlHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection);
       6:  
       7:     public RouteCollection RouteCollection { get; }
       8:     public ViewContext ViewContext { get; }
       9: }
      10: public class ViewContext : ControllerContext
      11: {
      12:     //省略成员
      13: }
      14: public class ControllerContext
      15: {
      16:     //其他成员   
      17:     public RequestContext RequestContext { get; set; }
      18:     public virtual RouteData RouteData { get; set; }
      19: }

    由于HtmlHelper只要在View中使用,所以它具有一个通过ViewContext属性表示的针对View的上下文。至于该属性对应的类型ViewContext,它是表示Controller上下文的ControllerContext的子类,而后者通过RequestContext和RouteData属性提供当前的请求上下文和路由数据(其实RouteData属性表示的RouteData对象已经包含在RequestContext属性表示的RequestContext对象中)。

    二、UrlHelper.Action V.S. HtmlHelper.ActionLink

    UrlHelper和HtmlHelper分别通过Action和ActionLink方法用于生成一个针对某个Controller的某个Action的URL和链接。下面的代码片断列出了UrlHelper的所有Action重载,参数actionName和controllerName分别代表Action和Controller的名称。通过object或者RouteValueDictionary类型表示的routeValues参数表示替换URL模板中变量的变量值。参数protocol和hostName代表作为完整URL的传输协议(比如http和https等)以及主机名。

       1: public class UrlHelper
       2: {
       3:     //其他成员
       4:     public string Action(string actionName);
       5:     public string Action(string actionName, object routeValues);
       6:     public string Action(string actionName, string controllerName);
       7:     public string Action(string actionName, RouteValueDictionary routeValues);
       8:     public string Action(string actionName, string controllerName, object routeValues);
       9:     public string Action(string actionName, string controllerName, RouteValueDictionary routeValues);
      10:  
      11:     public string Action(string actionName, string controllerName, object routeValues, string protocol);
      12:     public string Action(string actionName, string controllerName, RouteValueDictionary routeValues, string protocol, string hostName);
      13: }

    对于定义在UrlHelper中的众多Action方法,如果我们显示指定了传输协议(protocol参数)或者主机名称,返回的是一个完整的URL;否则返回的是一个相对URL。如果我们没有显示地指定Controller的名称(controllerName参数),那么当前Controller的名称被采用。对于UrlHelper来说,通过RequestContext属性表示的当前请求上下文包含了相应的路由信息,即RequestContext的RouteData属性表示的RouteData。RouteData的Values属性中必须包含一个Key为“controller”的元素,其值就代表当前Controller的名称。

    在System.Web.Mvc.Html.LinkExtensions中,我们为HtmlHelper定义了如下所示的一系列ActionLink方法重载。顾名思义,ActionLink不再仅仅返回一个URL,而是生成一个链接(<a>...</a>),但是其中作为目标URL的生成逻辑和UriHelper是完全一致的。

       1: public static class LinkExtensions
       2: {
       3:     //其他成员
       4:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName);
       5:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues);
       6:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName);
       7:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues);
       8:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes);
       9:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes);
      10:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes);
      11:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName,RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes);
      12:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes);
      13:     public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes);   
      14: }

    三、实例演示:创建一个RouteHelper模拟UrlHelper的URL生成逻辑

    为了让读者对UrlHelper如果利用ASP.NET路由系统进行URL生成的逻辑具有一个深刻认识,我们接下来创建一个名为RouteHelper的等效帮助类。我们将RouteHelper定义在创建的一个ASP.NET Web应用中,如下面的代码片断所示,RouteHelper具有RequestContext和RouteCollection两个属性,前者在构造函数中指定,后者则只是使用通过RouteTable的Routes静态属性表示的全局路由表。源代码从这里下载。

       1: public class RouteHelper
       2: {
       3:     public RequestContext RequestContext { get; private set; }
       4:     public RouteCollection RouteCollection { get; private set; }
       5:     public RouteHelper(RequestContext requestContext)
       6:     {
       7:         this.RequestContext = requestContext;
       8:         this.RouteCollection = RouteTable.Routes;
       9:     }
      10:  
      11:     public string Action(string actionName)
      12:     {
      13:         return this.Action(actionName, null, null, null, null);
      14:     }
      15:     public string Action(string actionName, object routeValues)
      16:     {
      17:         return this.Action(actionName, null, 
      18:             new RouteValueDictionary(routeValues), null, null);
      19:     }
      20:     public string Action(string actionName, string controllerName)
      21:     {
      22:         return this.Action(actionName, controllerName, null, null, null);
      23:     }
      24:     public string Action(string actionName, RouteValueDictionary routeValues)
      25:     {
      26:         return this.Action(actionName, null, routeValues, null, null);
      27:     }
      28:     public string Action(string actionName, string controllerName,  object routeValues)
      29:     {
      30:         return this.Action(actionName, controllerName, new RouteValueDictionary(routeValues), null, null);
      31:     }
      32:     public string Action(string actionName, string controllerName, RouteValueDictionary routeValues)
      33:     {
      34:         return this.Action(actionName, controllerName, routeValues, null, null);
      35:     }
      36:     public string Action(string actionName, string controllerName, object routeValues, string protocol)
      37:     {
      38:         return this.Action(actionName, controllerName, new RouteValueDictionary(routeValues), protocol, null);
      39:     }
      40:     public string Action(string actionName, string controllerName, RouteValueDictionary routeValues, string protocol, string hostName)
      41:     {
      42:         controllerName = controllerName ?? (string)this.RequestContext.RouteData.Values["controller"];
      43:         routeValues = routeValues ?? new RouteValueDictionary();
      44:         routeValues.Add("action", actionName);
      45:         routeValues.Add("controller", controllerName);
      46:         string virtualPath = this.RouteCollection.GetVirtualPath(this.RequestContext, routeValues).VirtualPath;
      47:         if (string.IsNullOrEmpty(protocol) && string.IsNullOrEmpty(hostName))
      48:         {
      49:             return virtualPath.ToLower();
      50:         }
      51:  
      52:         protocol = protocol??"http";
      53:         Uri uri = this.RequestContext.HttpContext.Request.Url;
      54:         hostName = hostName ?? uri.Host + ":" + uri.Port;            
      55:         return string.Format("{0}://{1}{2}", protocol, hostName, virtualPath).ToLower();
      56:     }
      57: }

    RouteHelper具有与UriHelper完全一致的Action方法重载定义,而URL的生成最终体现在最后一个Action重载中。具体的逻辑很简单,如果指定的Controller名称为Null,我们通过RequestContext获取出当前Controller名称,然后将Action和Controller名称添加到表示路由变量 列表的RouteValueDictionary对象中(routeValues参数),对应的Key分别是“action”和“controller”

    然后我们调用RouteCollection的GetVirtualPath得到一个VirtualPathData对象。如果既没有显示指定传输协议名称也没有指定主机名称,直接返回VirtualPathData的VirtualPath体现的相对路径,否则生成一个完整的URL。如果没有指定主机名称,我们采用当前请求的主机名称,并且使用当前的端口;如果没有指定传输协议,则直接使用“http”。

    接下来我们在添加的Global.asax中通过如下的代码注册一个URL模板为"{controller}/{action}/{id}”的路由对象。

       1: public class Global : System.Web.HttpApplication
       2: {
       3:     protected void Application_Start(object sender, EventArgs e)
       4:     {
       5:         RouteTable.Routes.MapRoute("default", "{controller}/{action}/{id}");
       6:     }
       7: }

    在添加的Web页面(Default.aspx)中我们通过如下的代码利用我们自定义的RouteHelper生成三个URL。在页面加载事件处理方法中,我们根据手工创建的HttpRequest和HttpResponse创建一个HttpContext对象,并进一步创建HttpContextWrapper对象。然后我们手工创建一个RouteData对象,并针对上面定义的URL模板添加了三个变量元素(controller=home;action=index;id=002),它们实际上和我们创建的HttpRequest的URL是一一匹配的。最后针对创建的HttpContextWrapper对象和RouteData进一步创建RequestContext对象,并最终创建出RouteHelper对象。

       1: public partial class Default : System.Web.UI.Page
       2: {
       3:     protected void Page_Load(object sender, EventArgs e)
       4:     {
       5:         HttpRequest request = new HttpRequest("default.aspx", "http://localhost:3721/home/index/002", null);
       6:         HttpResponse response = new HttpResponse(new StringWriter());
       7:         HttpContext context = new HttpContext(request, response);
       8:         HttpContextBase contextWrapper = new HttpContextWrapper(context);
       9:  
      10:         RouteData routeData = new RouteData();
      11:         routeData.Values.Add("controller", "home");
      12:         routeData.Values.Add("action", "index");
      13:         routeData.Values.Add("id", "002");
      14:         RequestContext requestContext = new RequestContext(contextWrapper, routeData);
      15:         RouteHelper helper = new RouteHelper(requestContext);
      16:  
      17:         Response.Write(helper.Action("GetProduct", "Products",new {id="002"}) + "<br/>");
      18:         Response.Write(helper.Action("GetProduct", "Products", new { id = "002" }, "http") + "<br/>");
      19:         Response.Write(helper.Action("GetProduct", "Products", new RouteValueDictionary { { "id", "002" } }, 
      20:             "https", "www.artech.com") + "<br/>");
      21:     }
      22: }

    我们通过调用RouteHelper其中其中三个Action方法重载生成出三个Url并写入HTTP回复。对于第一个方法调用,我们指定了Action和Controller的名称以及针对变量{id}的值;第二次在这基础上显示指定了传输协议名称http;第三个在同时指定了协议名称(https)和主机名称(www.artech.com)。当我们通过浏览器访问该Web页面的时候,我们会得到如下图所示3个URL。

    clip_image002

    四、UrlHelper.RouteUrl V.S. HtmlHelper.RouteLink

    不论是UrlHelper的Action方法,还是HtmlHelper的ActionLink,生成的URL都是通过一个路由表生成出来的,而在默认的情况下这个路由表就是通过RouteTable的静态属性Routes表示的全局路由表,换句话说,具体使用的总是路由表中第一个匹配的路由对象。但是在有的时候,我们需要针对注册的某个具体的路由对象来生成URL或者对应的链接,这时候就需要使用的UrlHelper和HtmlHelper的另外一组方法了。

    如下面的代码片断所示,UrlHelper定义了一系列的RouteUrl方法。除了第一个重载之外,后面的重载都接受一个路由对象注册名称的参数routeName。和UrlHelper的Action方法一样,我们可以通过参数指定用于替换定义在URL模板中变量的RouteValueDictionary对象(routeValues),以及传输协议和主机名称(hostName)。

       1: public class UrlHelper
       2: {
       3:     //其他成员
       4:     public string RouteUrl(object routeValues);
       5:     public string RouteUrl(string routeName);
       6:     public string RouteUrl(RouteValueDictionary routeValues);
       7:     public string RouteUrl(string routeName, object routeValues);
       8:     public string RouteUrl(string routeName, RouteValueDictionary routeValues);
       9:     public string RouteUrl(string routeName, object routeValues, string protocol);
      10:     public string RouteUrl(string routeName, RouteValueDictionary routeValues, string protocol, string hostName);  
      11: }

    对于没有指定路由对象注册名称的RouteUrl方法来说,它还是利用整个路由表进行URL的生成,如果显示指定了路由对象的注册名称,那么就会从路由表中获取相应的路由对象,如果该路由对象与指定的变量列表不匹配,则返回Null;否则返回生成的URL。

    HtmlHelper也同样定义了类似的RouteLink方法重载用于实现基于指定路由对象的链接生成,具体的RouteLink方法定义如下。

       1: public static class LinkExtensions
       2: {
       3:     //其他成员
       4:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, object routeValues);
       5:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName);
       6:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, RouteValueDictionary routeValues);
       7:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, object routeValues, object htmlAttributes);
       8:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, RouteValueDictionary routeValues);
       9:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes);
      10:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, object routeValues, object htmlAttributes);
      11:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes);
      12:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, string protocol, string hostName, string fragment, object routeValues, object htmlAttributes);
      13:     public static MvcHtmlString RouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes);
      14: }

    ASP.NET MVC路由扩展:路由映射 
    ASP.NET MVC路扩展:链接和URL的生成

    作者:Artech
    出处:http://artech.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    1] 技术剖析

     
    摘要: ASP.NET 路由系统通过注册的路由表旨在实现两个“方向”的路有功能,即针对入栈请求的路由和出栈URL的生成。前者通过调用代表全局路由表的RouteCollection对象的GetRouteData方法实现,后者则依赖于RouteCollection的GetVirtualPathData方法,而最终还是落在继承自RouteBase的路由对象的同名方法的调用上。为了编程的方面,ASP.NET MVC为了设计了HtmlHelper和UrlHelper这两个帮助类,我们可以通过调用它们的ActionLink/RouteLink和Action/RouteUrl根据注册的路有规则生成链接或者URL。从本质上讲,HtmlHelper/UrlHelper实现的对URL的生成最终还是依赖于上面所说的GetVirtualPathData方法。阅读全文
    posted @ 2012-03-27 08:09 Artech 阅读(258) | 评论 (1) 编辑
     
    摘要: 上周我写了三篇文章(一、二、三)详细地介绍了ASP.NET的路由系统。ASP.NET的路由系统旨在通过注册URL模板与物理文件之间的映射进而实现请求地址与文件路径之间的分离,但是对于ASP.NET MVC应用来说,请求的目标不再是一个具体的物理文件,而是定义在某个Controller类型中的Action方法。出于自身路由特点的需要,ASP.NET对ASP.NET的路由系统进行了相应的扩展。阅读全文
    posted @ 2012-03-26 08:14 Artech 阅读(1154) | 评论 (33) 编辑
     
    摘要: 前面我们已经提到过,ASP.NET 的路由系统主要具有两个方面的应用,其一就是通过注册URL模板与物理文件路径的匹配实现请求地址和物理地址的分离;另一个则是通过注册的路由规测生成一个相应的URL。后者通过调用RouteCollection类型的GetVirtualPath方法来实现。[源代码从这里下载]阅读全文
    posted @ 2012-03-21 08:10 Artech 阅读(1653) | 评论 (15) 编辑
     
    摘要: 我们可以通过RouteTable的静态属性Routes得到一个基于应用的全局路由表,这是一个类型的RouteCollection的集合对象,我们可以通过调用它的MapPageRoute进行路由映射。接下来我们通过实现演示的方式来说明路由注册的一些细节问题。阅读全文
    posted @ 2012-03-20 08:29 Artech 阅读(3730) | 评论 (31) 编辑
     
    摘要: 表现为请求地址与目标Controller和Action的动态映射的URL路由系统并不是专属于ASP.NET MVC,而是直接建立在ASP.NET 中。ASP.NET通过URL路由系统实现了请求地址与物理文件的分离。[源代码地址从这里下载]阅读全文
    posted @ 2012-03-19 07:43 Artech 阅读(3327) | 评论 (27) 编辑
     
    摘要: 作为Controller基类ControllerBase的Execute方法的核心在于对Action方法的执行和作为方法返回的ActionResult的执行,两者的执行是通过一个叫做ActionInvoker的组件来完成的。由于Action方法具有相应的参数,在执行Action方法之前必须进行参数的绑定。ASP.NET MVC将这个机制成为Model的绑定,而这又涉及到另一个重要的组件ModelBinder阅读全文
    posted @ 2012-03-12 17:30 Artech 阅读(2184) | 评论 (9) 编辑
     
    摘要: ASP.NET MVC的URL路由系统通过注册的路由表对HTTP请求进行解析从而得到一个用于封装路由数据的RouteData对象,而这个过程是通过自定义的UrlRoutingModule对HttpApplication的PostResolveRequestCache事件进行注册实现的。RouteData中已经包含了目标Controller的名称,现在我们来进一步分析真正的Controller对象是如何被激活的。阅读全文
    posted @ 2012-03-12 09:19 Artech 阅读(2561) | 评论 (5) 编辑
     
    摘要: 在一个ASP.NET MVC应用来说,针对HTTP请求的处理和相应定义Controller类型的某个Action方法中,每个HTTP请求的目标对象不再像ASP .NET Web Form应用一样是一个物理文件,而是某个Controller的某个Action。目标Controller和Action的名称包含在HTTP请求中,而ASP.NET MVC的首要任务就是通过当前HTTP请求的解析得到正确的Controller和Action的名称。这个过程是通过ASP.NET MVC的URL路由机制来实现的。阅读全文
    posted @ 2012-03-11 20:25 Artech 阅读(2082) | 评论 (9) 编辑
     
    摘要: ASP.NET由于采用了管道式设计,具有很好的扩展性,而整个ASP.NET MVC应用框架就是通过扩展ASP.NET实现的。通过上面对ASP.NET管道设计的介绍,我们知道ASP.NET的扩展点只要体现在HttpMoudle和HttpHandler这两个核心组建之上,实际上整个ASP.NET MVC框架就是通过自定义的HttpMoudle和HttpHandler实现的。为了上读者从整体上把握ASP.NET MVC的工作机制,接下来我按照其原理通过一些自定义组件来模拟ASP.NET MVC的运行原理,我们也可以将此视为一个“迷你版”的ASP.NET MVC。阅读全文
    posted @ 2012-03-11 09:34 Artech 阅读(2504) | 评论 (24) 编辑
     
    摘要: 不知道大家是否意识到一个现象,我们所说的Web服务其实并没有直接建立在Web上而是建立在SOAP上。SOAP居然成为了Web服务的标准,以至于我们提到Web服务就会想到SOAP。随着在Web服务中引入了REST架构,SOAP在整个Web服务体系中的垄断地位正在发生改变,或者已经发生了改变。REST提倡一种面向资源的架构(ROA: Resource Oriented Architecture),鼓励我们直接在Web上建立一种轻量级的Web服务。WCF在3.5就提供了对REST的支持,在4.0中对此进行较大的改进。阅读全文
    posted @ 2012-02-15 08:56 Artech 阅读(3891) | 评论 (21) 编辑
     
    摘要: 条件获取(Conditional Update)可以避免相同数据的重复传输,进而提高性能。条件更新(Conditional Update)用于解决资源并发操作问题。如果我们预先获取一个资源进行修改或者删除,条件更新检验帮助我们确认资源被获取出来到针对它的修改/删除操作被提交的这段时间内是否被其他人改动过。阅读全文
    posted @ 2012-02-14 08:41 Artech 阅读(2069) | 评论 (5) 编辑
     
    摘要: ASP.NET的输出缓存(Output Caching)机制允许我们针对整个Web页面或者页面的某个部分(主要针对用户控件)最终呈现的HTML进行缓存。对于后续针对相同资源的请求,只需要直接将缓存的HTML予以回复而无须按照页面处理生命周期对每次请求进行重复处理。WCF通过操作行为AspNetCacheProfileAttribute利用ASP.NET的输出缓存提供一种针对于某个操作的声明式缓存机制。阅读全文
    posted @ 2012-02-10 08:58 Artech 阅读(2520) | 评论 (16) 编辑
     
    摘要: REST服务采用面向资源的架构,而资源通过URI进行标识和定位,所以URI在REST中具有重要的地位。对于WCF来说,服务调用请求的URI映射为某个具体的操作,所以服务端需要解决的是如何根据请求URI选择出对应的操作。如果采用SOAP,操作的选择是根据消息的报头来实现的,那么REST服务又采用怎样的操作选择机制呢?阅读全文
    posted @ 2012-02-09 09:13 Artech 阅读(1208) | 评论 (11) 编辑
     
    摘要: WCF为REST服务的寄宿提供了一个新的ServiceHost,即WebServiceHost。WebServiceHost是ServiceHost的子类,而WebServiceHostFactory是对应的ServiceHostFactory,在基于IIS/WAS寄宿中被使用。由于对REST服务绝大部分功能的支持都是通过WebHttpBehavior这么一个终结点行为实现的,所以WebServiceHost的核心功能就是将该终结点行为应用到寄宿服务的所有终结点。除此之外,WebServiceHost还具有一些额外的功能,这些功能都是通过重写OnOpening方法实现的。阅读全文
    posted @ 2012-02-08 09:00 Artech 阅读(2630) | 评论 (15) 编辑
     
    摘要: 可以说WebHttpBinding和WebHttpBehavior是整个Web HTTP编程模型最为核心的两个类型,前者主要解决消息编码问题,而余下的工作基本上落在了终结点行为WebHttpBehavior上。WebHttpBehavior属性HelpEnabled和AutomaticFormatSelectionEnabled是“帮助页面”与“自动消息格式选择”这两个特性的总开关。阅读全文
    posted @ 2012-02-07 08:37 Artech 阅读(2194) | 评论 (15) 编辑
     
    摘要: 我们知道请求消息和回复消息分别是对操作方法输入参数和返回值(输出参数和引用参数)的封装,而请求消息和回复消息的主体具有两种不同的风格,即Bare和Wrapped。的Bare表示请求消息和回复消息的主体部分仅仅包含针对输入参数和返回值(输出参数和引用参数)序列化后的内容,而Wrapped则会在外面包装一个基于当前操作的“封套”。阅读全文
    posted @ 2012-02-06 08:52 Artech 阅读(2100) | 评论 (10) 编辑
     
    摘要: 不论是我们采用SOAP还是REST架构风格,运行时框架体系依然不曾改变,终结点也仍旧是通信的核心。在Web HTTP编程模型中,我们采用基于WebHttpBinding绑定的终结点。绑定是一组相关绑定元素的有序组合,绑定的特性与能力决定于它包含的绑定元素,在这里我们通过分析绑定元素的方式来剖析WebHttpBinding绑定与其它绑定有何不同阅读全文
    posted @ 2012-02-05 09:36 Artech 阅读(2471) | 评论 (14) 编辑
     
    摘要: 微软在WCF 3.5中就通过提供基于Web HTTP的编程模式使我们很容易地创建基于REST的服务,WCF 4.0中对此进行了较大的改进。为了让读者对REST在WCF中的应用有一个大致的了解,我们先来进行一个简单的实例演示。阅读全文
    posted @ 2012-02-04 11:47 Artech 阅读(2782) | 评论 (28) 编辑
     
    摘要: 本篇文章介绍可以算是WCF 4.0基于限流(Throttling)的新特性,是在修订《WCF技术剖析(卷1)》的时候编写演示实例的时候发现的。这个特性没有出现在官方文档上面,至少在MSDN上的相关介绍依然是错误的。阅读全文
    posted @ 2011-12-31 12:49 Artech 阅读(3805) | 评论 (113) 编辑
     
    摘要: 在《通过一个模拟程序让你明白ASP.NET MVC是如何运行的》一文中我通过一个普通的ASP.NET Web程序模拟了ASP.NET MVC的执行流程,现在我们通过类似的原理创建一个用于模拟WCF服务端和客户端工作原理的模拟程序。[源代码从这里下载]阅读全文
    posted @ 2011-12-07 21:25 Artech 阅读(4050) | 评论 (26) 编辑
     
    摘要: ASP.NET MVC的路由系统通过对HTTP请求的解析得到表示Controller、Action和其他相关的数据,并以此为依据激活Controller对象,调用相应的Action方法,并将方法返回的ActionResult写入HTTP回复中。为了更好的演示其实现原理,我创建一个简单的ASP.NET Web应用来模拟ASP.NET MVC的路由机制。这个例子中的相关组件基本上就是根据ASP.NET MVC的同名组件设计的,只是我将它们进行了最大限度的简化,因为我们只需要用它来演示大致的实现原理而已。阅读全文
    posted @ 2011-12-05 19:52 Artech 阅读(4085) | 评论 (34) 编辑
     
    摘要: 在定义和寄宿WCF服务的时候会面临三个名称/命名空间,它们分别是ServiceContractAttribute、ServiceBehaviorAttribute和Binding的Name和Namespace属性,很对人对此不能很好地区分。阅读全文
    posted @ 2011-11-13 10:00 Artech 阅读(4171) | 评论 (13) 编辑
     
    摘要: 现在我们通过一个实例来演示终结点的地址报头如何影响实现终结点选择的消息筛选机制。这个实例通过为服务端终结点指定地址报头实现针对客户端的授权,让经过许可的客户端才能访问这个服务。具体来说,我们将一个代码序列号的GUID作为终结点的地址报头。对于客户端发送的消息,只有具有相应的报头才能访问服务。阅读全文
    posted @ 2011-11-12 10:44 Artech 阅读(1993) | 评论 (7) 编辑
     
    摘要: 终结点是整个WCF的核心,由经典的ABC三要素组成。作为表示地址的EndpointAddress,很多人仅仅将其看成是一个表示标识服务并且表示服务所在地址的Uri,其实服务标识和定位服务仅仅是EndpointAddress一个基本的功能,它不仅仅是Uri那么简单。阅读全文
    posted @ 2011-11-11 12:59 Artech 阅读(2897) | 评论 (10) 编辑
     
    摘要: 作为.NET Framework的一部分,几乎每个版本.NET Framework的推出都会为WCF带来一些改变。针对于最新版本的.NET Framework 4.0,一些新的特性被引入到WCF。对于这些基于.NET Framework版本的更替而带来的针对WCF的变化,我个人是这么看待的:WCF在随着.NET Framework 3.0发布的时候就具有一个成熟的架构设计,可扩展性即使一个重要的衡量标准。基于后续版本的.NET Framework发布的WCF并没有像WF一样出现“革新”型的改变,很多都是利用了这个可扩展性的通信平台开发出来的新特性,WCF 4.0也不例外。阅读全文
    posted @ 2011-10-28 08:41 Artech 阅读(6588) | 评论 (18) 编辑
     
    摘要: WCF所谓的安全审核就是针对认证和授权所做的针对EventLog的日志记录。我们不但可以设置进行审核的事件(认证成功/失败,授权成功或失败),还可以选择记录信息被写入的EventLog类型,即应用程序日志还是安全日志。WCF的安全审核是通过ServiceSecurityAuditBehavior服务行为实现的。阅读全文
    posted @ 2011-10-27 08:17 Artech 阅读(2244) | 评论 (9) 编辑
     
    摘要: 在Managed模式下,可用服务的终结点通过发现代理来统一管理。客户端在进行可用目标服务探测和解析的时候直接向发现代理进行探测和解析请求就可以了。这篇文章通过一个简单的实例为你演示如果通过创建发现代理实现可用服务的实时维护。服务可以在上下线的时候自动注册和注销,客户端可以动态地向发现代理查询当时可用的服务。阅读全文
    posted @ 2011-10-26 09:12 Artech 阅读(1957) | 评论 (7) 编辑
     
    摘要: 在《原理篇》我们对客户端如何监听通知,以及服务在上下线时如何发送通知从原理上进行了深入地剖析。我们现在通过一个简单的实例演示如何通过ServiceDiscoveryBehavior服务行为为寄宿的服务添加一个实现上/下线通知的AnnouncementEndpoint终结点,以及客户端如何通过对AnnouncementService服务的寄宿实现对通知的监听和接收。[阅读全文
    posted @ 2011-10-25 12:00 Artech 阅读(2241) | 评论 (6) 编辑
     
    摘要: 到目前为止,我们所介绍的都是基于客户端驱动的服务发现模式,也就是说客户端主动发出请求以探测和解析可用的目标服务。在介绍WS-Discovery的时候,我们还谈到另外一种服务驱动的模式,即服务在上线和下线的时候主动对外发出Hello/Bye通知。阅读全文
    posted @ 2011-10-25 08:37 Artech 阅读(2856) | 评论 (9) 编辑
     
    摘要: 前面两篇我们分别介绍了可被发现服务如何被发布,以及客户端如果探测可用的服务。接下来我们通过一个简单的例子来演示如果创建和发布一个可被发现的服务,客户端如何在不知道服务终结点地址的情况下动态探测可用的服务并调用之。阅读全文
    posted @ 2011-10-09 09:26 Artech 阅读(2297) | 评论 (14) 编辑
     
    摘要: 在《服务如何能被”发现”》中我们着重讨论了可被发现的服务(Discoverable Service)如何通过ServiceDiscoveryBehavior行为的服务通过标准终结点DiscoveryEndpoint发布出来。现在我们来谈服务发现的另一个方面:客户端如何动态地探测可用的目标服务?阅读全文
    posted @ 2011-10-09 07:11 Artech 阅读(2937) | 评论 (7) 编辑
     
    摘要: 要让作为服务消费者的客户端能够动态地发现可用的服务,首先的要求服务本身具有可被发现的特性。那么到底一个可被发现的服务和一个一般的服务有何不同呢?或者说如何让一个一般的服务在寄宿的时候能够被它潜在的消费者“探测”到呢?阅读全文
    posted @ 2011-10-08 08:09 Artech 阅读(2777) | 评论 (13) 编辑
     
    摘要: 我们传统的服务调用的模式都是这样的:客户端在设计时就预先知道目标服务的地址,并基于这个地址创建客户端终结点对服务进行调用。而我们即将介绍的新特性则是你在预先不知道目标服务的地址的情况下,可以动态地探测可用的服务并调用之。WCF-Discovery并不是微软在.NET平台下的闭门造车,而是基于一个开放的标准,即我们接下来着重介绍的WS-Discovery。也就是说,如果JAVA平台的Web服务也是基于相同的WS-Discovery标准,那么它们也可以被WCF客户端“发现”。阅读全文
    posted @ 2011-10-07 19:25 Artech 阅读(2114) | 评论 (9) 编辑
     
    摘要: 今天写《WCF技术剖析(卷2)》关于“队列服务”部分,看了《WCF服务编程》相关的内容。里面介绍一个关于“终结点不能共享相同的消息队列”说法,个人觉得这值得商榷。撰写此文,希望对此征求大家的意见。阅读全文
    posted @ 2011-10-06 16:00 Artech 阅读(2263) | 评论 (7) 编辑
     
    摘要: 在本篇文章中,我们将通过一个具体的实例来演示如何通过路由服务。在这个例子中,我们会创建连个简单的服务HelloServie和GoodbyeService。假设客户端不能直接调用这两个服务,需要使用到路由服务作为两者之间的中介。阅读全文
    posted @ 2011-09-25 08:24 Artech 阅读(2525) | 评论 (29) 编辑
     
    摘要: 在一个典型的服务调用场景中,具有两个基本的角色,即服务的消费者和服务的提供者。从消息交换的角度讲前者一般是消息的最初发送者,而后者则是消息的最终接收者。在很多情况下,由于网络环境的局限,消息的最初发送者和最终接收者不能直接进行消息交换,这就需要一个辅助实现消息路由的中介服务,这就是我们接下来要介绍的路由服务。阅读全文
    posted @ 2011-09-23 14:51 Artech 阅读(2210) | 评论 (19) 编辑
     
    摘要: 很多WCF的初学者是从之前的Web服务上转移过来的,他们非常怀念.asmx Web服务无配置的服务寄宿方式。你只需要在定义Web服务的时候再表示服务操作的方法上应用WebMethodAttribute特性就可以了,完全可以不需要手工进行相应的配置。WCF 4.0通过默认终结点添加机制为你提供无配置服务寄宿的支持。阅读全文
    posted @ 2011-09-18 16:57 Artech 阅读(3833) | 评论 (11) 编辑
     
    摘要: WCF从第一个版本的推出到现在,整个架构体系基本上没有出现大的变化。在我看来,可扩展性的设计是WCF的架构体系能够在一段不短的时期内保持稳定的一个最主要的原因。而反观于WCF几乎同时推出的WF,各个版本演进的历史,你会发现几乎WF推出的每一个版本都是“革新性”的改变。正是因为WCF具有极大的扩展性,WCF新的版本的功能本身就可以通过这些丰富的扩展点来实现,而作为最终使用者的我们也可以实现我们自己的扩展,使WCF能够按照我们希望的方式来运作。阅读全文
    posted @ 2011-09-16 09:05 Artech 阅读(3552) | 评论 (19) 编辑
     
    摘要: 在《原理篇》中我们谈到了通过自定义ServiceHost对WCF进行扩展的本质,以及在IIS/WAS寄宿情况下ServiceHostFactory的作用。接下来通过一个具体的例子来演示如何通过WCF扩展实现以Unity为代表的IoC框架的集成,以及应用该扩展的ServiceHost和ServiceHostFactory如何定义。阅读全文
    posted @ 2011-09-15 11:30 Artech 阅读(2130) | 评论 (17) 编辑
     
    摘要: 在创建ServiceHost的时候,WCF会加载服务相关的配置并将其作为服务的描述信息附加到ServiceHost对象上,我们也可以在开启ServiceHost之前对其服务描述信息进行相应的修改。ServiceHost在开启之前具有的服务描述信息将会决定在开启之后创建的服务端运行时框架。所以如果我们通过自定义ServiceHost对象并根据具体应用场景的具体需求对其服务描述进行定制,同样可以起到对WCF服务端进行扩展的目的。阅读全文
    posted @ 2011-09-14 09:51 Artech 阅读(2185) | 评论 (3) 编辑
     
    摘要: 为了让读者对如何利用相应的行为对WCF进行扩展有个深刻的认识,在这里我提供一个简单的实例演示。本实例模拟的场景是这样的:我们创建一个支持多语言的资源服务,该服务旨在为调用者提供基于某种语言的文本型资源。但是,我们不希望客户端在每次调用服务的时候都显式地制定具体的语言,而是根据客户端服务调用线程表示语言文化的上下文来自动识别所需的语言。阅读全文
    posted @ 2011-09-13 08:27 Artech 阅读(2287) | 评论 (25) 编辑
     
    摘要: 作为最为常用的扩展方式,WCF的四大行为的使用主要体现在两个方面:其一、WCF自身提供的很多特性和功能是通过行为的方式来实现的;其二、作为使用WCF的应用,可以通过自定义的行为来实现解决具体问题的扩展。本篇文章为你讲述WCF四大行为(服务行为、终结点行为、契约行为和操作行为)的本质。阅读全文
    posted @ 2011-09-12 10:09 Artech 阅读(2807) | 评论 (10) 编辑
     
    摘要: 当基于某个终结点创建的ChannelFactory被开启的之后,位于服务模型层的客户端运行时框架被成功构建。站在编程的角度看ChannelFactory,它就是一个创建用于服务调用的服务代理对象的工厂。由于服务调用需要借助于服务代理来完成,我们很有必要从整个客户端运行架构层面来了解服务代理和基于服务代理的服务调用是如何实现的。阅读全文
    posted @ 2011-09-10 11:04 Artech 阅读(1918) | 评论 (9) 编辑
     
    摘要: 对于一般的编程人员来说,进行WCF的服务调用之需要通过添加服务引用通过获取元数据生成服务代理类型,或者直接通过ChannelFactory创建用于服务调用的代理对象即可。但是比是否知道当我们创建、开启ChannelFactory的时候,以及用它来创建服务代理的是否WCF内部为我们作了哪些工作?对于一个简单的服务调用,WCF客户端又是采用怎样的处理流程?本篇文章将会给你答案。阅读全文
    posted @ 2011-09-09 18:30 Artech 阅读(3312) | 评论 (23) 编辑
     
    摘要: 终结点分发器在自己的运行时中对请求消息的处理最终肯定体现在相应操作的执行。如果从服务描述的角度来看,操作是一个OperationDescription对象。而服务端分发运行时中的操作则代表的是一个DispatchOperation对象。作为服务描述的一部分,服务所有终结点的所有操作描述(OperationDescription)在ServiceHost创建过程中被创建。而当ServiceHost被正常开始时,这些操作描述最终转换成分发操作(DispatchOperation)。而DispatchRuntime的Operations属性代表了对应终结点的所有分发操作。阅读全文
    posted @ 2011-07-24 22:07 Artech 阅读(3380) | 评论 (8) 编辑
     
    摘要: 作为WCF中一个核心概念,终结点在不同的语境中实际上指代不同的对象。站在服务描述的角度,我们所说的终结点实际上是指ServiceEndpoint对象。如果站在WCF服务端运行时框架来说,终结点实际上指代的是终结点分发器(EndpointDispatcher)。两者是一一匹配的,并且前者是创建后者的基础。而终结点分发器具有自己的运行,即分发运行时(DispatchRuntime)。阅读全文
    posted @ 2011-07-23 15:07 Artech 阅读(3025) | 评论 (18) 编辑
     
    摘要: 在这篇文章中,我们对信道分发器(ChannelDispatcher)本身作一个深入的了解,首先来看看它具有哪些可供扩展的组件,以及我们可以针对信道分发器对WCF实现哪些可能的扩展。阅读全文
    posted @ 2011-07-18 22:12 Artech 阅读(3325) | 评论 (16) 编辑
     
    摘要: WCF的服务端架构体系又可以成为服务寄宿端架构体系。我们知道,对于一个基于某种类型的服务进行寄宿只需要使用到一个唯一的对象,那就是ServiceHost。甚至在某种语境下,我们所说的服务实际上就是指的对应的ServiceHost对象。整个服务寄宿过程包括两个阶段,即服务描述的创建和服务端运行框架的建立。而第一个阶段创建的服务描述是为了第二个阶段对服务端运行时框架建立服务的。阅读全文
    posted @ 2011-07-17 22:10 Artech 阅读(4663) | 评论 (16) 编辑
     
    摘要: 对于WCF服务来说,一个服务具有若干操作,而这些操作由于提供的功能或者内部访问的资源不同,需要进行不同的权限设置。借助于.NET安全相关的应用编程接口,我们可以通过声明的方式将某个服务操作与调用该操作应当具有的权限集进行关联。在运行时,当调用某个服务操作的用户被成功认证后,它具有的权限集被获取出来并绑定到当前安全上下文。WCF框架本身在试图执行目标操作之前可以根据当前安全上下文确定该用户是否有权限执行该服务操作。阅读全文
    posted @ 2011-07-12 22:13 Artech 阅读(4115) | 评论 (12) 编辑
     
    摘要: 在《模拟(Impersonation)与委托(Delegation)》一文中,我们对模拟和委托这两个概念以及相关编程实现进行了详细说明。如果将模拟使用在WCF上面,就意味着WCF可以模拟客户端身份(而不是启动寄宿进程的Windows帐号)执行服务操作。这篇文章主要介绍WCF关于模拟的编程。阅读全文
    posted @ 2011-07-12 22:05 Artech 阅读(1652) | 评论 (0) 编辑
     
    摘要: 在《原理篇》中,我们谈到WCF自定义授权体系具有两个核心的组件:AuthorizationPolicy和ServiceAuthorizationManager,已经它们是如何写作最终提供一种基于声明的授权实现。为了让自定义授权有深刻的理解,我们来进行一个简单实例来演示如何通过自定义这两个组件实现“非角色授权策略”。阅读全文
    posted @ 2011-07-11 22:16 Artech 阅读(2265) | 评论 (9) 编辑
     
    摘要: 到目前为止,我么介绍的授权策略都是围绕着安全主体进行的,基本上都是基于角色的授权。虽然角色是定义权限最为常用的形式,但是它解决不了授权的所有问题。有时候授权需要通过一个复杂的表达式来表示,而且其中会涉及诸多元素,比如身份、角色和组织等。一句话,如果简单的基于角色的授权不能解决我们的问题,我们需要自定义授权策略。阅读全文
    posted @ 2011-07-11 21:13 Artech 阅读(2929) | 评论 (4) 编辑
     
    摘要: 在《原理篇》中我们谈到:如果采用自定义安全主体权限模式,我们可以通过自定义AuthorizationPolicy或者ServiceAuthorizationManager实现对基于当前认证用于相关的安全主体的提供,进而达到授权的目的。为了让大家对此有个更加深刻的认识,在这篇文章中我们会提供一个具体的例子。阅读全文
    posted @ 2011-07-09 20:35 Artech 阅读(1658) | 评论 (25) 编辑
     
    摘要: 在《通过扩展自行实现服务授权》一文中,我通过自定义CallContextInitializer的方式在操作方法之前之前根据认证用户设置了当前线程的安全主体,从而实现授权的目的。实际上,WCF的安全体系本就提供相应的扩展,使你能够自由地实现安全主体的提供方式。具体来说,安全主体的提供可以通过自定AuthorizationPolicy或者ServiceAuthorizationManager来实现。阅读全文
    posted @ 2011-07-07 22:07 Artech 阅读(2885) | 评论 (4) 编辑
     
    摘要: 其实针对安全主体的授权实现的原理很简单,原则上讲,只要你能在服务操作执行之前能够根据本认证的用户正确设置当前的安全主体就可以了。如果你了解WCF的整个运行时框架结构,你会马上想到用于授权的安全主体初始化可以通过自定义CallContextInitializer来实现。阅读全文
    posted @ 2011-07-05 19:01 Artech 阅读(4264) | 评论 (18) 编辑
     
    摘要: 为了让读者对基于ASP.ENT Roles授权方式有一个全面的认识,我们现在来做一个实例演示。在这个实例中,我们将采用不同的认证方式,包括Windows认证和证书认证(ASP.NET Membership + Roles为常见的组合方式,在这里就不多作演示)。阅读全文
    posted @ 2011-07-04 19:43 Artech 阅读(1804) | 评论 (11) 编辑
     
    摘要: 在采用Windows认证的情况下,使用基于Windows用户组安全主体权限模式是一个不错的选择,但是采用ASP.NET Roles却可以使用与任何类型的客户端凭证和认证模式。甚至可以这么说,绝大部分基于角色的授权都可以通过ASP.NET Roles来实现。阅读全文
    posted @ 2011-07-04 13:46 Artech 阅读(3314) | 评论 (3) 编辑
     
    摘要: 由于服务操作是在寄宿进程中执行,在默认的情况下,服务操作是否具有足够的权限访问某个资源(比如文件)决定于执行寄宿进程Windows帐号的权限设置,而与作为客户端的Windows帐号无关。在有多情况下,我们希望服务操作执行在基于客户端的安全上下文中执行,以解决执行服务进行的帐号权限不足的问题。这就涉及到一个重要的话题——模拟与委托。阅读全文
    posted @ 2011-07-03 15:00 Artech 阅读(2871) | 评论 (11) 编辑
     
    摘要: 为了让读者对基于Windows用户组的授权具有深刻的认识,接下来我们通过一个简单的事例来讲解在真正的应用中该授权模式如何使用。对于接下来演示的事例,我们将采用Windows认证和授权。至于授权的最终实现,我们采用的是在服务方法上面应用PrincipalPermissionAttribute特性方式的声明式授权。阅读全文
    posted @ 2011-07-02 22:58 Artech 阅读(2372) | 评论 (14) 编辑
     
    摘要: Windows用户组安全主体权限模式,顾名思义,就是将利用Windows安全系统将对应的Windows帐号所在的用户组作为该用户权限集的授权方式。认证和授权密不可分,但是对于认证和授权在WCF安全体系中的实现来说,它们则是相对独立的。认证属于安全传输的范畴,是在信道层实现的,而授权则是在服务模型层实现的。但是对于基于Windows用户组的授权来说,最终体现出来的授权行为却和采用何种认证具有密切的关系。阅读全文
    posted @ 2011-07-02 11:35 Artech 阅读(3529) | 评论 (5) 编辑
     
    摘要: 前面的两篇文章主要探讨基于安全主体的授权。通过这些介绍我们知道:如果我们在实施授权的时候,当前线程的安全主体能够被正确设置,我们就可以正确地完成授权。安全主体具有两个基本的要素:身份与权限。身份在客户端经过认证之后已经确立下来,现在需要解决的问题就是如何获取被认证用户的权限。为了解决这个问题,WCF为我们提供了三种不同的方案。阅读全文
    posted @ 2011-07-01 22:44 Artech 阅读(3490) | 评论 (10) 编辑
     
    摘要: 毫不夸张地说,安全主体(Principal)是整个授权机制的核心。我们可以简单地将将安全主体定义成能够被成功实施授权的主体。一个安全主体具有两个基本的要素:基于某个用户的安全身份和该用户具有的权限。绝大部分的授权都是围绕着“角色”进行的,我们将一组相关的权限集和一个角色绑定,然后分配给某个用户。所以在基于角色授权环境下,我们可以简单地将安全主体表示成:身份 + 角色。阅读全文
    posted @ 2011-06-30 14:57 Artech 阅读(3139) | 评论 (14) 编辑
     
    摘要: 我们为应用建立安全保障体系的一个重要的目的在于:通过权限控制让用户只能执行被允许的功能,访问被许可的资源。这就是本系列文章讨论的主题授权。对于WCF服务来说,一个服务具有若干操作,而这些操作由于提供的功能或者内部访问的资源不同,需要进行相应的授权。在正式介绍WCF授权之前,先来谈谈两个重要的概念:身份与安全主体。阅读全文
    posted @ 2011-06-29 22:56 Artech 阅读(3329) | 评论 (22) 编辑
     
    摘要: 对消息进行签名和加密分别解决了消息的一致性和机密性问题。而最终是仅仅采用签名还是签名与加密共用取决于契约中对消息保护级别的设置。但是具体的签名和加密在整个WCF框架体系中如何实现?是采用对称加密还是非对称加密?密钥如何而来?相信这些问题在本篇文章中你会找到答案阅读全文
    posted @ 2011-06-27 07:40 Artech 阅读(1440) | 评论 (8) 编辑
     
    摘要: 在《上篇》中,我们着重讨论了消息的保护等级如果在契约中定义,定义在不同契约(服务契约、错误契约和消息契约)中的消息保护等级具有怎样的层级关系,以及在默认情况下各种绑定采用怎样的保护等级。在下篇中,我们进一步来探讨消息保护等级和绑定的关系。阅读全文
    posted @ 2011-06-21 23:04 Artech 阅读(2381) | 评论 (12) 编辑
     
    摘要: 到目前为止,对于WCF安全传输的三个方面,我们已经对认证进行了详细的介绍,现在我们来关注另外两个话题:消息的一致性和机密性,两者又统称为消息保护(Message Protection)。消息安全等级指的是对整个消息或者消息的某个部分实施安全保护采用的等级。按照级别由低到高,WCF支持三种不同的安全等级阅读全文
    posted @ 2011-06-20 23:20 Artech 阅读(2757) | 评论 (25) 编辑
     
    摘要: 前面介绍Windows认证和用户名/密码认证这两种典型的客户端认证模式,我们最后来介绍最后一种客户端认证方式,即客户端凭证类型为X.509证书时服务端采用的认证,简称为证书认证。本篇文章主要涉及两个主题:在客户端如何设置X.509证书作为客户端凭证;在服务端如何设置不同的模式来对客户端的证书凭证进行认证阅读全文
    posted @ 2011-06-15 22:01 Artech 阅读(4162) | 评论 (16) 编辑
     
    摘要: 对于基于Internet的应用,基于用户名和密码的认证方式是最为常用的,而WCF为你提供了不同模式的用户名认证方式:Windows、MembershipProvider和Custom阅读全文
    posted @ 2011-06-13 21:13 Artech 阅读(3181) | 评论 (16) 编辑
     
    摘要: 结束了服务认证的介绍之后,我们接着介绍WCF双向认证的另一个方面,即服务对客户端的认证,简称客户端认证。客户端认证采用的方式决定于客户端凭证的类型,内容只要涉及基于以下三种典型客户凭证类型的认证:Windows、用户名和X.509证书。先来谈谈Windows认证阅读全文
    posted @ 2011-06-12 21:17 Artech 阅读(3370) | 评论 (16) 编辑
     
    摘要: 在采用TLS/SSL实现Transport安全的情况下,客户端对服务证书实施认证。但是在默认情况下,这种认证仅仅是确保服务证书的合法性(通过数字签名确保证书确实是由申明的CA颁发)和可信任性(证书或者CA证书存储于相应的可信赖存储区)。而WCF提供服务证书并不限于此,客户端对服务认证的模式应该是这样的:服务端预先知道了服务的身份,在进行服务调用之前,服务端需要提供相应的凭证用以辅助客户端确认调用的服务具有预先确定的身份。对于这样的服务认证模式,具有两个重要的概念,即服务凭证和服务身份。阅读全文
    posted @ 2011-06-12 11:40 Artech 阅读(2944) | 评论 (6) 编辑
     
    摘要: 上一篇演示的是绑定类型为NetTcpBinding情况下基于TLS/SSL的Transport安全模式的实现,接下来我们改用另外一种绑定:WS2007HttpBinding。对于基于HTTP的绑定,Transport安全模式的实现方式又根据寄宿方式的不同而具有一定的差异阅读全文
    posted @ 2011-06-02 22:32 Artech 阅读(3461) | 评论 (12) 编辑
     
    摘要: 在接下来的系列文章中我们正是讨论关于身份认证的主题。在前面我们已经谈到了,WCF中的认证属于“双向认证”,既包括服务对客户端的认证(以下简称客户端认证),也包括客户端对服务的认证(以下简称服务认证)。对于TLS/SSL来说,客户端和服务在为建立安全上下文而进行的协商过程中会验证服务端的X.509证书如否值得信任。对于服务证书的验证实际上可以看成是一种服务认证,或者说TLS/SSL对证书的验证可以看成是WCF服务认证的一个环节。阅读全文
    posted @ 2011-05-29 14:14 Artech 阅读(2241) | 评论 (10) 编辑
     
    摘要: 对于常用的几种绑定类型,它们都支持怎样的安全模式,以及针对各种安全模式可以采用怎样的认证方式(通过客户端凭证类型决定),这些都在前面的一系列文章中进行了详细的介绍。接下来我们通过表格的形式对不同类型的系统预定义对不同的安全模式进行一下总结。阅读全文
    posted @ 2011-05-28 11:17 Artech 阅读(3546) | 评论 (13) 编辑
     
    摘要: 在前面两篇中,我们详细地介绍了四种基于HTTP的绑定分别支持的安全模式,已经在相应的安全模式下可以采用怎样的客户端凭证。在本篇文章中,我们安全线相同的方式来介绍三种基于局域网的绑定,即NetNamedPipeBinding、NetTcpBinding与 NetMsmqBinding。阅读全文
    posted @ 2011-05-27 22:48 Artech 阅读(3634) | 评论 (4) 编辑
     
    摘要: 在上一篇文章中,我们详细地介绍了BasicHttpBinding具有怎样的安全模式的支持,已经在各种安全模式下分别可以采用怎样的客户端凭证。接下来我们来进一步分析另外三个基于HTTP的绑定,即WSHttpBinding、WS2007HttpBinding和WSDualHttpBinding。阅读全文
    posted @ 2011-05-26 20:24 Artech 阅读(4102) | 评论 (13) 编辑
     
    摘要: 整个安全传输是在WCF的信道层进行的,而绑定是信道层的缔造者,所以终结点采用哪种类型的绑定以及对绑定的属性进行怎样的设置决定了信道层最终采用何种机制实现消息的安全传输。具体来说,我们可以通过绑定设置最终采用的安全模式,以及基于相应安全模式下进行认证和消息保护的行为。至于认证,最终采用怎样的认证方式是由客户端凭证决定的。阅读全文
    posted @ 2011-05-25 18:32 Artech 阅读(2922) | 评论 (4) 编辑
     
    摘要: 在《上篇》中,我们谈到了常用的认证方式:用户名/密码认证和Windows认证。在下篇中,我们着重来介绍另外一种重要的凭证类型:X.509证书,以及针对X.509证书的认证方式。不过为了让读者能够真正地全面地了解X.509证书,本篇文章还提供一些基本的关于非对称加密的背景知识。阅读全文
    posted @ 2011-05-23 20:55 Artech 阅读(3668) | 评论 (14) 编辑
     
    摘要: 如果要给认证下一个定义,我个人的倾向这样的定义:认证是确定被认证方的真实身份和他或她申明(Claim)的身份是否相符的行为。认证方需要被认证方提供相应的身份证明材料,以鉴定本身的身份是否与声称的身份相符。在计算机的语言中,这里的身份证明有一个专有的名称,即“凭证”,或者用户凭证、认证凭证。阅读全文
    posted @ 2011-05-23 07:39 Artech 阅读(4377) | 评论 (23) 编辑
     
    摘要: WCF的安全体系主要包括三个方面:传输安全、授权或者访问控制以及审核。而传输安全又包括两个方面:认证和消息保护。认证帮助客户端或者服务确认对方的真实身份,而消息保护则通过签名和加密实现消息的一致性和机密性。WCF采用两种不同的机制来解决这三个涉及到传输安全的问题,我们一般将它们称为不同的安全模式,即Transport安全模式和Message安全模式。阅读全文
    posted @ 2011-05-22 16:09 Artech 阅读(4750) | 评论 (43) 编辑
     
    摘要: 条件编译,顾名思义,就是根据在编译时指定的条件决定最后需要编译的代码。条件编译是我们可以针对某些特性的环境编写相应的代码,比如有写的代码只需要在Debug模式下才需要执行,有些代码仅仅是为了在SIT或者UAT环境下有效地进行Troubleshooting,而在Production环境下则不应该执行。通过条件编译机制,我们可以针对某中特定的“条件编译符(Conditional Compilation Symbol)”编写相应的代码。在进行最终编译的时候,通过指定的条件编译符,编译器判断这些特殊的代码是否应该被编译。阅读全文
    posted @ 2011-04-06 16:21 Artech 阅读(3853) | 评论 (13) 编辑
     
    摘要: 《上篇》中我们介绍Kerberos认证的整个流程。在允许的环境下,Kerberos是首选的认证方式。在这之前,Windows主要采用另一种认证协议——NTLM。较之Kerberos,基于NTLM的认证过程要简单很多。NTLM采用一种质询/应答消息交换模式完成对请求者的认证。阅读全文
    posted @ 2011-01-25 12:37 Artech 阅读(6296) | 评论 (12) 编辑
     
    摘要: 最近一段时间都在折腾安全(Security)方面的东西,比如Windows认证、非对称加密、数字证书、数字签名、TLS/SSL、WSS等。如果时间允许,我很乐意写一系列的文章与广大网友分享、交流。对于很多读者来说,今天讨论的可能是一个既熟悉、又陌生的话题——Windows认证。阅读全文
    posted @ 2011-01-24 21:57 Artech 阅读(5063) | 评论 (34) 编辑
     
    摘要: 在《上篇》中我们揭示了“缺省参数”的本质,现在我们接着来谈谈C#4.0中另一个重要的新特性:协变(Covariance)与逆变(Contravariance)。对于协变与逆变,大家肯定不会感到陌生,但是我相信有很多人不能很清晰地说出他们之间的区别。我希望通过这篇文章能够让读者更加深刻的认识协变与逆变。但是也不排除另一种可能,那就是读者这篇文章你对这两个概念更加模糊。文章一些内容仅代表个人观点,如有不妥,还望指正。阅读全文
    posted @ 2011-01-13 21:08 Artech 阅读(11539) | 评论 (99) 编辑
     
    摘要: C#4.0关于缺省参数的新特性,相信大家都不会陌生。所谓缺省参数,顾名思义,就是在声明方法的某个参数的时候为之指定一个默认值,在调用该方法的时候如果采用该默认值,你就无须指定该参数。和很多语言层面特性(语法糖)的实现一样,缺省参数也是编译器为我们玩的一个小花招。缺省参数最终体现为两个特殊的自定义特性OptionalAttribute和DefaultParameterValueAttribute 。阅读全文
    posted @ 2011-01-12 13:41 Artech 阅读(7411) | 评论 (100) 编辑
     
    摘要: 在这之前我写过一些文章来介绍关于字符串内存分配和驻留的文章,涉及到的观点主要有:字符串的驻留机制避免了重复对象的创建;驻留的字符串对象不能被GC回收;被驻留的字符串是被同一进程中所有应用程序域共享的。这里我通过内存分析工具来证明这些结论。阅读全文
    posted @ 2010-11-25 22:12 Artech 阅读(5316) | 评论 (73) 编辑
     
    摘要: 《上篇》中我们主要讨论的是程序集和应用程序域的话题,着重介绍了两个不同的程序集加载方式:独占方式和共享方式("中立域"方式);以及基于"进程范围内"的字符串驻留。这篇将关注点放在托管对象创建时"内存的分配"和对"大对象的回收"上。阅读全文
    posted @ 2010-10-20 22:24 Artech 阅读(4673) | 评论 (100) 编辑
     
    摘要: 半年之前,PM让我在部门内部进行一次关于“内存泄露”的专题分享,我为此准备了一份PPT。今天无意中将其翻出来,觉得里面提到的关于CLR下关于内存管理部分的内存还有点意思。为此,今天按照PPT的内容写了一篇文章。本篇文章不会在讨论那些我们熟悉的话题,比如“值类型引用类型具有怎样的区别?”、“垃圾回收分为几个步骤?”,而是讨论一些不"不一样"的东西。阅读全文
    posted @ 2010-10-18 22:02 Artech 阅读(6713) | 评论 (147) 编辑
     
    摘要: 在《谈谈你最熟悉的DateTime》一文中,我们从跨时区的角度剖析了我们熟悉的时间类型。如果你采用传统的ADO.NET编程,并用DataSet作为数据实体,可能你会熟悉DataSetDateTime这个类型。这个类型也是为实现跨时区场景设计的,为了对前文的补充,这篇文章就来谈谈基于DataSet的时间处理问题。阅读全文
    posted @ 2010-09-05 11:24 Artech 阅读(3648) | 评论 (29) 编辑
     
    摘要: 最近一直在负责公司内部框架的升级工作,今天对一个小问题进行了重新思考——时间的处理。具体来说,是分布式应用中如何有效地进行时间的处理以提供对跨时区的支持。不过,对该问题解决方案的介绍我会放在后续的文章中,在这里我们先来介绍一些基础性的内容——谈谈我们熟悉的DateTime类型阅读全文
    posted @ 2010-09-04 10:16 Artech 阅读(6874) | 评论 (64) 编辑
     
    摘要: 在前一篇文章中我曾经说过,现在正在做一个小小的框架以实现采用统一的API实现对上下文(Context)信息的统一管理。这个框架同时支持Web和GUI应用,并支持跨线程传递和跨域传递,和对上下文项目的读写控制。在对后两个特性的支持上,出现一个小小的关于序列化的问题。解决方案只需要改动短短的一行代码,结果却让我折腾了老半天...阅读全文
    posted @ 2010-08-31 20:16 Artech 阅读(3587) | 评论 (21) 编辑
     
    摘要: 最近一直在进行公司内部框架的升级工作,其中一个小的部分就是通过HttpSessionState和CallContext建立一套统一的、可扩展的用于管理上下文信息的框架。在为写好的程序编写Unit Test和QuickStart的时候,遇到了两个基于LogicalCallContext的严重问题。导致这两个问题的根源还没有来得及去追踪,或许是微软VS Unit Test框架本身和WebHost本身的一个Bug。现在将其写出来,一来是希望读者在遇到相同情况的时候知道LogicalCallContext可能是影响因素之一,另一方面也希望借助社区的力量快速找到问题的症结。阅读全文
    posted @ 2010-08-29 00:59 Artech 阅读(1795) | 评论 (5) 编辑
     
    摘要: WCF是一个具有极高扩展度的分布式通信框架。在WCF众多可扩展点中,CallContextInitializer可以帮助我们在服务操作执行前后完成一些额外的功能,这实际上就是一种AOP的实现方式。昨天,李永京同学问了我一个相关的问题,由此发现了一个基于自定CallContextInitializer的WCF扩展的严重问题。阅读全文
    posted @ 2010-07-27 12:15 Artech 阅读(2698) | 评论 (18) 编辑
     
    摘要: 最近园子里发表了一些讨论“事件(Event)”的文章,我也来凑个热闹,谈谈我对事件的一些粗浅的认识。本文不谈设计模式(主要是观察者模式),只从运行时的角度来分析事件这个对象到底是个什么东西?它有那么神秘吗?为了更好的分析事件,本文将会编写一些例子来模拟事件的订阅机制。本文对事件的分析可以概括为下面三句话:1.事件本质上是一个MulticastDelegate对象; 2.MulticastDelegate对象是多个Delegate对象的链表;3.Delegate = Object + MethodInfo,委托的执行最终通过反射来完成。阅读全文
    posted @ 2010-07-10 13:56 Artech 阅读(7224) | 评论 (29) 编辑
     
    摘要: 对于任何一个企业级应用来说,安全都是一个不可回避的话题。如何识别用户的身份?如何将用户可执行的操作和可访问的资源限制在其允许的权限范围之内?如何记录用户行为,让相应的操作都有据可查?这些都是应用的安全机制或者安全框架需要考虑的典型问题,它们分别对应着三个安全行为:认证、授权和审核。作为Windows平台下最完备的分布式通信平台,WCF具有一套强大的、完整的的可扩展安全体系,对上述的安全问题提供有效的支持。由于安全体系在整个WCF框架体系中具有极其重大的分量,在接下来的系列文章中,我将深入探讨这一块在我之前的文章中一直不曾触碰的境地 阅读全文
    posted @ 2010-07-07 00:13 Artech 阅读(5067) | 评论 (31) 编辑
     
    摘要: Windows Communication Foundation (WCF) 中的可靠会话使用传输窗口保存客户端和服务上的消息。可配置属性 MaxTransferWindowSize 指示传输窗口可以保存多少条消息。在发送方,这指示在等待确认消息时传输窗口可以保存多少条消息,在接收方,则指示为服务缓冲多少条消息。选择合适的大小可影响使用网络的效率以及运行服务的最佳容量。 当编写一个允许从不同的客户端启用可靠会话通信的服务时,可能会有许多客户端同时建立与该服务的可靠会话。在这些情况下,服务的响应取决于 MaxPendingChannels 属性。当发送方创建到接收方的可靠会话通道时,发送方和接收方之间的握手将建立可靠会话。建立可靠会话之后,该通道会放入到挂起的通道队列中以供服务接受。此 MaxPendingChannels 属性指示有多少个通道可以处于此状态。 阅读全文
    posted @ 2010-06-30 22:18 Artech 阅读(2819) | 评论 (5) 编辑
     
    摘要: 作为一个通信基础平台,WCF必须保证通信的可靠性。由于消息交换是WCF采用的通信手段,通信可靠性的保障体现在确保消息的可靠传输。由于网络环境的限制,网络层不能百分之百地确保对消息的有效交付。如何克服中间环节的制约,确保从一端发送的消息能够被有效地交付给另一端,这就是可靠消息传输需要解决的问题。WCF通过可靠会话实现了种种端到端的可靠消息传输。阅读全文
    posted @ 2010-05-13 21:20 Artech 阅读(7624) | 评论 (47) 编辑
     
    摘要: 上面一部分我们站在信道层的角度剖析了WCF为了实现可靠会话在信道层进行的一系列消息交换,或者说客户端和服务端的RS信道为了实现可靠消息传输所进行一轮又一轮的握手。这一切都是基于这样一个假设:两个RS信道均可以在适当的时机向对方发送消息,或者说两个RS信道之间是一个双工的通道。 如果我们站在传输层看待这个问题,该假设对于TCP传输是成立的,但是对于HTTP来说就有点问题了。HTTP本身就是一个基于请求|回复消息交换模式的应用层网络协议,并不能对双工通信提供支持。 阅读全文
    posted @ 2010-05-05 21:21 Artech 阅读(3617) | 评论 (33) 编辑
     
    摘要: 本系列先后通过《实例篇》、《概念篇》、《协议篇》和《编程篇》对WCF的可靠会话进行了详细探讨。作为本系列的最后一片,我们将深入到WCF的可靠会话体系的最底层,对实现可靠会话的实现原理进行深入剖析。如果读者仔细阅读本系列博文,相信会使读者对可靠会话的理解提升到一定的高度。 从《编程篇》中,我们不难看出可靠会话的编程仅仅围绕着一个对象,那就是绑定。绑定在整个WCF架构模型具有重要的地位。WCF整个架构模型由两部分构成,即服务模型(Service Model)层和信道(Channel)层,而绑定是信道层的缔造者,同时也是连接两个层次的纽带。对可靠会话的实现,是完全在信道层实现的。阅读全文
    posted @ 2010-05-04 23:52 Artech 阅读(1954) | 评论 (34) 编辑
     
    摘要: 整个可靠会话的机制是完全在信道层实现的,而整个信道层的最终缔造者就是绑定,所以可靠会话编程是围绕着绑定进行的。《上篇》对实现可靠会话的绑定元素已经如何使用系统绑定实现可靠会话进行了介绍,下篇将和你探讨WCF可靠会话编程模型余下两个主题:自定义绑定和对消息传递的强制约束。阅读全文
    posted @ 2010-04-29 23:04 Artech 阅读(3064) | 评论 (10) 编辑
     
    摘要: 对WCF的可靠会话编程有一定了解的人应该知道,我们可以使用 DeliveryRequirementsAttribute 可以指示WCF确认绑定提供服务或客户端实现所需的功能。但是,当你使用该特性的时候,会出现一些很奇怪的现象。经过我个人的分析,这是WCF的一个Bug。阅读全文
    posted @ 2010-04-27 13:12 Artech 阅读(2879) | 评论 (16) 编辑
     
    摘要: 在《实例篇》给出的例子中,我们实际上是通过对终结点的绑定进行相应的配置让整个消息的交换过程在一个可靠会话中进行,进而实现可靠消息传输的目的。由于整个可靠会话的机制是完全在信道层实现的,而整个信道层的最终缔造者就是绑定,所以可靠会话编程是围绕着绑定进行的。本篇文章主要为你讲述基于绑定的可靠会话编程。阅读全文
    posted @ 2010-04-26 21:17 Artech 阅读(3432) | 评论 (18) 编辑
     
    摘要: 在《上篇》中,我们认识了从序列创建到终止过程中消息交换的大致流程。接下来,我们进一步将关注点聚焦到单个小消息上,看看在整个基于序列的上下文中,不同类型的消息具有怎样的结构阅读全文
    posted @ 2010-04-25 19:19 Artech 阅读(1619) | 评论 (21) 编辑
     
    摘要: 在《实例篇》中,我通过可靠会话实现了对图片的可靠、有序的传输;在《概念篇》中,我们对可靠消息涉及到的可靠消息传输(RM)的相关概念进行了讲述。在WS-*大家庭中,WS-RM为可靠消息传输提供了一个一个规范,使互操作成为可能。在《协议篇》中,我们侧重对WS-RM的介绍。阅读全文
    posted @ 2010-04-24 08:51 Artech 阅读(3092) | 评论 (9) 编辑
     
    摘要: 服务(Service)的本质就是提供服务消费者期望的某种功能,服务的价值体现在两个方面:服务本身的质量和寄宿服务的平台应付消费者的数量,并发(Concurrency)的关注的是第二个要素。WCF服务寄宿于资源有限的环境中,要实现服务效用的最大化,需要考虑如何利用现有的资源实现最大的吞吐量(Throughput)。提高吞吐量就某个寄宿的服务实例(Service Instance)来说,一个重要的途径就是让它能够同时处理来自各个客户端(服务代理)的并发访问。WCF实现了一套完整的并发控制体系,为你提供了不同的并发模式。 我经常说软件架构是一门权衡的艺术,需要综合考虑各种相互矛盾的因素,找到一种最优的组合方式。提高单个服务实例允许的并发访问量能够提高整体吞吐量,这样的理论依赖于一种假设,那就是服务端所能使用的资源是无限。我们知道,这种假设无论在什么情况下都不会成立......阅读全文
    posted @ 2010-04-22 19:11 Artech 阅读(6284) | 评论 (33) 编辑
     
    摘要: WCF支持不同的消息交换模式,比较典型的有以下三种MEP:One-Way、Request/Reply和Duplex。消息会被WCF的信道层发送到传输层,并通过相应的传输协议发送到目的地。但是HTTP协议,大家都知道它天生就基于Request/Reply模式的,那么它是如何能够突破自己的局限,为One-Way和Duplex消息交换模式提供支持呢?阅读全文
    posted @ 2010-04-21 18:16 Artech 阅读(2402) | 评论 (14) 编辑
     
    摘要: 在《实例篇》中,我通过可靠会话成功地进行了美女图片的传输,相信大家在保了眼福之余,会对WCF的可靠会话的功用具有一个深刻的认识。实际上,这涉及到WS中一个重要的概念——可靠消息传输(RM)。如果想对可靠会话有一个深入的认识,对可靠消息传输的了解是必须的。阅读全文
    posted @ 2010-04-19 23:59 Artech 阅读(3564) | 评论 (21) 编辑
     
    摘要: 通过前面一系列的博文,我对WCF的并发体系进行了深入的剖析,在接下来的博文中,我只要专注于WCF的可靠会话机制。作为一个通信基础平台,WCF必须保证通信的可靠性。WCF通过可靠会话实现了一种端到端的可靠消息传输。为了让读者对可靠会话的作用现有一个直观的认识,我们先来做一个很有意思的实例演示,这也是早年微软推广WCF技术频繁使用的案例:图片传输。 阅读全文
    posted @ 2010-04-18 23:59 Artech 阅读(6222) | 评论 (86) 编辑
     
    摘要: 通过《上篇》介绍,我们知道了如何通过编程和配置的方式设置相应的最大并发量,从而指导WCF的限流体系按照你设定的值对并发的服务调用请求进行限流控制。那么,在WCF框架体系内部,整个过程是如何实现的呢?这就是本篇文章需要为你讲述的内容。阅读全文
    posted @ 2010-04-14 18:51 Artech 阅读(2706) | 评论 (23) 编辑
     
    摘要: WCF是一个基于多线程的消息监听、接收和处理框架体系,能够同时应付来自相同或者不同客户端的服务调用请求。一方面,我们期望WCF服务端能够处理尽可能多的并发请求,但是资源的有限性决定了并发量有一个最大值。如果WCF不控制进入消息处理系统的并发量,试图处理所有抵达的并发请求,一旦超过了这个临界值,整个服务端将会由于资源耗尽而崩溃。 所以,我们需要在WCF的消息接收系统和消息处理系统之间设置一道道屏障,将流入消息处理系统的请求控制到一个最佳的范围,以实现对现有资源的有效利用,从而达到确保服务的可用性和提高整体吞吐量的目的。 阅读全文
    posted @ 2010-04-13 22:55 Artech 阅读(3037) | 评论 (19) 编辑
     
    摘要: 在《上篇》中,我通过一个具体的实例演示了WCF服务宿主的同步上下文对并发的影响,并简单地介绍了同步上下文是什么东东,以及同步上下文在多线程中的应用。那么,同步上下文在WCF并发体系的内部是如何影响服务操作的执行的呢?这实际上涉及到WCF的一个话题,即线程的亲和性,本篇文章将为你剖析WCF线程亲和机制的本质。阅读全文
    posted @ 2010-04-08 19:40 Artech 阅读(2684) | 评论 (17) 编辑
     
    摘要: WCF并发体系下的同步机制是通过对InstanceContext进行加锁实现的,按照这样的理论,对于PerCall实例上下文模式,不论采用怎样的并发模式,服务操作应该是并发执行的;对于PerSession和Single实例上下文模式,如果采用Multiple并发模式,服务操作也应该是并发执行的。但是,一定是这样吗?阅读全文
    posted @ 2010-04-07 23:22 Artech 阅读(2777) | 评论 (11) 编辑
     
    摘要: 对于正常的服务调用,从客户端发送到服务端的请求消息最终会被WCF服务运行时分发到实例上下文中。对于回调场,回调对象也是封装到实例上下文中,并将其封送到客户端。服务调用与回调,并没有本质的不同。本篇文章讲通过《实践重于理论》中的实例,综合分析WCF对并发服务调用和并发回调的处理机制。 阅读全文
    posted @ 2010-03-31 18:41 Artech 阅读(2765) | 评论 (17) 编辑
     
    摘要: 由于WCF的并发是针对某个封装了服务实例的InstanceContext而言的,所以在不同的实例上下文模式下,会表现出不同的并发行为。本篇文章将以以实例演示加原理分析相结合的方式对不同实例上下文模式下的并发实现机制进行深度剖析...阅读全文
    posted @ 2010-03-30 20:17 Artech 阅读(3135) | 评论 (15) 编辑
     
    摘要: 由于WCF的并发是针对某个封装了服务实例的InstanceContext而言的,所以在不同的实例上下文模式下,会表现出不同的并发行为。接下来,我们从具体的实例上下文模式的角度来剖析WCF的并发处理机制。为了使读者对采用不同实例上下文对并发的影响有一个深刻的认识,会创建一个简单的WCF应用,并在此基础上添加监控功能,主要监控各种事件的执行时间,比如客户端服务调用的开始和结束时间,服务操作开始执行和结束执行的时间等等。读者可以根据实时输出的监控信息,对WCF的并发处理情况有一个很直观的认识。 阅读全文
    posted @ 2010-03-22 19:19 Artech 阅读(3360) | 评论 (12) 编辑
     
    摘要: 在《WCF 并发的本质》中,我们谈到了WCF提供的三种不同的并发模式,使开发者可以根据具体的情况选择不同的并发处理的策略。对于这三种并发模式,Multiple采用的并行的执行方式,而Single和Reentrant则是采用串行的执行方式。串行执行即同步执行,在WCF并发框架体系中,这样的同步机制是如何实现的呢? 阅读全文
    posted @ 2010-03-21 18:49 Artech 阅读(3595) | 评论 (9) 编辑
     
    摘要: 并发的含义就是多个并行的操作同时作用于一个相同的资源或者对象,或者说同一个资源或者对象同时应付多个并行的请求。对于WCF的并发来说,这里将的“资源或者对象”指的就是承载服务操作最终执行的服务实例。而WCF将服务实例封装在一个称为实例上下文对象中,所以WCF中的并发指的是同一个服务实例上下文同时处理多个服务调用请求。 阅读全文
    posted @ 2010-03-19 20:33 Artech 阅读(4702) | 评论 (34) 编辑
     
    摘要: [续《上篇》]TransactionFlow选项通过TransactionFlowAttribute这个操作契约写入绑定上下文,由事务绑定创建的事务信道获取该选项并以此作为首否对事务实施传播(发送或者接收)的依据。但是整个WCF事务还有一个重要的步骤需要实现:如何将通过OperationBehaviorAttribute特性标记为TransactionRequired的操作的执行自动纳入到流入的事务之中。接下来,我们就来着重讨论这个问题。 阅读全文
    posted @ 2010-03-18 19:32 Artech 阅读(1995) | 评论 (17) 编辑
     
    摘要: WCF事务编程主要涉及到这么三个方面:通过服务(操作)契约确定TransactionFlow的策略;通过事务绑定实现事务流转;通过服务操作行为控制事务的自动登记(Enlistment)行为,以及对事务超时时限、隔离级别和实例行为的设定。那么,在WCF内部这三者之间究竟是如何通过相互协作实现分布式事务的呢?这就是本篇文章所要讲述的内容阅读全文
    posted @ 2010-03-17 18:56 Artech 阅读(2303) | 评论 (18) 编辑
     
    摘要: 在完成了对于WCF事务编程(《上篇》、《中篇》、《下篇》)的介绍后,本篇文章将提供一个完整的分布式事务的WCF服务应用,通过本例,读者不仅仅会了解到如何编程实现事务型服务,还会获得其他相关的知识,比如DTC和AS-AT的配置等。阅读全文
    posted @ 2010-03-16 19:04 Artech 阅读(2236) | 评论 (41) 编辑
     
    摘要: 在WCF事务编程模型下,通过服务契约确定事务流转的策略(参阅《上篇》),通过事务绑定实施事务的流转(参阅《中篇》)。但是,对于事务绑定接收到并成功创建的事务来说,服务操作的执行是否需要自动登记到该事务之中,以及服务操作采用怎样的提交方式,这就是服务端自己说了算了。阅读全文
    posted @ 2010-03-15 00:48 Artech 阅读(2510) | 评论 (5) 编辑
     
    摘要: 续《上篇》]通过将TransactionFlowAttribute特性应用在服务契约的某个操作之上,并指定相应的TransactionFlowOption枚举直,仅仅定义了事务流转的策略而已。至于WCF框架是否有能力对事物进行流转,按照怎样的协议进行流转,则是通过绑定实现的,本篇着重介绍绑定对事务流转的支持. 阅读全文
    posted @ 2010-03-12 19:40 Artech 阅读(1693) | 评论 (11) 编辑
     
    摘要: WCF事务编程其实很简单,可以用三句话进行概括:通过服务契约决定事物流转(Transaction Flow)的策略;通过绑定实施事务的流转;通过服务行为控制事务的相关行为。本篇文章着重介绍如果通过TransactionFlowAttribute特性定义事务流转策略。 阅读全文
    posted @ 2010-03-11 18:48 Artech 阅读(3095) | 评论 (16) 编辑
     
    摘要: 在一个基于SOA架构的分布式系统体系中,服务(Service)成为了基本的功能提供单元,无论与业务流程无关的基础功能,还是具体的业务逻辑,均实现在相应的服务之中。服务对外提供统一的接口,服务之间采用标准的通信方式进行交互,各个单一的服务精又有效的组合、编排成为一个有机的整体。在这样一个分布式系统中某个活动(Activity)的实现往往需要跨越单个服务的边界,如何协调多个服务之间的关系使之为活动功能的实现服务,涉及到SOA一个重要的课题:服务协作(Service Coordination)。而具体来讲,一个分布式的活动可能会执行几秒钟,比如银行转帐;也可能执行几分钟、几个小时、几天甚至更长,比如移民局处理移民的申请。事务,无疑是属于短暂运行服务协作(Short-Running Service Coordination)的范畴。阅读全文
    posted @ 2010-01-31 13:22 Artech 阅读(8489) | 评论 (15) 编辑
     
    摘要: 在前面一篇给出的Transaction的定义中,信息的读者应该看到了一个叫做DepedentClone的方法。该方法对用于创建基于现有Transaction对象的“依赖事务(DependentTransaction)”。不像可提交事务是一个独立的事务对象,依赖事务依附于现有的某个事务(可能是可提交事务,也可能是依赖事务)。依赖事务可以帮助我们很容易地编写一些事务型操作,当环境事务不存的时候,可以确保操作在一个独立的事务中执行;当环境事务存在的时候,则自动加入其中。 阅读全文
    posted @ 2010-01-31 09:19 Artech 阅读(4048) | 评论 (11) 编辑
     
    摘要: 在.NET 1.x中,我们基本是通过ADO.NET实现对不同数据库访问的事务。.NET 2.0为了带来了全新的事务编程模式,由于所有事务组件或者类型均定义在System.Transactions程序集中的System.Transactions命名空间下,我们直接称基于此的事务为System.Transactions事务。System.Transactions事务编程模型使我们可以显式(通过System.Transactions.Transaction)或者隐式(基于System.Transactions.TransactionScope)的方式进行事务编程。阅读全文
    posted @ 2010-01-30 16:49 Artech 阅读(5401) | 评论 (19) 编辑
     
    摘要: [续上篇]当基于LTM或者KTM的事务提升到基于DTC的分布式事务后,DTC成为了本机所有事务型资源管理器的管理者;此外,当一个事务型操作超出了本机的范围,出现了跨机器的调用后,本机的DTC需要于被调用者所在机器的DTC进行协助。上级对下级(包括本机DTC对本机所有资源管理器,以及上下级DTC)的管理得前提是下级在上级那里登记,即事务登记(Transaction Enlist)。所有事务参与者,包括所有资源管理器和事务管理器(即DTC)在进行了事务等级完成之后形成了一个树形的层级结构,该结构的形成是后续的事务提供成为可能,因此我们将其称之为事务提交树(Transaction Commit Tree)。 阅读全文
    posted @ 2010-01-27 22:41 Artech 阅读(4479) | 评论 (24) 编辑
     
    摘要: 通过上一篇的介绍,我们知道了SOA真正需要的是一个能够协调服务操作直接(通过服务自身访问的资源)或者间接(通过被调用服务访问的资源)访问的所有资源的分布式事务管理系统,这是一个复杂的架构体系。WCF,作为Windows平台下基于SOA的分布式框架,对分布式事务提供全面的支持。不过,WCF并不是另起炉灶,而是充分地利用了Windows现有的事务控制基础架构。本节着重讨论Windows事务处理模型,首先来看看在这个模型中各个事务参与者各自扮演怎样的角色。 阅读全文
    posted @ 2010-01-27 21:42 Artech 阅读(5235) | 评论 (12) 编辑
     
    摘要: 在一个基于SOA架构的分布式系统体系中,服务(Service)成为了基本的功能提供单元,无论与业务流程无关的基础功能,还是具体的业务逻辑,均实现在相应的服务之中。服务对外提供统一的接口,服务之间采用标准的通信方式进行交互,各个单一的服务精又有效的组合、编排成为一个有机的整体。在这样一个分布式系统中某个活动(Activity)的实现往往需要跨越单个服务的边界,如何协调多个服务之间的关系使之为活动功能的实现服务,涉及到SOA一个重要的课题:服务协作(Service Coordination)。而具体来讲,一个分布式的活动可能会执行几秒钟,比如银行转帐;也可能执行几分钟、几个小时、几天甚至更长,比如移民局处理移民的申请。事务,无疑是属于短暂运行服务协作(Short-Running Service Coordination)的范畴。 阅读全文
    posted @ 2010-01-26 22:57 Artech 阅读(6972) | 评论 (38) 编辑
     
    摘要: 在《上篇》中,我通过使用Delegate的方式解决了服务调用过程中的异常处理以及对服务代理的关闭。对于《WCF技术剖析(卷1)》的读者,应该会知道在第7章中我通过类似于AOP的方式解决了相似的问题,现在我们来讨论这个解决方案。阅读全文
    posted @ 2010-01-08 20:49 Artech 阅读(4430) | 评论 (29) 编辑
     
    摘要: 在进行基于会话信道的WCF服务调用中,由于受到并发信道数量的限制,我们需要及时的关闭信道;当遇到某些异常,我们需要强行中止(Abort)信道。在真正的企业级开发中,正如我们一般不会让开发人员手工控制数据库连接的开启和关闭一样,我们一般也不会让开发人员手工去创建、开启、中止和关闭信道,这些工作是框架应该完成的操作。这篇文章,我们就来介绍如果通过一些编程技巧,让开发者能够无视“信道”的存在,像调用一个普通对象一样进行服务调用。阅读全文
    posted @ 2010-01-04 19:46 Artech 阅读(5169) | 评论 (41) 编辑
     
    摘要: 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置;通过ChannelFactory创建服务代理对象。在这篇文章中,我们采用一种独特的方式进行服务的调用。阅读全文
    posted @ 2009-12-29 19:41 Artech 阅读(4106) | 评论 (27) 编辑
     
    摘要: 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-MEX和HTTP-GET的元数据发布,针对这两种不同的协议,元数据获取的实现方式也是不同的,本片文章中通过自己的方式进行元数据获取,可以看成是对WCF客户端元数据框架的模拟。阅读全文
    posted @ 2009-12-28 18:46 Artech 阅读(2663) | 评论 (16) 编辑
     
    摘要: 在上篇文章中,我通过程序模拟了基于WS-MEX模式下元数据的发布,现在我们来模拟另外一中元数据发布模式:HTTP-GET,这两个模拟程序不仅仅会帮助你深刻地理解WCF的元数据发布机制,对你进一步认识WCF服务端的分发体系具有重要的帮助。阅读全文
    posted @ 2009-12-27 17:50 Artech 阅读(2028) | 评论 (1) 编辑
     
    摘要: 通过《如何将一个服务发布成WSDL[编程篇]》的介绍我们知道了如何可以通过编程或者配置的方式将ServiceMetadataBehavior这样一个服务形式应用到相应的服务上面,从而实现基于HTTP-GET或者WS-MEX的元数据发布机制。那么在WCF内部具体的实现原理又是怎样的呢?相信很多人对此都心存好奇,本篇文章的内容将围绕着这个主题展开。 阅读全文
    posted @ 2009-12-26 18:35 Artech 阅读(1269) | 评论 (3) 编辑
     
    摘要: 对于WCF服务端元数据架构体系来说,通过MetadataExporter将服务的终结点导出成MetadataSet,仅仅是完成了一半的工作。被成功导出的以MetadataSet对象表示的元数据需要最终作为可被访问的网络资源发布出来,才能被服务消费者获取,进而有效地帮助他们进行服务调用。元数据的发布最终是通过ServiceMetadataBehavior这样一个服务行为实现的。阅读全文
    posted @ 2009-12-25 18:35 Artech 阅读(3134) | 评论 (13) 编辑
     
    摘要: 通过《实现篇》对WSDL元素和终结点三要素的之间的匹配关系的介绍,我们知道了WSDL的Binding元素来源于终结点的绑定对象,那么这些基于Binding的元数据以及相应的策略断言是如何被写入WSDL的呢?WSDL导出扩展(WSDL Export Extension)和策略导出扩展(Policy Export Extension)就是为此设计的。 阅读全文
    posted @ 2009-12-24 20:30 Artech 阅读(1989) | 评论 (6) 编辑
     
    摘要: 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框架体系中,元数据的导出工作由MetadataExporter实现。MetadataExporter是一个抽象类型,定义了导出元数据的基本行为。WCF定义一个具体的MetadataExporter:WsdlExporter,将基于某个终结点的元数据导出生成基于WSDL的MetadataSet。我们先来认识MetadataExporter和MetadataSet。阅读全文
    posted @ 2009-12-23 19:46 Artech 阅读(2006) | 评论 (4) 编辑
     
    摘要: [WS标准篇]中我花了很大的篇幅介绍了WS-MEX以及与它相关的WS规范:WS-Policy、WS-Transfer和WSDL,因为WCF元数据结构体系完全是基于WS-MEX等相关的规范之上。熟悉这些基本的WS规范,对于我们全面、深刻的理解WCF整个元数据架构体系具有十分重要的意义。接下来我们具体来介绍基于MetadataSection和MetadataSet基于两个类型的元数据表示。阅读全文
    posted @ 2009-12-22 18:51 Artech 阅读(2131) | 评论 (15) 编辑
     
    摘要: 微软EnterLib的PIAB是一个比较好用的轻量级的AOP框架,自身也提供了一系列的CallHandler,其中CachingCallHandler直接利用HttpRuntime的Cache实现了基于方法级别的缓存。但是,PIAB发布到现在,CachingCallHandler就一直存着一个问题:如果目标方法具有Out参数并且返回类型不是void,会抛出IndexOutOfRangeException,如果返回类型为void,out参数也不会被缓存。不知道微软对此作何考虑,反正我觉得这是一个不可原谅的Bug。阅读全文
    posted @ 2009-12-21 23:07 Artech 阅读(1766) | 评论 (23) 编辑
     
    摘要: 在《WCF技术剖析(卷1)》中,我多次向读者强调WCF进行通信的本质:终结点是客户端和服务端进行通信的手段。服务的提供者通过一个或者多个终结点将服务发布出来;服务的消费者则通过创建于之匹配的终结点进行服务的调用。站在服务消费者的角度,这样一个“匹配”的终结点该如何创建呢?或者说客户端基于何种信息创建能够有效调用目标服务的终结点呢?这就是元数据需要解决的问题。阅读全文
    posted @ 2009-12-20 12:05 Artech 阅读(1916) | 评论 (18) 编辑
     
    摘要: 通过上一篇了解了模块内基本的层次划分之后,接下来我们来聊聊PetShop中一些基本基础功能的实现,以及一些设计、架构上的应用如何同WCF进行集成。本篇讨论两个问题:实现分布式的Membership和客户端到服务端上下文(Context)的传递。阅读全文
    posted @ 2009-12-07 18:30 Artech 阅读(2590) | 评论 (21) 编辑
     
    摘要: 上篇中我们谈到:将一个生命周期较短的对象(对象A)注册到一个生命周期较长(对象B)的某个事件(Event)上,两者便无形之间建立一个引用关系(B引用A)。这种引用关系导致GC在进行垃圾回收的时候不会将A是为垃圾对象,最终使其常驻内存(或者说将A捆绑到B上,具有了和B一样的生命周期)。这种让无用的对象不能被GC垃圾回收的现象,在托管环境下就是一种典型的内存泄漏问题。我们今天将会着重解释其背后的原因。阅读全文
    posted @ 2009-12-06 22:57 Artech 阅读(4042) | 评论 (32) 编辑
     
    摘要: 最近这两天一直在忙着为一个项目检查内存泄漏(Memory Leak)的问题,对相关的知识进行了一下简单的学习和探索,其间也有了一些粗浅的经验积累,今天特意写一篇相关的文章与大家分享。那些对内存泄漏稍微有点了解的人,对于本篇文章的标题,相信不会觉得是在危言耸听。就我查阅的资料,已经这两天的发现也证实了这一点:觉得部分的内存泄漏问题与事件(Event)有关。本篇文章将会介绍其原理,以及如何发现和解决由事件导致的内存泄漏问题。阅读全文
    posted @ 2009-12-03 21:02 Artech 阅读(5593) | 评论 (43) 编辑
     
    摘要: 上一篇文章主要讨论的是PetShop的模块划分,在这一篇文章中我们来讨论在一个模块中如何进行层次划分。模块划分应该是基于功能的,一个模块可以看成是服务于某项功能的所有资源的集合;层次划分侧重于关注点分离(SoC:Separation of Concern ),让某一层专注于某项单一的操作,以实现重用性、可维护性、可测试性等相应的目的。阅读全文
    posted @ 2009-12-01 19:57 Artech 阅读(4596) | 评论 (34) 编辑
     
    摘要: 在《WCF技术剖析(卷1)》的最后一章,我写了一个简单基于WCF的Web应用程序,该程序模拟一个最简单的网上订购的场景,所以我将其命名为PetShop。PetShop的目在于让读者体会到在真正的项目开发中,如何正确地、有效地使用WCF。在这个应用中,还会将个人对设计的一些总结融入其中,希望能够对读者有所启发。阅读全文
    posted @ 2009-11-30 19:22 Artech 阅读(9012) | 评论 (97) 编辑
     
    摘要: 服务端只有抛出FaultException异常才能被正常地序列化成Fault消息,并实现向客户端传播。对于一般的异常(比如执行Divide操作抛出的DivideByZeroException),在默认的情况下,异常信息无法实现向客户端传递。但是,倘若为某个服务应用了ServiceDebugBehavior这么一个服务行为,并开启了IncludeExceptionDetailInFaults开关,异常信息将会原封不动地传播到客户端。WCF内部是如何处理抛出的非FaultException异常的呢? 阅读全文
    posted @ 2009-11-24 18:45 Artech 阅读(2477) | 评论 (16) 编辑
     
    摘要: WCF客户端和服务端的框架体系相互协作,使得开发人员可以按照我们熟悉的方式进行异常的处理:在服务操作执行过程中抛出异常(FaultException),在调用服务时捕获异常,完全感觉不到“分布式”的存在,如同典型的“本地”操作一般。为了实现这样的效果,WCF在内部为我们作了很多。 阅读全文
    posted @ 2009-11-23 22:59 Artech 阅读(2238) | 评论 (17) 编辑
     
    摘要: 从整个基础构架的层次结构上讲,WCF可以分成两个部分:服务模型层(Service Mode Layer)和信道层(Channel Layer)。服务模型层建立在信道层之上,提供了一个统一的、可扩展的编程模型。信道层则通过绑定(Binding)建创的信道栈为消息通信提供了一个传输、处理的通道。阅读全文
    posted @ 2009-11-21 21:34 Artech 阅读(5238) | 评论 (8) 编辑
     
    摘要: 在《WCF技术剖析(卷1)》写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列。本系列的目的在于对《WCF技术剖析》的补充,会对书中的一些内容进行展开讲述,同时会囊括很多由于篇幅的原因忍痛割弃的内容。为了方便广大WCF爱好者的阅读,今天花了两个小时的时候对前一阵子撰写的《WCF技术剖析》系列博文(一共30篇)进行收集整理,将其发布出来与大家分享。阅读全文
    posted @ 2009-11-21 19:03 Artech 阅读(32348) | 评论 (56) 编辑
     
    摘要: Enterprise Library是微软P&P部门开发的众多Open source框架中的一个,最新的版本已经出到了4.1。由于接触Enterprise Library已经有很长的一段时间,在实际的项目中使用的频率也很高。对此有了一些积累,希望通过这个新的系列和广大网友一起分享和交流。本系列假设读者已经对Enterprise Library有一定的了解,故而不会对各个Application Block的基本原理和编程模型进行介绍,而把侧重点放在Enterprise Library深层次的实现原理、设计模式的应用、有效扩展和最佳实践上阅读全文
    posted @ 2009-11-21 18:12 Artech 阅读(6727) | 评论 (1) 编辑
     
    摘要: 在[第2篇]中,我们深入剖析了单调(PerCall)模式下WCF对服务实例生命周期的控制,现在我们来讨轮另一种极端的服务实例上下文模式:单例(Single)模式。阅读全文
    posted @ 2009-11-10 00:11 Artech 阅读(2175) | 评论 (5) 编辑
     
    摘要: [上篇]中,我们介绍了WCF关于实例管理一些基本的知识点,包括InstanceContext、InstanceContextMode、已经如何通过ServiceBehaviorAttribute应用不同的实例上下文模式给不同的服务。在[第1篇]中,对WCF采用的三种不同实例上下文模式进行了简单的比较,本篇的重点方法对单调(PerCall)模式为进行详细介绍。 在单调(Per-Call)实例上下文模式下,WCF总是创建一个新的服务实例上下文处理接收到的每一个服务调用请求,并在服务操作执行结束后,回收服务上下文和服务实例。换句话说,单调服务实例上下文模式使服务实例上下文的生命周期与服务调用本身绑定。我们首先来介绍单调模式下服务实例上下文具体有怎样的生命周期。阅读全文
    posted @ 2009-11-09 00:04 Artech 阅读(2928) | 评论 (20) 编辑
     
    摘要: [上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常。在服务执行过程中,我们手工抛出FaultException异常,WCF服务端框架会对该异常对象进行序列化病最终生成Fault消息。当WCF客户端框架介绍到该Fault消息之后,会做一项相反的操作:对Fault消息中进行解析和反序列化,重新生成并抛出FaultException异常。WCF框架自动为我们作了这么多“幕后”工作,使得开发人员可以完全采用编写一般的.NET应用程序的模式进行异常的处理:在错误的地方抛出相应异常,对于潜在出错的方法调用进行相应的异常捕获和处理。所以,WCF的异常处理框架的核心功能就是实现FaultException异常和Faul阅读全文
    posted @ 2009-10-29 19:52 Artech 阅读(1388) | 评论 (10) 编辑
     
    摘要: 对于上一篇文章 (WCF基本异常处理模式:[上篇]、[中篇]、[下篇]),主要是站在最终开发者的角度对WCF关于异常处理编程模式进行了介绍,接下来,我们需要将我们的目光转移到WCF框架内部,深入剖析整个WCF异常处理流程。阅读全文
    posted @ 2009-10-28 20:58 Artech 阅读(2419) | 评论 (13) 编辑
     
    摘要: 从FaultContractAttribute的定义我们可以看出,该特性可以在同一个目标对象上面多次应用(AllowMultiple = true)。但是,如果你在同一个操作方法上面应用了多了FaultContractAttribute特性的时候,需要遵循怎样的规则呢,这是本篇文章着重要介绍的内容。阅读全文
    posted @ 2009-10-27 19:11 Artech 阅读(2690) | 评论 (6) 编辑
     
    摘要: 通过WCF基本的异常处理模式[上篇], 我们知道了:在默认的情况下,服务端在执行某个服务操作时抛出的异常(在这里指非FaultException异常),其相关的错误信息仅仅限于服务端可见,并不会被WCF传递到客户端;如果将开启了IncludeExceptionDetailInFaults的ServiceDebug服务行为通过声明(通过在服务类型上应用ServiceBehaviorAttrite特性)或者配置的方式应用到相应的服务上,异常相关的所有细节信息将会原封不动地向客户端传送。 这两种方式体现了两种极端的异常传播(Exception Propagation)机制,对于基于服务操作执行过程中抛出的异常的错误细节,要么完全对客户端屏蔽,要么全部暴露于客户端。阅读全文
    posted @ 2009-10-22 18:17 Artech 阅读(3173) | 评论 (10) 编辑
     
    摘要: 由于WCF采用.NET托管语言(C#和NET)作为其主要的编程语言,注定以了基于WCF的编程方式不可能很复杂。同时,WCF设计的一个目的就是提供基于非业务逻辑的通信实现,为编程人员提供一套简单易用的应用编程接口(API)。WCF编程模式的简单性同样体现在异常处理上面,本篇文章的主要目的就是对WCF基于异常处理的编程模式做一个简单的介绍。阅读全文
    posted @ 2009-10-21 22:36 Artech 阅读(3823) | 评论 (13) 编辑
     
    摘要: 任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源。同理,一个WCF服务的监听与执行同样需要通过一个进程来承载。我们将为WCF服务创建或指定一个进程的方式称为服务寄宿(Service Hosting)。服务寄宿的本质通过某种方式,创建或者指定一个进程用以监听服务的请求和执行服务操作,为服务提供一个运行环境。服务寄宿的手段是为一个WCF服务类型创建一个ServiceHost对象(或者任何继承于ServiceHostBase的对象)。无论采用哪种寄宿方式,在为某个服务创建ServiceHost的过程中,WCF框架内部会执行一系列的操作,其中最重要的步骤就是为服务创建服务描述(Service Description)。在本篇文章中,我们将对服务描述进行全面的介绍。 阅读全文
    posted @ 2009-08-27 16:30 Artech 阅读(3525) | 评论 (9) 编辑
     
    摘要: 通过上篇的介绍,我们知道了WCF所有与编码与解码相关的功能都实现在相应的XmlDictionaryWriter和XmlDictionaryReader中。但是在真正的WCF处理框架中,却并不直接使用XmlDictioanryWriter和XmlDictionaryReader对象,而通过相应的消息编码器(MessageEncoder)对其进行进一步封装,专门用于消息的编码和解码。 阅读全文
    posted @ 2009-08-06 19:31 Artech 阅读(3498) | 评论 (22) 编辑
     
    摘要: 消息作为WCF进行通信的唯一媒介,最终需要通过写入传输层进行传递。而对消息进行传输的一个前提或者是一项必不可少的工作是对消息进行相应的编码。WCF提供了一系列可供选择的编码方式,它们分别在互操作和性能各具优势。在本篇文章我们将对各种编码方式进行消息的讨论。 阅读全文
    posted @ 2009-08-05 21:51 Artech 阅读(3564) | 评论 (23) 编辑
     
    摘要: 在本篇文章中,我们将讨论WCF四大契约(服务契约、数据契约、消息契约和错误契约)之一的消息契约(Message Contract)。服务契约关注于对服务操作的描述,数据契约关注于对于数据结构和格式的描述,而消息契约关注的是类型成员与消息元素的匹配关系......阅读全文
    posted @ 2009-08-02 10:06 Artech 阅读(4392) | 评论 (12) 编辑
     
    摘要: WCF技术剖析(卷1)》自出版近20天以来,得到了园子里的朋友和广大WCF爱好者的一致好评,并被卓越网计算机书店作为首页推荐,在这里对大家的支持表示感谢。同时我将一直坚持这个博文系列,与大家分享我对WCF一些感悟和学习经验。在《消息(Message)详解》系列的上篇和中篇,先后对消息版本、详细创建、状态机和基于消息的基本操作(读取、写入、拷贝、关闭)进行了深入剖析,接下来我们来谈谈消息的另一个重要组成部分:消息报头(Message Header)。阅读全文
    posted @ 2009-08-01 10:44 Artech 阅读(3839) | 评论 (14) 编辑
     
    摘要: 在上篇中大体上围绕着Message的两个话题进行讲述:消息版本(Message Version)和采用五种不同的方式创建Message。本篇文章将会详细介绍Message的另外两个主题:和消息的基本操作,比如读、写、拷贝、关闭等,以及消息状态机(Message State Machine)。阅读全文
    posted @ 2009-07-28 18:16 Artech 阅读(3285) | 评论 (11) 编辑
     
    摘要: 消息交换是WCF进行通信的唯一手段,通过方法调用(Method Call)形式体现的服务访问需要转化成具体的消息,并通过相应的编码(Encoding)才能通过传输通道发送到服务端;服务操作执行的结果也只能以消息的形式才能被正常地返回到客户端。所以,消息在整个WCF体系结构中处于一个核心的地位,WCF可以看成是一个消息处理的管道。接下来我将分阅读全文
    posted @ 2009-07-27 21:55 Artech 阅读(4040) | 评论 (6) 编辑
     
    摘要: 数据契约是对用于交换的数据结构的描述,是数据序列化和反序列化的依据。在一个WCF应用中,客户端和服务端必须通过等效的数据契约方能进行有效的数据交换。随着时间的推移,不可避免地,我们会面临着数据契约版本的变化,比如数据成员的添加和删除、成员名称或者命名空间阅读全文
    posted @ 2009-07-21 23:25 Artech 阅读(2935) | 评论 (11) 编辑
     
    摘要: 如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML。反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该如何实现这样的场景? 这就需要使用到一个特殊的对象:数据契约代理(DataContract Surrogate)。阅读全文
    posted @ 2009-07-20 18:23 Artech 阅读(3698) | 评论 (18) 编辑
     
    摘要: 第一次邂逅WCF是在微软举办的一场关于Windows Vista技术推广培训上,时间大概是2005年10月份,当时对WCF可谓是一见钟情。如果读者也像我一样,之前习惯了采用.NET Remoting、XML Web Service、WSE、MSMQ来架构你分布式应用的话,应该不难想象我第一次接触WCF时心中的那份震撼。WCF是Windows平台下所有分布式技术集大成者,它将这一系列独立的分布式技术整合,提供一个统一的应用编程接口,这本身就是一项创举。这些被整合的分布式技术不仅仅包含提到的这些,还包括 DCOM、Enterprise Service等。WCF并非单纯地将它们进行简单的累加,而是从底而上进行了革新性的重新设计,使WCF成为了一个可定制、可扩展的通信框架。阅读全文
    posted @ 2009-07-15 22:31 Artech 阅读(1744) | 评论 (8) 编辑
     
    摘要: 在.NET Framework 2.0中,泛型第一次被引入。我们可以定义泛型接口、泛型类型、泛型委托和泛型方法。序列化依赖于真实具体的类型,而泛型则刻意模糊了具体类型概念。而集合代表一组对象的组合,集合具有可迭代(Enumerable)的特性,可以通过某个迭代规则遍历集合中的每一个元素。由于范型类型和集合类型在序列化和反序列化上具有一些特殊的行为和规则,在这篇文章中,我将会对此进行详细介绍。上篇先来说所泛型数据契约。阅读全文
    posted @ 2009-07-13 17:38 Artech 阅读(4005) | 评论 (10) 编辑
     
    摘要: [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道《天天山海经》为此录制的节目视频(苏州话)]]DataContractSerializer承载着所有数据契约对象的序列化和反序列化操作。在上面一篇文章(< a href="http://www.cnblogs.com/artech/archive/2009/07/09/1520121.html">《数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)》)中,我们谈到DataContractSerializer基本的序列化规则;如何控制DataContractSerializer序列化或者反序列化对象的数量;以及如何在序列化后的XM阅读全文
    posted @ 2009-07-12 16:27 Artech 阅读(5476) | 评论 (21) 编辑
     
    摘要: [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道《天天山海经》为此录制的节目视频(苏州话)]] 大部分的系统都是以数据为中心的(Data Central),功能的实现表现在对相关数据的正确处理。而数据本身,是有效信息的载体,在不同的环境具有不同的表示。一个分布式的互联系统关注于数据的交换,而数据正常交换的根本前提是参与数据交换的双方对于数据结构的一致性理解。WCF下的序列化(Serialization)解决的是如何将数据从对象的表现形式转变成XML表现形式,以确保数据的正常交换。从本章起,我将讲述WCF序列化的本质,首先从从数据契约谈起。阅读全文
    posted @ 2009-07-09 21:20 Artech 阅读(6353) | 评论 (7) 编辑
     
    摘要: 说完了客户端的异步服务调用(参阅WCF技术剖析之十一:异步操作在WCF中的应用(上篇)),我们在来谈谈服务端如何通过异步的方式为服务提供实现。在定义服务契约的时候,相信大家已经注意到了OperationContractAttribute特性具有一个bool类型的AsynPattern。该属性可以将一个服务操作定义成异步实现模式,接下来的内容主要是着眼于介绍异步操作的定义和实现原理。 阅读全文
    posted @ 2009-07-08 22:56 Artech 阅读(4225) | 评论 (27) 编辑
     
    摘要: 按照操作执行所需的资源类型,我们可以将操作分为CPU绑定型(CPU Bound)操作和I/O绑定型(I/O Bound)操作。对于前者,操作的执行主要利用CPU进行密集的计算,而对于后者,大部分的操作处理时间花在I/O操作处理,比如访问数据库、文件系统、网络资源等。对于I/O绑定型操作,我们可以充分利用多线程的机制,让多个操作在自己的线程并发执行,从而提高系统性能和响应能力。服务调用就是典型的I/O绑定型操作,所以多线程在服务调用中具有广泛的应用。在本篇文章中,我们专门来讨论多线程或者是异步操作在WCF中的具体应用。阅读全文
    posted @ 2009-07-08 21:14 Artech 阅读(4920) | 评论 (6) 编辑
     
    摘要: 在前面一片文章(服务代理不能得到及时关闭会有什么后果?)中,我们谈到及时关闭服务代理(Service Proxy)在一个高并发环境下的重要意义,并阐明了其根本原因。但是,是否直接调用ICommunicationObject的Close方法将服务代理关闭就万事大吉了呢?事情远不会这么简单,这其中还会涉及关于异常处理的一些操作,这就是本篇文章需要讨论的话题。阅读全文
    posted @ 2009-07-05 18:33 Artech 阅读(6002) | 评论 (25) 编辑
     
    摘要: 我们想对WCF具有一定了解的人都会知道:在客户端通过服务调用进行服务调用过程中,服务代理应该及时关闭。但是如果服务的代理不等得到及时的关闭,到底具有怎样的后果?什么要关闭服务代理?在任何时候都需要关闭服务代理吗?是否有一些例外呢?本篇文章将会围绕着这些问题展开。阅读全文
    posted @ 2009-07-04 17:58 Artech 阅读(6257) | 评论 (43) 编辑
     
    摘要: 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service Proxy)。而ChannelFactory则是服务代理的创建者。在客户端,我们具有两种典型的服务代理创建方式,其一是通过诸如SvcUtil.exe这样的工具导入服务的元数据生成相应的服务代理(一个继承自ClientBase的类型)代码和相关配置;其二是直接通过相应的终结点信息(通过代码指定或者配置)创建ChannelFactory对象,并借助该对象直接进行服务代理的创建。实际上,即使通过ClientBase对象进行服务调用,其内部也是调用ChannelFactory创建的服务代理。整个ChannelFactory的创建是一项相对复杂并且费时的工作,会涉及很多诸如反射、配置文件的读取等操作。为了提高服务调用的性能,在.NET 3.5中,WCF在ClientBase中引入了ChannelFac阅读全文
    posted @ 2009-07-03 20:36 Artech 阅读(6088) | 评论 (17) 编辑
     
    摘要: 在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅《MS Enterprise Library Policy Injection Application Block 深入解析[总结篇]》),也写过WCF与PIAB的集成(参阅:《WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block 的集成》)、WCF与Unity的集成(参阅《WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成》)以及Unity与PIAB的集成(参阅《Enterprise Library深入解析与灵活应用(1):通过Unity Extension实现和Policy Injection Application Block的集成》、阅读全文
    posted @ 2009-06-29 16:03 Artech 阅读(5595) | 评论 (57) 编辑
     
    摘要: 在EnteLib中,PIAB(Policy Injection Application Block)和Unity的定位是轻量级的AOP框架和IoC容器(Container)。通过PIAB,我们可以将一些业务无关的crosscutting concern定义于相应的CallHandler中,通过Attribute声明或者配置应用到承载业务逻辑的目标方法上。而通过Unity提供的IoC容器(或者DI容器),即UnityContainer,很好地实现了依赖的动态注入,从而实现了组件之间、模块之间或者服务之间的松耦合。在本篇文章中,我们将关注如何将两者有机地关联起来。阅读全文
    posted @ 2009-06-28 23:12 Artech 阅读(5026) | 评论 (21) 编辑
     
    摘要: 近半年以来,一直忙于我的第一本WCF专著《WCF技术剖析》的写作,一直无暇管理自己的Blog。到目前为止《WCF技术剖析(卷1)》的写作暂告一段落,初步预计于下个月由武汉博文视点出版。在《WCF技术剖析》写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列。本系列的目的在于对《WCF技术剖析》的补充,会对书中的一些内容进行展开讲述,同时会囊括很多由于篇幅的原因忍痛割弃的内容。阅读全文
    posted @ 2009-06-27 17:04 Artech 阅读(1914) | 评论 (14) 编辑
     
    摘要: 本篇文章来源于几天前一个朋友向我咨询的问题。问题是这样的,他说他采用ASP.NET应用程序的方式对定义的WCF服务进行寄宿(Hosting),并使用配置的方式对服务的BaseAddress进行了设置,但是在创建ServiceHost的时候却抛出InvalidOperationException,并提示相应Address Scheme的BaseAddress找不到。我意识到这可能和WCF中用于判断服务寄宿方式的逻辑有关,于是我让这位朋友将相同的服务寄宿代码和配置迁移到GUI程序或者Console应用中,看看是否正常。结果如我所想,一切正常,个人觉得这应该是WCF的一个Bug。今天撰文与大家讨论,看看大家对这个问题有何见解。阅读全文
    posted @ 2009-06-26 19:33 Artech 阅读(4206) | 评论 (28) 编辑
     
    摘要: 在《基于IIS的WCF服务寄宿(Hosting)实现揭秘》中,我们谈到在采用基于IIS(或者说基于ASP.NET)的WCF服务寄宿中,具有两种截然不同的运行模式:ASP.NET并行(Side by Side)模式和ASP.NET兼容模式。对于前者,WCF通过HttpModule实现了服务的寄宿,而对于后者,WCF的服务寄宿通过一个HttpHandler实现。只有在ASP.NET兼容模式下,我们熟悉的一些ASP.NET机制才能被我们使用,比如通过HttpContext的请求下下文;基于文件或者Url的授权;HttpModule扩展;身份模拟(Impersonation)等。 由于在ASP.NET兼容模式下,ASP.NET采用与.aspx Page完全一阅读全文
    posted @ 2009-06-25 18:17 Artech 阅读(5290) | 评论 (34) 编辑
     
    摘要: 通过《再谈IIS与ASP.NET管道》的介绍,相信读者已经对IIS和ASP.NET的请求处理管道有了一个大致的了解,在此基础上去理解基于IIS服务寄宿的实现机制就显得相对容易了。概括地说,基于IIS的服务寄宿依赖于两个重要的对象:System.ServiceModel.Activation.HttpModuleSystem. ServiceModel.Activation.HttpHandler。 阅读全文
    posted @ 2009-06-24 20:33 Artech 阅读(6461) | 评论 (11) 编辑
     
    摘要: 上面一篇文章中,我们对不同版本的IIS,以及ASP.NET得的实现机制进行了详细而深入的分析。在介绍IIS7.0的时候,我们谈到,HTTP.SYS+W3SVC实现了基于HTTP的请求监听,在此基础上引入了三组网络监听器(Listener)和监听适配器(Adapter),实现了基于TCP、Named Pipes和MSMQ的网络监听。由于IIS 7提供了基于非HTTP网络协议的监听支持,那么就意味着当我们当我们通过IIS进行WCF服务寄宿(Hosting)的时候,可以采用非HTTP的通信方式。在本篇文章中,我们将通过一个简单实例介绍进行非HTTP的IIS服务寄宿,Source Code下载阅读全文
    posted @ 2009-06-21 22:12 Artech 阅读(7305) | 评论 (51) 编辑
     
    摘要: 在2007年9月份,我曾经写了三篇详细介绍IIS架构和ASP.NET运行时管道的文章,深入介绍了IIS 5.x与IIS 6.0HTTP请求的监听与分发机制,以及ASP.NET运行时管道对HTTP请求的处理流程: [原创]ASP.NET Process Model之一:IIS 和 ASP.NET ISAPI
    [原创]ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part I
    [原创]ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline - Part II
    很多人留言为何没有IIS 7的介绍。在写作《WCF深入剖析》中,为了剖析基于IIS的WCF服务寄宿(Hosting),再次对相关内容进行了研究,在这里一并与大家分享。阅读全文
    posted @ 2009-06-20 00:19 Artech 阅读(13166) | 评论 (68) 编辑
     
    摘要: 细算起来,已经有好几个月没有真正的写过文章了。近半年以来,一直忙于我的第一本WCF专著《WCF技术剖析》的写作,一直无暇管理自己的 Blog。到目前为止《WCF技术剖析(卷1)》的写作暂告一段落,初步预计于下个月由武汉博文视点出版。在《WCF技术剖析》写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列。本系列的目的在于对《WCF技术剖析》的补充,会对书中的一些内容进行展开讲述,同时会囊括很多由于篇幅的原因忍痛割弃的内容。本系列的第一篇,我将会对WCF的基本架构作一个大致的讲解。不过,一改传统对WCF的工作流程进行平铺直叙,我将另辟蹊径,借助于我们熟悉的ASP.NET作为请求处理平台,通过一个简a单的托管程序模拟整个WCF客户端和服务端的架构。本篇文章的大部分内容节选自《WCF技术剖析(卷1)》第八章。Source Code下载:阅读全文
    posted @ 2009-06-18 21:24 Artech 阅读(17160) | 评论 (118) 编辑
     
    摘要: 由于绑定对象由一系列有序的绑定元素组成,绑定元素最终决定着信道栈中信道的组成,而信道的组成最终又决定了信道栈对消息进行处理的方式和能力,所有要确定绑定的特性和能力,我们可以通过查看其绑定元素的构成来一窥究竟... ...阅读全文
    posted @ 2008-12-14 13:16 Artech 阅读(4733) | 评论 (12) 编辑
     
    摘要: 在上面的内容中,先后介绍了信道、信道管理器、信道监听器和信道工厂。从对象的创建来讲,信道管理器是信道的创建者。说的再具体点,客户端的信道通过信道工厂创建,服务端的信道通过信道监听器创建。但是信道工厂和信道监听器又是如果被创建出来的呢? 我们在一开始就已经说过,作为终结点三要素的绑定对象实现了所有的通信细节,并且通过创建信道栈实现了消息的传递。从这一点来说,绑定对象无疑是信道层所有通信对象的最终缔造者,所以信道工厂和信道监听器最终的创建都是靠绑定对象实现的。关于这个创建过程又和另一个重要的对象密切相关,那就是绑定元素。阅读全文
    posted @ 2008-12-05 17:24 Artech 阅读(4687) | 评论 (20) 编辑
     
    摘要: 由于信道管理器在客户端和服务端所起的不同作用,分为信道监听器和信道工厂。和服务端的信道监听其相比,处于客户端的信道工厂显得简单。从名称就可以看得出来,信道工厂的作用就是单纯的创建用于消息发送的信道。我们先来看看与信道工厂相关的一些接口和基类的定义。阅读全文
    posted @ 2008-12-05 17:11 Artech 阅读(5331) | 评论 (10) 编辑
     
    摘要: WCF采用基于消息交换的通信方式,而绑定则实现了所有的通信细节。绑定通过创建信道栈实现了消息的编码与传输,以及对WS-*协议的实现。在这一节中,我们就来着重介绍WCF中的信道和信道栈。阅读全文
    posted @ 2008-11-14 11:05 Artech 阅读(6067) | 评论 (7) 编辑
     
    摘要: 下面通过一个简单的Console Application演示Type Innitializer的执行顺序。希望大家各抒己见,对于实验的结果给出一个圆满的解释,同时希望读者从中理解到更多关于编译、关于CLR一些被我们忽略的细节。阅读全文
    posted @ 2008-11-01 15:57 Artech 阅读(4267) | 评论 (21) 编辑
     
    摘要: WCF的通信是基于消息的,如果从消息交换(message exchange)的角度讲,信道层则可以看成是进行消息交换参与者之间的中介。信道层通过一个个信道组成一个连续的channel stack,该channel stack构成了一个消息流通的管道。消息的发送者通过该管道流到消息的接收者,消息的接收者对消息进行相应的处理,生成新的消息通过该管道回复给消息的发送者。本文将着重介绍WCF中的Binding模型,从该模型中,读者将会对WCF如何通过Binding创建channel stack的整个过程有一个大致的了解。阅读全文
    posted @ 2008-09-22 08:53 Artech 阅读(8533) | 评论 (26) 编辑
     
    摘要: 对于希望对WCF的消息交换有一个深层次了解的读者来说,tcpTracer绝对是一个不可多得好工具。我们将tcpTracer置于服务和服务代理之间,tcpTracer会帮助我们接获、显示和转发流经他的消息。 从本质上讲,tcpTracer是一个路由器。当启动的时候,我们需要设置两个端口:原端口(source port)和目的端口(destination port),然后tcpTracer就会在原端口进行网络监听。一旦请求抵达,他会截获整个请求的消息,并将整个消息显示到消息面板上。随后,tcpTracer会将该消息原封不动地转发给目的端口。在另一方面,从目的端口发送给原端口的消息,也同样被tcpTracer截获、显示和转发。 阅读全文
    posted @ 2008-09-19 15:56 Artech 阅读(6052) | 评论 (25) 编辑
     
    摘要: 对于所有的开发人员来说,Exception Handling是我们每天都要面对的事情。对于基于Source Code的Exception Handling,我想大家已经司空见惯了,但是对于Database级别的Exception Handling,就没有那么常见了。在这篇文章中,我将会介绍我对于基于Database编程中Exception Handling的一些粗浅的认识:在编写Stored Procedure时,如何抛出一个可预知的Exception,ADO.NET如何处理从Database抛出的Exception,如何保存基于Database Exception的Error Message,如何在Database和.NET Application之间进行消息的传递[注:这里的Database主要指SQL Server]。阅读全文
    posted @ 2008-08-28 13:44 Artech 阅读(3386) | 评论 (7) 编辑
     
    摘要: 我们都知道,WCF支持Duplex的消息交换模式,它允许在service的执行过程中实现对client的回调。WCF这种双向通信的方式是我们可以以Event Broker或者订阅/发布的方式来定义和调用WCF Service。今天我们就给大家一个具体的例子:通过WCF的duplex communication方式现在Session管理。阅读全文
    posted @ 2008-08-04 09:53 Artech 阅读(6251) | 评论 (27) 编辑
     
    摘要: 我们都知道,WCF支持Duplex的消息交换模式,它允许在service的执行过程中实现对client的回调。WCF这种双向通信的方式是我们可以以Event Broker或者订阅/发布的方式来定义和调用WCF Service。今天我们就给大家一个具体的例子:通过WCF的duplex communication方式现在Session管理。阅读全文
    posted @ 2008-08-04 09:49 Artech 阅读(8239) | 评论 (29) 编辑
     
    摘要: 在上一篇文章中,我们通过自定义InstanceProvider实现了WCF和微软Enterprise Library Unity Application Block的集成, 今天我们已相同的方式实现WCF与Enterprise Library的另一个Application Block的集成:Policy Injection Application Block (PIAB)。阅读全文
    posted @ 2008-07-29 09:22 Artech 阅读(6194) | 评论 (35) 编辑
     
    摘要: 松耦合、高内聚是我们进行设计的永恒的目标,如何实现这样的目标呢?我们有很多实现的方式和方法,不管这些方式和方法在表现形式上有什么不同,他们的思想都可以表示为:根据稳定性进行关注点的分离或者分解,交互双方依赖于一个稳定的契约,而降低对对方非稳定性因素的依赖。从抽象和稳定性的关系来讲,抽象的程度和稳定程度成正相关关系。由此才有了我们面向抽象编程的说法,所以“只有依赖于不变,才能应万变”... ...阅读全文
    posted @ 2008-07-28 09:15 Artech 阅读(5884) | 评论 (11) 编辑
     
    摘要: 在上一篇文章中,我们讨论了如何通过CallContextInitializer实现Localization的例子,具体的做法是将client端的culture通过SOAP header传到service端,然后通过自定义的CallContextInitializer设置当前方法执行的线程culture。在client端,当前culture信息是通过OperationContext.Current.OutgoingMessageHeaders手工至于SOAP Header中的。实际上,我们可以通过基于WCF的另一个可扩展对象来实现这段逻辑,这个可扩展对象就是MessageInspector。我们今天来讨论MessageInspector应用的另外一个场景:如何通过MessageInspector来传递Context信息。阅读全文
    posted @ 2008-07-24 09:06 Artech 阅读(6681) | 评论 (28) 编辑
     
    摘要: 在上一篇文章中, 我列出了WCF一系列的可扩展对象和元素,并简单介绍了他们各自的功能、适合的场景和具体解决的问题。从本篇开始我将通过一个个具体的例子来介绍如何利用这些扩展点对WCF进行扩展,从而解决一些我们在实现的项目开发中可能出现的问题。阅读全文
    posted @ 2008-07-17 09:15 Artech 阅读(5186) | 评论 (19) 编辑
     
    摘要: 在本系列的每篇文章中,我多次提到WCF是一个极具可扩展性的分布是消息通信框架。为了让读者对WCF Extension有一个总体的的认识,在这里我会简单列举了我们经常使用的绝大部分的扩展点,以及通过这些扩展点能够解决实现项目开发中的那些问题。阅读全文
    posted @ 2008-07-16 09:11 Artech 阅读(5695) | 评论 (18) 编辑
     
    摘要: 在本系列的第一部分、第二部分中,我们对WCF的channel layer进行了深入的讨论。我们接下来继续讨论WCF的ser vice mode layer。本篇文章着重介绍service 端的ServiceMode。写作此篇文章旨在达到以下两个目的: 希望读者对ServiceMode有一个大致的了解,结合前面介绍的channel layer的相关知识,帮助读者了解WCF的整个实现机制和执行的流程。 介绍ServiceMode涉及到的绝大部分extension point,让读者在具体的项目开发中能够根据实际的需要灵活、自由地对WCF进行扩展。阅读全文
    posted @ 2008-07-15 09:14 Artech 阅读(8049) | 评论 (54) 编辑
  • 相关阅读:
    第十五章:Android 调用WebService(.net平台)
    第十四章:样式(Style)和主题(Theme)
    第十三章:常用控件下
    第十三章:常用控件上
    第十二章:Android数据存储(下)
    第十一章:Android数据存储(上)
    第十章:Intent详解
    PHP7.X连接SQLSERVER数据库(CENTOS7)
    CentOs install oracle instant client
    softmax
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2419011.html
Copyright © 2011-2022 走看看