Introduction to ABP framework based on asp.net mvc-practical tips

Source: Internet
Author: User

Why use ABP
In recent years we have developed a number of Web applications and desktop applications that require or are simple or complex, implemented or elegant or ugly. A basic fact is: we just accumulate some experience or improve the familiarity of the net.
With the increasing experience of software development, we find that many of the work is repetitive machinery, and as the complexity of the software continues to improve, the past rely on experience to complete a number of simple additions and deletions to check the practice has not been feasible. In particular, the requirements of users more and more high, want to add more features, the current development model, has been stretched. It's hard for me to imagine how to integrate multiple systems and add new features to existing models.
When developing a system, we will inevitably use a variety of frameworks. Data persistence layer implementation, log, asp.net MVC, IOC, and automatic mapping. A high-quality software system often has global fault tolerance, Message Queuing and other components.
When these components are grouped together, their complexity increases dramatically. It is difficult to design a balanced and coordinated framework for the technical skills of individuals and small teams in general. I am also very skeptical about the traditional so-called three-tier structure. (The three-tier architecture of the programmer with a monthly salary of 15k, I have read it carefully, is also a lot of problems, and can not explain why use three layers).
In fact, we just hope that when programming, most of the attention to focus on the business implementation. Do not think too much about the underlying software structure of the various problems. There should be a box or a paradigm to provide basic services such as logging, fault tolerance, and aop,di.
A slightly more formal company after years of precipitation has formed its own internal software framework, they are in the development of software is not from a blank start. It is built on a very solid foundation platform. This greatly increases the speed of development, and a framework often determines the pattern of division and collaboration. The reason why we are unable to work together is the lack of a mature and stable infrastructure and workflow.
Current. NET has a lot of open source framework. Like Apworks and ABP. Among them Apworks is a set of open source framework written by Chinese. It is a full-featured, not only can write distributed applications, but also can write desktop applications. ABP's full name is asp.net boilerplate project (asp.net model project). is a very active open source project on the GitHub. It does not use any new technology, but only two architects integrate some of the tools commonly used in asp.net development, and partially implement the concept of DDD. is an out-of-the-box framework that can serve as a good starting point for asp.net distributed applications.
There is a cost to using the framework, and you have to be intrusive by the framework's strong API or use his dialect. And this framework wants to be thorough, also pay a lot of learning cost. But the benefits are obvious. The industry's top architects have built an infrastructure for you, responding well to questions about how a software system should be designed and planned, and provide a set of best practices and examples.
Although learning to pay the cost, but after a long trek, we have been standing on the threshold of industrial development. Based on this framework, we can be very good to divide the task, the unit test and so on. Dramatically reduces the likelihood of software bugs.

Create an empty Web application from a template

ABP's official website: http://www.aspnetboilerplate.com
ABP Open Source project on GitHub: Https://github.com/aspnetboilerplate
ABP provides a startup template for new projects (although you can manually create projects and get ABP packages from NuGet, the template is easier to do).
Go to Www.aspnetboilerplate.com/Templates to create your application from the template.
You can choose a spa (Angularjs or Durandaljs) or select MPa (classic multiple page application) project. You can choose the Entity Framework or NHibernate as the ORM framework.
Here we select the Angularjs and entity Framework, fill in the project name "Simpletasksystem", click "CREATE My Project" button can download a zip compression package, decompression and get VS2013 solution, Use of. NET version is 4.5.1.

ABP components and other third-party components are referenced in each project and need to be downloaded from the NuGet.

The yellow exclamation point icon indicates that this component does not exist in the local folder and needs to be restored from the NuGet. The operation is as follows:

To get the project running, you also have to create a database. This template assumes that you are using a SQL2008 or newer version. Of course, it can be easily replaced with other relational databases.
Open the Web.config file to view and configure the link string:

Copy Code code as follows:

<add name= "Default" connectionstring= "server=localhost; Database=simpletasksystemdb; trusted_connection=true; "/>

(After using the EF code-Data Migration, a database named Simpletasksystemdb is automatically created in the SQL Server database.) )
In this way, the project is ready to run! Open VS2013 and press F5:
The following step-by-step implementation of this simple task System program

Create an entity
the entity class is written in the core project because the entity is part of the domain layer.
A simple scenario: create tasks and assign them to people. We need both the task and the person entities.
A task entity has several attributes: Description (Description), creation time (CreationTime), task status (state), and optional navigation properties (Assignedperson) to refer to person.

public class task:entity<long>
{
  [ForeignKey (' Assignedpersonid ')] public
  virtual person Assignedperson {get; set;}

  public virtual int? Assignedpersonid {get; set;}

  Public virtual string Description {get; set;}

  Public virtual DateTime CreationTime {get; set;}

  Public virtual taskstate state {get;}

  Public Task ()
  {
    creationtime = DateTime.Now;
    state = taskstate.active;
  }
}


