在ASP.NET MVC Web API中使用Apworks開發第一個HTTP服務

來源:互聯網
上載者:User

上周我發布了Apworks架構的最新版本,打算寫點文章來介紹如何在實際項目中使用Apworks進行開發。今天先簡單寫一點東西,首先說明一下,Apworks本身是面向領域驅動的一套開發架構,因此,領域模型的分析和建立就是使用Apworks的重點;然而,在大家對Apworks還沒有任何瞭解的基礎上,我暫時先拋開領域模型的建立,先向大家展示一下,如何使用Apworks開發第一個可以啟動並執行程式。在這篇文章的介紹中,我們的領域模型只有一個彙總:日記(Note),而且我們會將這個彙總對象同時用作資料轉送對象,這當然與DDD的宗旨是違背的,但為了簡化介紹過程,我們也不把問題複雜化了。現在,就讓我們一起來建立一個對“日記”資訊進行維護的ASP.NET MVC Web API應用程式吧。

通過本文的介紹,你將瞭解到:

  • Apworks下領域模型的建立
  • Apworks架構的初始化
  • 使用基於Entity Framework的倉儲實現彙總維護
建立ASP.NET MVC Web API項目

首先,建立一個ASP.NET MVC Web API項目,這個過程很簡單,開啟Visual Studio,然後建立一個ASP.NET MVC 4 Web Application,取名為NoteService(姑且取這個名字吧),然後在New ASP.NET MVC 4 Project對話方塊中,選擇Web API模板,然後直接單擊OK按鈕:

在完成解決方案的建立以後,在Solution Explorer(方案總管)中,可以看到標準的Web API目錄結構:

建立領域模型

再次聲明,雖然接下來的步驟會在NoteService的Models目錄下建立領域模型,但Models目錄本身是用來定義View Model的,作為領域模型,定義在另一個單獨的程式集中會更合適。總之,需要對領域模型(Domain Model)和視圖模型(View Model)進行區分。

首先,在NoteService項目上單擊右鍵,選擇Manage NuGet Packages菜單,在彈出的對話方塊中,搜尋Apworks,然後選擇Apworks,單擊Install按鈕:

接下來,在項目的Models目錄上點右鍵,選擇“Add –> Class”菜單,建立一個類,將類儲存成Note.cs檔案,並在檔案中輸入以下代碼:

using Apworks;using System;namespace NoteService.Models{    public enum Weather    {        Cloudy, Rainy, Sunny, Windy    }    public class Note : IAggregateRoot    {        public Guid ID { get; set; }        public string Title { get; set; }        public string Content { get; set; }        public DateTime CreatedDate { get; set; }        public Weather Weather { get; set; }    }}

行了,目前我們就只建立一個彙總:Note。從上面的代碼得知,彙總的根需要繼承於IAggregateRoot介面。

使用Unity作為IoC容器

Apworks目前僅整合了Unity作為整個架構的IoC容器,因此,我們需要為Unity的使用作準備。同樣,開啟Manage NuGet Packages對話方塊,從中選擇Apworks Unity Object Container,然後點擊Install安裝。注意:此時NuGet會把所依賴的Unity也一併安裝:

另外,我們還需要添加對Unity.WebAPI組件的引用,該組件提供了Unity對WebAPI的整合,以便能夠在WebAPI中更好地使用Unity。用同樣的方法添加引用:

OK,使用Unity的準備工作已經完成了,接下來,我們對Apworks進行配置。

配置Apworks架構

Apworks架構提供三種配置方式:app/web.config、直接寫代碼配置(使用RegluarConfigSource類),以及Fluent  Interface。為應用程式框架提供多樣化的配置方式,這是架構架構中必不可少的工作,究其原因和實現方式,請參考我以前寫的一篇文章:《.NET應用程式框架架構設計實踐 - 為應用程式架構提供多樣化的配置方式》。Fluent Interface這種配置方式的實現,請參考我前面寫的文章:《在C#中使用裝飾器模式和擴充方法實現Fluent Interface》。下面言歸正傳。

