Last week, I released the latest version of the Apworks framework. I plan to write some articles to introduce how to use Apworks for development in actual projects. Today, I would like to briefly write something. First of all, Apworks is a domain-driven development framework. Therefore, the analysis and establishment of Domain Models is the focus of Apworks. However, on the basis that you have no knowledge about Apworks, I will leave the domain model for the moment and show you how to use Apworks to develop the first program that can run. In this article, our domain model has only one aggregation: Note, and we will use this aggregation object as a data transmission object at the same time, of course, this is against the purpose of DDD, but we will not complicate the problem to simplify the introduction process. Now, let's create an ASP. net mvc Web API application that maintains the "Diary" information.
Through the introduction in this article, you will understand:
- Domain Model Establishment in Apworks
- Apworks framework Initialization
- Aggregate maintenance using Entity Framework-based Warehousing
Create an ASP. net mvc Web API Project
First, create an ASP. net mvc Web API project, the process is very simple, open Visual Studio, and then create a new ASP. net mvc 4 Web Application, named NoteService (let's take this name), and then in New ASP. in the. net mvc 4 Project dialog box, select the Web API template and click OK:
After creating a Solution, you can see the standard Web API directory structure in Solution Explorer:
Create a domain model
Again, although the next step will create a domain Model under the Models directory of NoteService, the Models directory is used to define the View Model as the domain Model, the definition is more appropriate in another separate assembly. In short, the Domain Model and View Model need to be differentiated.
First, right-click the NoteService project, select the Manage NuGet Packages menu, search for Apworks in the pop-up dialog box, select Apworks, and click the Install button:
Next, right-click the Models directory of the project, select the "Add-> Class" menu, create a Class, save the Class as the Note. cs file, and enter the following code in the file:
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; } }}
Now, we only create one aggregation: Note. The code above shows that the aggregated root must inherit from the IAggregateRoot interface.
Use Unity as an IoC container
Apworks currently only integrates Unity as the IoC container of the entire framework. Therefore, we need to prepare for the use of Unity. Similarly, open the Manage NuGet Packages dialog box, select Apworks Unity Object Container, and click Install. Note: In this case, NuGet will install the dependency Unity together:
In addition, we also need to add references to the Unity. WebAPI component, which provides Unity's integration with WebAPI to better use Unity in WebAPI. Add reference in the same way:
OK. The preparation for using Unity is complete. Next, we will configure Apworks.
Configure the Apworks framework
The Apworks framework provides three configuration methods: app/web. config, Directly Writing code configuration (using the RegluarConfigSource class), and Fluent Interface. Providing a variety of configuration methods for the application framework is essential in the framework architecture. For the reasons and implementation methods, please refer to an article I wrote earlier :《.. NET application framework architecture design practices-provides diverse configuration methods for application frameworks. For the implementation of Fluent Interface configuration, see the article I wrote earlier: using the decorator mode and Extension Method in C # To implement Fluent Interface. Let's get down to the truth.
Open Global. asax. cs file, first add to Apworks. application, Apworks. config. fluent, Microsoft. practices. unity and Unity. add the following code in 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();
The above code should clearly describe the configuration content, so I will not explain it much. In the application, you can use intelliisense to understand which configuration items are implemented by Apworks Fluent Interface.
Use Entity Framework-based Warehousing
Introduce the Apworks Entity Framework Repository component in the same way:
Create a new class in the NoteService project named NoteServiceDbContext. The implementation of this class is as follows:
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); }}
In addition, in order to add some sample data for testing during the first database creation, I also added the following classes:
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)); }}
Now, the Entity Framework is ready, and the following are some common configuration items.
First, modify the web. config file and add the following to the database connection configuration of the 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>
Then, open the Global. asax. cs file and modify the Application_Start method:
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();}
In this part of the code, the changes are: 1. Use Database. setInitializer method, set EF database initialization policy, we use the prepared NoteServiceInitializer as the initialization policy; 2. In the Create delegate method, we have added type registration for IRepositoryContext, IRepository <> and NoteServiceDbContext to use Entity Framework Repository. Note: IRepositoryContext is registered as HierarchicalLifetimeManager, so that Unity can correctly call the Dispose method of IRepositoryContext at the end of the Request. For details, see http://devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package.
Develop Web API Service
In Solution Explorer, rename ValuesController to NotesController, and then rewrite the NotesController class as follows:
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. Now, an ASP. net mvc Web API service has been completed. Due to the use of DependencyResolver, NotesController will obtain the IRepository <Note> instance (injected by IoC through constructor) when it is created. Therefore, in each method call, you can use the Note warehouse to complete the required operations.
Test
You can use Microsoft ASP. NET Web API Client Libraries to test the developed Web API service. You can refer to the articles on the Internet. For example, you can test the GET request using the following methods:
[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); }}
Due to space limitations, I will not post code to the test cases of other methods. I have passed all tests:
Summary
This document describes how to use the Apworks framework to develop a simple HTTP service in ASP. net mvc Web API. Through the introduction in this article, we can learn how to create our domain model based on Apworks, how to configure Apworks to use Unity Container, and how to configure Apworks to use Entity Framework-based warehousing. At the same time, we also learned some ASP. net mvc Web API development technologies. I hope this article will help developers who intend to use Apworks for domain-driven architecture development.
After reading this article, you may feel that using Entity Framework directly in this case seems faster than using Apworks. Yes. This case is just an opening demonstration of Apworks. It focuses on the use of the Apworks Framework rather than on the Entity Framework. I have no way to use Apworks to create a complete set of cases. (In fact, I have contributed a case to the Community: Byteart Retail, but it does not use any components of Apworks), but I may change Byteart Retail to Apworks in the near future. I believe you will find that: it's really easy to use Apworks to develop applications that drive a layered architecture. I will also occasionally release some articles on the Apworks framework application to help you better understand this framework.
Case code
Click here to download the case code in this article. After downloading and unzipping, use Visual Studio 2012 Update 2 to open the solution file.