使用 ServiceStack 構建跨平臺 Web 服務(轉)

出處:http://www.cnblogs.com/shanyou/p/3348347.htmlhtml

本文主要來自MSDN雜誌《Building Cross-Platform Web Services with ServiceStack》,Windows Communication Foundation (WCF) 是一個至關優秀的服務框架,當咱們討論跨平臺的服務的時候,雖然WCF對WebService的支持還行,在面對一些高級應用的不太好,微軟從新發展了ASP.NET WebAPI框架,關於這兩個框架的討論能夠看我另一篇文章《WCF和ASP.NET Web API在應用上的選擇》 。在討論跨平臺的Web服務上,ASP.NET Web API是一個重要選項,在本文中,我將展現如何利用 ServiceStack (開放源代碼.NET 和Mono REST 服務框架) 來完成這一任務,不用離開 Visual Studio 或 Microsoft.NET/Mono,除了 ServiceStack 以外還有個Nancy的框架,具體能夠看《.NET的微型Web框架 Nancy》。git

一個典型的 Web 服務結構以下:github

Print

  • 服務層是您定義您的Web 服務接口的地方。 這也是,客戶端和你的 Web 服務進行交互的一層。
  • 業務層一般是業務邏輯
  • 數據層是爲了封裝數據訪問和操縱在業務層提供抽象的數據模型。
  • Web服務一般有遠程過程調用(RPC)和RESTful (HTTP)兩類,如今佔據主導地位的Web服務是RESTful (HTTP),具體內容能夠參看文章《REST在企業中得到成功了麼?》,貼一張文章裏的圖片:

REST&SOAP1

2年前REST就已經成爲Web API部署方式的主流了,並且一直保持這種發展勢頭,如今基本上都是REST服務,SOAP在企業內網還存在。web

遠程過程調用 (RPC) ,每一個請求旨在相似於函數調用:服務器

public interface IServiceapp

{框架

      string DoSomething(int input);ide

}函數

RPC 方法對服務的修改很是不友好。 例如前面的代碼段,若是要求從客戶端來執行更高版本的 Web 服務的 DoSomething 方法的兩個輸入參數 — 或須要返回字符串值以外的另外一個字段 —— 給老客戶重大更改是不可避免的。 固然,您始終能夠建立平行的 DoSomething_v2 方法,要帶兩個輸入的參數,但長此以往會搞亂您的 Web 服務接口和消費者,服務變得愈來愈醜,用WCF實現的Web服務就是屬於這種狀況,下面咱們介紹ServiceStack。性能

ServiceStack是.Net和Mono的開源框架,相對WCF,MVC及Web API而言它是開發Web服務與Web應用的有力替代品,它愈來愈普及。 用 ServiceStack 生成的 web 服務能夠運行在 Windows 環境中,.NET 代碼或Mono支持 Linux 環境中。 Mono支持的操做系統包括:

  • Linux
  • Mac OS X, iOS
  • Sun Solaris
  • BSD
  • Microsoft Windows
  • Nintendo Wii
  • Sony PlayStation 3

ServiceStack是一系列事物的綜合體:

ServiceStack 強制遠程 Web 服務最佳實踐、 基於公約 DTO 標準爲其 Web 服務接口,ServiceStack 還提供預置的響應狀態對象,可用於撰寫 DTO,鼓勵更加直接和簡單的錯誤處理方案,顯然和WCF是明顯不一樣的路線。

本文假定您有一些熟悉 WCF 和.NET 框架。 爲了更好地展現WCF 概念能夠如何轉化爲 ServiceStack 的概念,首先會在WCF中實現服務層。我會告訴你如何經過將WCF Web 服務移植到等效的使用 ServiceStack 轉換爲跨平臺的 Web 服務。

WCF 使用數據合同創建的客戶端和服務器之間的通訊手段。 ServiceStack和WCF相同。 WCF 須要何數據對象和數據成員打上標記; 不然,WCF 簡單地忽略它們。 這是 ServiceStack 和 WCF 與的不一樣的地方。 ServiceStack 支持全部POCO 的對象做爲契約:

WCF的契約:

   [DataContract] 
    public class Ticket 
    { 
        [DataMember] 
        public int TicketId { get; set; } 
        [DataMember] 
        public int TableNumber { get; set; } 
        [DataMember] 
        public int ServerId { get; set; } 
        [DataMember] 
        public List<Order> Orders { get; set; } 
        [DataMember] 
        public DateTime Timestamp { get; set; } 
    } 
    [ServiceContract] 
    public interface ITicketService 
    { 
        /// <summary> 
        /// 檢索當前隊列中的全部門票的完整清單 
        /// </summary> 
        /// <returns></returns> 
        [OperationContract] 
        List<Ticket> GetAllTicketsInQueue();

        /// <summary> 
        /// 新增新門票 
        /// </summary> 
        /// <param name="ticket"></param> 
        [OperationContract] 
        void QueueTicket(Ticket ticket);

        /// <summary> 
        /// 從隊列拉出一張票 
        /// </summary> 
        /// <returns></returns> 
        [OperationContract] 
        Ticket PullTicket(); 
    } 
}

把它轉換爲ServiceStack的契約:

public class Ticket 

       public int TicketId { get; set; } 
        public int TableNumber { get; set; } 
        public int ServerId { get; set; } 
        public List<Order> Orders { get; set; } 
        public DateTime Timestamp { get; set; }

}

public class GetAllTicketsInQueueRequest 

}

public class QueueTicketRequest 

    public Ticket Ticket { get; set; } 
}