開啟Global.asax.cs檔案,首先添加對Apworks.Application、Apworks.Config.Fluent、Microsoft.Practices.Unity和Unity.WebApi這幾個命名空間的引用,然後在Application_Start中添加以下代碼:

AppRuntime.Instance    .ConfigureApworks()    .UsingUnityContainerWithDefaultSettings()    .Create((sender, e) =>        {            var container = e.ObjectContainer.GetWrappedContainer<UnityContainer>();            // TODO: register types            GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);        }).Start();

上面代碼應該非常清晰地表述了配置內容,我也就不多解釋了,在應用中可以使用IntelliSense來瞭解一下Apworks Fluent Interface還實現了哪些設定項目。

使用基於Entity Framework的倉儲

以同樣的方法,引入Apworks Entity Framework Repository組件:

在NoteService項目上建立一個類,取名為NoteServiceDbContext,該類實現如下:

public class NoteServiceDbContext : DbContext{    public NoteServiceDbContext()        : base("NoteServiceDB") { }    public DbSet<Note> Notes { get; set; }    protected override void OnModelCreating(DbModelBuilder modelBuilder)    {        modelBuilder.Entity<Note>()            .HasKey(p => p.ID)            .Property(p => p.ID)            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);        base.OnModelCreating(modelBuilder);    }}

另外,為了能在第一次建立資料庫時,加入一些樣本資料作為測試,我還添加了以下類:

public class NoteServiceInitializer : DropCreateDatabaseIfModelChanges<NoteServiceDbContext>{    protected override void Seed(NoteServiceDbContext context)    {        new List<Note>        {            new Note            {                Title = "My first note",                 Content = "This is my first note.",                 CreatedDate = DateTime.Now,                 Weather = Weather.Sunny            },            new Note            {                Title = "My second note",                 Content = "This is my second note.",                 CreatedDate = DateTime.Now,                 Weather = Weather.Windy            }        }.ForEach(p => context.Notes.Add(p));    }}

好了,Entity Framework的準備已經做好,接下來就是幾個常規的配置項。

首先,修改web.config檔案,將Entity Framework的資料庫連接配置加上:

<entityFramework><defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">  <parameters><parameter value="Data Source=(LocalDb)\v11.0; Initial Catalog=NoetServiceDB; Integrated Security=True; Connect Timeout=120; MultipleActiveResultSets=True; AttachDBFilename=|DataDirectory|\NoteServiceDB.mdf" />  </parameters></defaultConnectionFactory></entityFramework>

然後,開啟Global.asax.cs檔案,將Application_Start方法修改成:

protected void Application_Start(){    AreaRegistration.RegisterAllAreas();    WebApiConfig.Register(GlobalConfiguration.Configuration);    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);    RouteConfig.RegisterRoutes(RouteTable.Routes);    BundleConfig.RegisterBundles(BundleTable.Bundles);    // Initialize database    Database.SetInitializer<NoteServiceDbContext>(new NoteServiceInitializer());    AppRuntime.Instance        .ConfigureApworks()        .UsingUnityContainerWithDefaultSettings()        .Create((sender, e) =>            {                var container = e.ObjectContainer.GetWrappedContainer<UnityContainer>();                // TODO: register types                container.RegisterInstance<NoteServiceDbContext>(new NoteServiceDbContext(), new PerResolveLifetimeManager())                    .RegisterType<IRepositoryContext, EntityFrameworkRepositoryContext>(new HierarchicalLifetimeManager(),                        new InjectionConstructor(new ResolvedParameter<NoteServiceDbContext>()))                    .RegisterType(typeof(IRepository<>), typeof(EntityFrameworkRepository<>));                GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);            }).Start();}

這部分代碼中,改動的地方是:1、使用Database.SetInitializer方法,設定EF的資料庫初始化策略,我們使用已經編寫好的NoteServiceInitializer作為初始化策略;2、在Create的委託方法中,我們添加了對IRepositoryContext、IRepository<>以及NoteServiceDbContext的類型註冊,以使用Entity Framework Repository。注意:IRepositoryContext被註冊為HierarchicalLifetimeManager生命週期,以便Unity能夠在Request結束時能夠正確調用IRepositoryContext的Dispose方法。詳細請參見:http://devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package。

開發Web API服務

在Solution Explorer(方案總管)中,將ValuesController改名為NotesController,然後,改寫NotesController類如下:

using Apworks.Repositories;using NoteService.Models;using System;using System.Collections.Generic;using System.Web.Http;namespace NoteService.Controllers{    public class NotesController : ApiController    {        readonly IRepository<Note> noteRepository;        public NotesController(IRepository<Note> noteRepository)        {            this.noteRepository = noteRepository;        }        // GET api/notes        public IEnumerable<Note> Get()        {            return noteRepository.FindAll();        }        // GET api/notes/6EE246A5-9E68-4BC9-BA24-7F4EC2B326D4        public Note Get(Guid id)        {            return noteRepository.GetByKey(id);        }        // POST api/notes        public void Post([FromBody]Note value)        {            noteRepository.Add(value);            noteRepository.Context.Commit();        }        // PUT api/notes/6EE246A5-9E68-4BC9-BA24-7F4EC2B326D4        public void Put(Guid id, [FromBody]Note value)        {            var note = noteRepository.GetByKey(id);            note.Title = value.Title;            note.Content = value.Content;            note.CreatedDate = value.CreatedDate;            note.Weather = value.Weather;            noteRepository.Update(note);            noteRepository.Context.Commit();        }        // DELETE api/notes/6EE246A5-9E68-4BC9-BA24-7F4EC2B326D4        public void Delete(Guid id)        {            var note = noteRepository.GetByKey(id);            noteRepository.Remove(note);            noteRepository.Context.Commit();        }    }}

OK,至此,一個使用Apworks開發的ASP.NET MVC Web API服務已經完成,由於DependencyResolver的使用,NotesController在被建立時會獲得IRepository<Note>的執行個體(由IoC通過建構函式注入),於是,在每個方法調用中,都能使用Note倉儲完成所需的操作。

測試

我們可以使用Microsoft ASP.NET Web API Client Libraries對開發的Web API服務進行測試,具體用法也就不說了,可以自行參閱網上的文章。例如:可以用以下方法測試GET請求:

[TestClass]public class NoteServiceTest{    static readonly HttpClient client = new HttpClient();    [ClassInitialize]    public static void TestInitialize(TestContext context)    {        client.BaseAddress = new Uri("http://localhost:10895");        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));    }    [TestMethod]    public void GetTest()    {        var response = client.GetAsync("api/notes").Result;        Assert.IsTrue(response.IsSuccessStatusCode);        var notes = response.Content.ReadAsAsync<IEnumerable<Note>>().Result;        Assert.IsTrue(notes.Count() > 0);    }}

限於篇幅,其它方法的測試案例我就不貼代碼了,我是通過了所有測試的:

總結

本文介紹了在ASP.NET MVC Web API中使用Apworks架構開發一個簡單的HTTP服務的一般步驟。通過本文的介紹,我們可以瞭解到如何基於Apworks建立我們的領域模型,如何配置Apworks以使用Unity Container,如何配置Apworks以使用基於Entity Framework的倉儲。同時我們還瞭解到了一些ASP.NET MVC Web API的開發技術,希望本文對打算使用Apworks進行面向領域驅動架構開發的開發人員有一定的協助。

或許在讀完本文之後,你會覺得,在本案例中,直接使用Entity Framework貌似要比使用Apworks來得更快。不錯,本案例僅僅是對Apworks的一個開場示範,它的重點是在Apworks架構的使用上,而不是在Entity Framework上。主要是時間有限,我目前沒有辦法再去使用Apworks重新做一套完整的案例(事實上我已經向社區貢獻了一個案例:Byteart Retail,不過它並沒有使用Apworks的任何組件),但我有可能會在近期將Byteart Retail改成使用Apworks實現,相信到時候你會發現:使用Apworks開發面向領域驅動分層架構的應用程式,真的非常簡單。我也會不定期地繼續發布一些有關Apworks架構應用的文章,來協助大家更好地理解這個架構。

本文案例代碼

請【單擊此處】下載本文案例代碼,下載解壓後請用Visual Studio 2012 Update 2開啟解決方案檔案。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.