The person entity is simpler and defines only one name property:
public class person:entity
{public
  virtual string Name {get; set;}
}

In the ABP framework, there is a entity base class that has an id attribute. Because the task class inherits from Entity<long>, it has an ID of type long. The person class has an ID of type int because the int type is the default type of the entity base class ID, and the ID of the entity is the int type when no particular type is specified.

Create DbContext
to use entityframework you need to define the DbContext class, ABP template has created DbContext file, we just need to add the task and person class to the Idbset, see Code:

public class Simpletasksystemdbcontext:abpdbcontext
{public
  virtual idbset<task> Tasks {get; set;} Public

  Virtual idbset<person> people {get; set;}

  Public Simpletasksystemdbcontext ()
    : Base (' Default ')
  {

  } public

  Simpletasksystemdbcontext (string nameorconnectionstring)
    : Base (nameorconnectionstring)
  {
      
  }
}

Create a database table from the DB migrations
we created the database schema using EntityFramework's code-I mode. The project generated by the ABP template already has the data migration enabled by default, and we modify Configuration.cs files under the Migrations folder under the Simpletasksystem.entityframework project:

Internal sealed class Configuration:

Dbmigrationsconfiguration<simpletasksystem.entityframework.simpletasksystemdbcontext>
{
  public Configuration ()
  {
    automaticmigrationsenabled = false;
  }

  protected override void Seed (SimpleTaskSystem.EntityFramework.SimpleTaskSystemDbContext context)
  {
    context . People.addorupdate (
      P => p.name,
      new Person {name = ' Isaac Asimov '},
      new person {name = ' Thomas More '},
   new person {name = "George Orwell"},
      new person {name = "Douglas Adams"}
      );
  }


In the Package Manager console window at the bottom of VS2013, select the default item and execute the command "Add-migration initialcreate"

A Xxxx-initialcreate.cs file is generated under the Migrations folder, which reads as follows:

Public partial class Initialcreate:dbmigration {public override void up () {createtable ("dbo. Stspeople ", c => new {Id = C.int (Nullable:false, identity:true), Name = C.string () ,
        })
      .
      
    PrimaryKey (t => t.id); CreateTable ("dbo.") Ststasks ", c => new {Id = C.long (Nullable:false, identity:true), Assignedpersonid = C.int (), Description = C.string (), CreationTime = C.datetime (nullable:false), state = C.b Yte (Nullable:false),}). PrimaryKey (t => t.id). ForeignKey ("dbo.") Stspeople ", T => T.assignedpersonid).      
  Index (t => T.assignedpersonid); public override void Down () {Dropforeignkey ("dbo.") Ststasks "," Assignedpersonid "," dbo. "
    Stspeople "); Dropindex ("dbo.")
    Ststasks ", new[] {" Assignedpersonid "}); Droptable ("dbo.")
    Ststasks "); Droptable ("dbo.")
  Stspeople ");

 }
}

Then continue to perform "update-database" in the Package Manager console, which automatically creates the corresponding datasheet in the database:
Pm> Update-database

The database appears as follows:

(after modifying the entity, you can perform add-migration and update-database again, so you can easily synchronize the database structure with the entity class)

Defining warehousing Interfaces
through the warehousing mode, you can better separate the business code from the database operation code, you can have different implementation classes for different databases, and the business code does not need to be modified.
The code that defines the warehousing interface is written to the core project because the warehousing interface is part of the domain layer.
Let's first define the storage interface for the task:

Public interface Itaskrepository:irepository<task, long>
{
  list<task> getallwithpeople (int? Assignedpersonid, Taskstate? State);
}

It inherits from the IRepository generic interface from the ABP framework.
In the irepository has already defined the commonly used to delete and change the search method:

So Itaskrepository has the above methods by default. It can be added to its unique method of Getallwithpeople (...).

You do not need to create a warehouse class for the person class, because the default method is sufficient. ABP provides a way to inject common warehousing, which will be seen in the Taskappservice class in the "Creating Application Services" section later.

Realize storage class
we will implement the Itaskrepository warehousing interface defined above in the EntityFramework project.

A project built from a template already defines a warehouse base class: Simpletasksystemrepositorybase (This is a good practice because you can add generic methods to this base class later).

public class Taskrepository:simpletasksystemrepositorybase<task, Long>, itaskrepository
{public
  List <Task> getallwithpeople (int assignedpersonid, taskstate State)
  {
    //In warehousing methods, do not have to deal with database connections, DbContext, and data transactions , the ABP framework is automatically processed.
      
    var query = GetAll ();//getall () returns a iqueryable<t> interface type
      
    //Add some where condition

    if ( Assignedpersonid.hasvalue)
    {
      query = query. Where (Task => task. Assignedperson.id = = Assignedpersonid.value);
    }

    if (state. HasValue)
    {
      query = query. Where (Task => task. state = = state)
    ;

    return query
      . OrderByDescending (Task => task. CreationTime)
      . Include Task => task. Assignedperson)
      . ToList ();
  }


Taskrepository inherits from Simpletasksystemrepositorybase and implements the Itaskrepository interface defined above.


Create an Application service (application services)
define application services in the application project. First, define the interface for the application service layer of the task:

Public interface Itaskappservice:iapplicationservice
{
  gettasksoutput gettasks (gettasksinput input);
  void Updatetask (Updatetaskinput input);
  void CreateTask (Createtaskinput input);
}

Itaskappservice inherits from IAPPLICATIONSERVICE,ABP automatically provides some functional features (such as dependency injection and parameter validation) for this class.

We then write the Taskappservice class to implement the Itaskappservice interface:

public class Taskappservice:applicationservice, Itaskappservice {private readonly itaskrepository _taskrepository;
    
  Private ReadOnly irepository<person> _personrepository; <summary>///constructors automatically inject the class or interface we need///</summary> public taskappservice (Itaskrepository taskrepository
    , irepository<person> personrepository) {_taskrepository = taskrepository;
  _personrepository = personrepository; Public gettasksoutput gettasks (gettasksinput input) {//specific method of calling task warehousing getallwithpeople var tasks = _task Repository.getallwithpeople (input. Assignedpersonid, input.

    State); Use AutoMapper to automatically convert list<task> to list<taskdto> return new Gettasksoutput {Tasks = mapper.ma
  P<list<taskdto>> (Tasks)}; The public void Updatetask (Updatetaskinput input) {//can be directly Logger, which is defined in Applicationservice base class Logger.info ("Up

    Dating a task for input: "+ input"; The general method of the warehouse base class get, gets the TA with the specified IDSK Entity Object var task = _taskrepository.get (input.

    TASKID); Modifies the attribute value of the task entity if (input. State.hasvalue) {task. state = input.
    State.value; } if (input. Assignedpersonid.hasvalue) {task. Assignedperson = _personrepository.load (input.
    Assignedpersonid.value); //We do not need to call the Update method///Because the method of applying the service layer opens the work unit mode by default (units of Work)//ABP the frame will automatically save all changes to the entity when the work unit completes, unless an exception is thrown.
  An exception is automatically rolled back because the work unit opens the database transaction by default.

    public void CreateTask (Createtaskinput input) {logger.info ("Creating a task for Input:" + input); Create a new task entity var task = Description = input by entering parameters.

    Description}; if (input. Assignedpersonid.hasvalue) {task. Assignedpersonid = input.
    Assignedpersonid.value;
  //Invoke the Insert method of the warehouse base class to save the entity to the database _taskrepository.insert (Task);

 }
}

Taskappservice uses warehousing for database operations, which leads to references to constructors that inject warehousing objects.

Data validation

If the parameter object of the application service method implements the Iinputdto or Ivalidate interface, ABP automatically validates the parameter validation.

The CreateTask method has a createtaskinput parameter, which is defined as follows:

public class Createtaskinput:iinputdto
{public
  int? Assignedpersonid {get; set;}

  [Required]
  public string Description {get; set;}
}

The Description property specifies that it is required by annotations. You can also use other Data Annotation attributes.

If you want to use custom validation, you can implement the Icustomvalidate interface:

public class Updatetaskinput:iinputdto, Icustomvalidate
{
  Range (1, long. MaxValue)] public
  long TaskId {get; set;}

  public int? Assignedpersonid {get; set;}

  Public taskstate? State {get; set;}

  public void Addvalidationerrors (list<validationresult> results)
  {
    if (Assignedpersonid = = null & & state = null)
    {
      results. ADD (New Validationresult ("Assignedpersonid and state cannot be empty at the same time!", new[] {"Assignedpersonid", "State"});}


You can write custom validation code in the Addvalidationerrors method.

Creating a Web API Service
ABP can easily publish the public method of the application service as a Web API interface that can be invoked by the client via Ajax.

Dynamicapicontrollerbuilder
  . Forall<iapplicationservice> (assembly.getassembly (typeof (Simpletasksystemapplicationmodule)), "Tasksystem" )
  . Build ();

Simpletasksystemapplicationmodule all classes that inherit the Iapplicationservice interface in this assembly will automatically create the corresponding Apicontroller, where the public method, is converted to the Webapi interface method.

Can be invoked through a routing address such as Http://xxx/api/services/tasksystem/Task/GetTasks.

Through the case above, the usage of the domain layer, infrastructure layer and application service layer is outlined.

The application service method can now be invoked directly in the controller action method of asp.net mvc.

If you are programming with spa single-page, you can invoke the corresponding application service method directly on the client via Ajax (by creating a Dynamic Web Api).

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.