public class PullTicketRequest 

}

public interface ISCTicketService 

    List<Ticket> Any(GetAllTicketsInQueueRequest request);

    void Any(QueueTicketRequest request);

    Ticket Any(PullTicketRequest request); 
}

ServiceStack 規定每一個惟一的請求是對象所標識惟一的請求,這意味着你不能重用 DTO 跨多個服務實現與 ServiceStack 的請求。ServiceStack 支持不一樣的操做,若有 Get 和 Post。 您的選擇在這裏僅影響的 HTTP 請求。 指定任何 Web 服務請求是指能夠經過 HTTP GET 和 HTTP POST 調用操做。 這種強制措施,簡化了 rest 風格的 Web 服務實現。要將您的 ServiceStack Web 服務變成 rest 風格的 Web 服務,只需添加 URL [Route(...)]向您的 Web 服務請求聲明屬性。

    //Request DTO 
    public class Hello 
    { 
        public string Name { get; set; } 
    }

    //Response DTO 
    public class HelloResponse 
    { 
        public string Result { get; set; } 
        public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized 
    }

    //Can be called via any endpoint or format, see: http://servicestack.net/ServiceStack.Hello/ 
    public class HelloService : Service 
    { 
        public object Any(Hello request) 
        { 
            return new HelloResponse { Result = "Hello, " + request.Name }; 
        } 
    }

    //REST Resource DTO 
    [Route("/todos")] 
    [Route("/todos/{Ids}")] 
    public class Todos : IReturn<List<Todo>> 
    { 
        public long[] Ids { get; set; } 
        public Todos(params long[] ids) 
        { 
            this.Ids = ids; 
        } 
    }

    [Route("/todos", "POST")] 
    [Route("/todos/{Id}", "PUT")] 
    public class Todo : IReturn<Todo> 
    { 
        public long Id { get; set; } 
        public string Content { get; set; } 
        public int Order { get; set; } 
        public bool Done { get; set; } 
    }

    public class TodosService : Service 
    { 
        public TodoRepository Repository { get; set; }  //Injected by IOC

        public object Get(Todos request) 
        { 
            return request.Ids.IsEmpty() 
                ? Repository.GetAll() 
                : Repository.GetByIds(request.Ids); 
        }

        public object Post(Todo todo) 
        { 
            return Repository.Store(todo); 
        }

        public object Put(Todo todo) 
        { 
            return Repository.Store(todo); 
        }

        public void Delete(Todos request) 
        { 
            Repository.DeleteByIds(request.Ids); 
        } 
    }   

以ASP.NET Hosting承載ServiceStack,建立一個空的ASP.NET應用,使用 NuGet 包管理器控制檯將 ServiceStack 引用添加到 ServiceStack.Host.AspNet中所示

image

Web.config 會增長下面的配置

<configuration> 
  <system.web> 
    <compilation debug="true" targetFramework="4.0" /> 
    <httpHandlers> 
      <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" /> 
    </httpHandlers> 
  </system.web> 
  <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true" /> 
    <validation validateIntegratedModeConfiguration="false" /> 
    <handlers> 
      <add path="*" name="ServiceStack.Factory" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" /> 
    </handlers> 
  </system.webServer> 
</configuration>

你須要從 ServiceStack.WebHost.End 繼承­實現端點。

public class AppHost  : AppHostBase 
    {        
        public AppHost() //Tell ServiceStack the name and where to find your web services 
            : base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly) { }

        public override void Configure(Funq.Container container) 
        { 
            //Set JSON web services to return idiomatic JSON camelCase properties 
            ServiceStack.Text.JsConfig.EmitCamelCaseNames = true; 
        
            //Configure User Defined REST Paths 
            Routes 
              .Add<Hello>("/hello") 
              .Add<Hello>("/hello/{Name*}");

            //Uncomment to change the default ServiceStack configuration 
            //SetConfig(new EndpointHostConfig { 
            //});

            //Enable Authentication 
            //ConfigureAuth(container);

            //Register all your dependencies 
            container.Register(new TodoRepository());            
        }

        /* Uncomment to enable ServiceStack Authentication and CustomUserSession 
        private void ConfigureAuth(Funq.Container container) 
        { 
            var appSettings = new AppSettings();

            //Default route: /auth/{provider} 
            Plugins.Add(new AuthFeature(() => new CustomUserSession(), 
                new IAuthProvider[] { 
                    new CredentialsAuthProvider(appSettings), 
                    new FacebookAuthProvider(appSettings), 
                    new TwitterAuthProvider(appSettings), 
                    new BasicAuthProvider(appSettings), 
                }));

            //Default route: /register 
            Plugins.Add(new RegistrationFeature());

            //Requires ConnectionString configured in Web.Config 
            var connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString; 
            container.Register<IDbConnectionFactory>(c => 
                new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));

            container.Register<IUserAuthRepository>(c => 
                new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));

            var authRepo = (OrmLiteAuthRepository)container.Resolve<IUserAuthRepository>(); 
            authRepo.CreateMissingTables(); 
        } 
        */

        public static void Start() 
        { 
            new AppHost().Init(); 
        } 
    }

ServiceStack Web 應用程序啓動時,您的服務合同列出做爲元數據操做,如圖所示:

image

相關文章:

SignalR, Filters and ServiceStack

採訪ServiceStack的項目領導Demis Bellot——第1部分

採訪ServiceStack的項目領導Demis Bellot——第2部分            

相關文章
相關標籤/搜索