Getting Started Series -ASP.NET Core MVC Introduction - Chapter One

About this tutorial

In this tutorial series, you will build an application to manage a list of books and their authors.  The Entity Framework Core (Core EF) will be used as ORM provider, because it is the default database provider.

This is the first chapter of this tutorial, all sections, here are all the chapters:

You can from GitHub repository to access the application code source. You can also watch this tutorial by community members ABP recorded video lessons .

Create a project

Create a file called Acme.BookStorenew project, create a database and follow the Getting Started documentation to run the application.

Structural solutions

The following picture shows a project from start to create a template of how hierarchical.

bookstore-visual-studio-solution

You can view the application template document to learn more about the solution structure. However, you will learn the basics of this tutorial.

Create a Book entity

Domain layer starting template is divided into two items:

  • Acme.BookStore.DomainInclude your entityfield service and other core domain objects.
  • Acme.BookStore.Domain.SharedIt contains constants that can be shared with customers, enumeration, or other domain related objects.

In the solution domain layer ( Acme.BookStore.Domaindefined Project) entity main application is the entity. BookIn. Acme.BookStore.DomainTo create a project called Bookclasses, as follows:

using System;
using Volo.Abp.Domain.Entities.Auditing;

namespace Acme.BookStore
{
    public class Book : AuditedAggregateRoot<Guid>
    {
        public string Name { get; set; }

        public BookType Type { get; set; }

        public DateTime PublishDate { get; set; }

        public float Price { get; set; }
    }
}
  • ABP provides a solid base two basic classes:  AggregateRootand EntityAggregate Root is Domain Driven Design (DDD)  one of the concepts and best practices For more information, please refer to. Physical document .
  • BookEntity inherited AuditedAggregateRoot, AuditedAggregateRootclass AggregateRootadds some class on the basis of audit attributes ( CreationTimeCreatorIdLastModificationTime etc.).
  • GuidIt is the Bookprimary key of the entity type.
  • Using  data annotations  to EF Core Add Mapping. Or you can use EF Core comes with FLUENT Mapping API .

BookType Enumeration

The use of the above BookTypeenumeration defined as follows:

namespace Acme.BookStore
{
    public enum BookType
    {
        Undefined,
        Adventure,
        Biography,
        Dystopia,
        Fantastic,
        Horror,
        Science,
        ScienceFiction,
        Poetry
    }
}

Adding to the Book entity in DbContext

EF Core you will need to associate entities and DbContext easiest way is in. Acme.BookStore.EntityFrameworkCoreThe project BookStoreDbContextto add class DbSetattributes as follows:

public class BookStoreDbContext : AbpDbContext<BookStoreDbContext>
{
    public DbSet<Book> Books { get; set; }
    ...
}

Book your configuration entity

In Acme.BookStore.EntityFrameworkCoreopen project BookStoreDbContextModelCreatingExtensions.csfile and add the following code to the ConfigureBookStoreend of the method is to configure the Book entity:

builder.Entity<Book>(b =>
{
    b.ToTable(BookStoreConsts.DbTablePrefix + "Books", BookStoreConsts.DbSchema);
    b.ConfigureByConvention(); //auto configure for the base class props
    b.Property(x => x.Name).IsRequired().HasMaxLength(128);
});

Add a new Migration and update the database

Use this template to start the EF Core Code First Migrations to create and maintain the database structure. Open the  Package Manager Console (Package Penalty for Manager Console) (PMC)  (Tools / Nuget Package Manager menu), select  Acme.BookStore.EntityFrameworkCore.DbMigrationsas the default project and then do the following The command:

bookstore-pmc-add-book-migration

In this way we will Migrationscreate a new migration class folder and then execute Update-Databasethe command to update the database structure.

PM> Update-Database

Add sample data

Update-DatabaseIn order to create a database AppBookstable to open the database and enter a few example lines, in order to display them on the page:

Creating Application Services

The next step is to create the application services to manage (create, list, update, delete) book launch application layer template is divided into two items:

  • Acme.BookStore.Application.ContractsDTO contains your main application and service interface.
  • Acme.BookStore.ApplicationIt contains implement application services.

BookDto

In Acme.BookStore.Application.Contractscreating a project called BookDtoDTO class:

using System;
using Volo.Abp.Application.Dtos;

namespace Acme.BookStore
{
    public class BookDto : AuditedEntityDto<Guid>
    {
        public string Name { get; set; }

        public BookType Type { get; set; }

        public DateTime PublishDate { get; set; }

        public float Price { get; set; }
    }
}
  • DTO classes are used in the  presentation layer  and the  application layer  transmitted data . See DTO documentation for more information.
  • In order to display the book information on the page, BookDtoit is used to pass data to the presentation layer of books.
  • BookDtoInherited from  AuditedEntityDto<Guid>. Defined above with Bookthe same class have some audit attributes.

When the book is returned to the presentation layer, we need to Bookconvert entities BookDtosubject.  AutoMapper library can automatically perform this conversion when defining the correct mapping startup template configured AutoMapper, so you just in. Acme.BookStore.ApplicationThe project BookStoreApplicationAutoMapperProfiledefined in the class mapping:

using AutoMapper;

namespace Acme.BookStore
{
    public class BookStoreApplicationAutoMapperProfile : Profile
    {
        public BookStoreApplicationAutoMapperProfile()
        {
            CreateMap<Book, BookDto>();
        }
    }
}

CreateUpdateBookDto

In Acme.BookStore.Application.Contractscreating a project called CreateUpdateBookDtoDTO class:

using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.AutoMapper;

namespace Acme.BookStore
{
    public class CreateUpdateBookDto
    {
        [Required]
        [StringLength(128)]
        public string Name { get; set; }

        [Required]
        public BookType Type { get; set; } = BookType.Undefined;

        [Required]
        public DateTime PublishDate { get; set; }

        [Required]
        public float Price { get; set; }
    }
}
  • The DTO class is used to get book information from the user interface when creating or updating books.
  • It defines the annotation data attributes (e.g. [Required]) to verify the defined attributes. ABP the DTO by the frame automatically verified .

Like the above BookDto, as a creation from CreateUpdateBookDtoobject to the Bookmapping of entities:

CreateMap<CreateUpdateBookDto, Book>();

IBookAppService

In Acme.BookStore.Application.Contractsthe project define a named IBookAppServiceinterface:

using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;

namespace Acme.BookStore
{
    public interface IBookAppService : 
        ICrudAppService< //定义了CRUD方法
            BookDto, //用来展示书籍
            Guid, //Book实体的主键
            PagedAndSortedResultRequestDto, //获取书籍的时候用于分页和排序
            CreateUpdateBookDto, //用于创建书籍
            CreateUpdateBookDto> //用于更新书籍
    {

    }
}
  • Interface Framework defines application service is not required . However, it is recommended as a best practice.
  • ICrudAppServiceDefines the common CRUD methods: GetAsync, GetListAsync, CreateAsync, UpdateAsyncand DeleteAsync. You can start with an empty IApplicationServiceinterface inheritance and manually define their own methods.
  • ICrudAppServiceThere are some variations, you can use a separate DTO in each method, may be respectively separately specified.

BookAppService

In Acme.BookStore.Applicationthe project realization called BookAppServicethe IBookAppService:

using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

namespace Acme.BookStore
{
    public class BookAppService : 
        CrudAppService<Book, BookDto, Guid, PagedAndSortedResultRequestDto,
                            CreateUpdateBookDto, CreateUpdateBookDto>,
        IBookAppService
    {
        public BookAppService(IRepository<Book, Guid> repository) 
            : base(repository)
        {

        }
    }
}
  • BookAppServiceInherited CrudAppService<...>. It implements CRUD method defined above.
  • BookAppServiceInjection IRepository <Book,Guid>, which is the Bookdefault storage entity. ABP automatically creates default storage for each aggregate root (or entity). See warehousing documentation
  • BookAppServiceUse IObjectMapperto Bookconvert an object to BookDtoobject, CreateUpdateBookDtoconvert the object to Bookobject. Start template AutoMapper library as the object mapping provider. Before you define the mapping, so it will work as expected.

Auto-generated API Controllers

You usually create Controller to the application service exposed as HTTP API endpoint, thus allowing the browser or through third-party client AJAX call them. ABP can automatically follow the conventions of your application service is configured MVC API controller.

Swagger UI

Start template configured to use Swashbuckle.AspNetCore run Swagger the UI . Run the application and enter in your browser https://localhost:XXXX/swagger/(replace with your own port XXXX) as the URL.

You will see some of the interface and built-in Bookinterfaces, they are REST-style:

bookstore-swagger

Swagger has a nice UI to test the API. You can try the [GET] /api/app/book API to get a list of books.

Dynamic JavaScript proxy

In Javascript end by way of calling AJAX HTTP API interfaces are very common, you can use $.ajaxor other tool to call interface. Of course, ABP provides a better way.

ABP  automatically  creates a JavaScript API interface for all  agents . So, as you can call the  JavaScript function the same as to call any interface.

In the browser's developer console test interface

You can use your favorite browser  developer console  . Easily test agent running JavaScript programs, and open the browser  developer tool (shortcut: F12), switch to the  Console  tab, enter the following code and press Enter:

acme.bookStore.book.getList({}).done(function (result) { console.log(result); });
  • acme.bookStoreIs the BookAppServicenamespace, converted hump named .
  • bookIt is the BookAppServicename (and to turn into camelCase addition AppService suffix) after conversion.
  • getListIt is defined in the AsyncCrudAppServicebase class GetListAsyncname (and to turn into camelCasing addition Async suffix) the method of conversion.
  • {}Parameters used to send null object to the GetListAsyncmethod, which usually requires a type PagedAndSortedResultRequestDtoof object that is used to send paging and sorting options to the server (all properties are optional, so you can send an empty object).
  • getListMethod returns a promiseresult, you can pass a callback function to done(or then) method to get the result returned by the service.

We use the createmethod  to create a new book :

acme.bookStore.book.create({
    name: 'Foundation',
    type: 7,
    publishDate: '1951-05-24',
    price: 21.5
}).done(function(result){
    console.log('successfullycreatedthebookwithid: '+result.id);
});

You will see the console displays output like this:

successfully created the book with id: f3f03580-c1aa-d6a9-072d-39e75c69f5c7

Check the database Bookstable to see the new books. You can try it yourself get, updateand deletefunction.

Create a book page

Now let's create some things visible and available to replace the classic MVC, we recommend the use of Microsoft's Razor Pages and the the UI .

In  Acme.BookStore.Webthe project Pagesto create a new file in the folder called Booksand add a file called Index.cshtmlthe Razor Page.

Open Index.cshtmland modify the contents such as the following:

@page
@using Acme.BookStore.Web.Pages.Books
@inherits Acme.BookStore.Web.Pages.BookStorePage
@model IndexModel

<h2>Books</h2>
  • This code changes the default inheritance Razor View Page Model, so it from the BookStorePageclass (and not PageModel) inheritance. Start the supplied template BookStorePageclass that provides a number of shared properties / methods used by all the pages.
  • Ensure IndexModel(Index.cshtml.cs) has a Acme.BookStore.Pages.Booksnamespace, or Index.cshtmlupdate it in.

Adding Books page to the main menu

Open Menusa folder  BookStoreMenuContributor class, the ConfigureMainMenuAsyncadd the following code at the bottom of the method:

context.Menu.AddItem(
    new ApplicationMenuItem("BooksStore", l["Menu:BookStore"])
        .AddItem(new ApplicationMenuItem("BooksStore.Books", l["Menu:Books"], url: "/Books"))
);

Localization menu

Localized text located in Acme.BookStore.Domain.Sharedthe project Localization/BookStorefolder:

Open the en.jsonfile, Menu:BookStoreand Menu:Bookslocalized text keys are added to the end of the file:

{
  "culture": "en",
  "texts": {
    "Menu:BookStore": "Book Store",
    "Menu:Books": "Books"
  }
}
  • ABP localization capabilities are built on ASP.NET Core's standard localization above and adds some extensions. View localized documentation .
  • Localization key is arbitrary. You can set any names. We prefer to add menu items Menu:prefix to distinguish them from other texts. If the text is not defined in the localization file, it will return to a localization key (ASP.NET Core standards of behavior).

Run the application, see the new menu item has been added to the top of the bar:

bookstore-menu-items

Click the Books menu item will jump to new pages of a book.

List of Books

We will use Datatables.net JQuery plugin to display a list of tables on the page. Data Sheet can work entirely via AJAX, fast, and provide a good user experience. Datatables plugin configuration in the startup template, so you can directly on any page use it, but need to reference the style and script files in the page.

Index.cshtml

Will be Pages/Books/Index.cshtmlchanged to look like this:

@page
@inherits Acme.BookStore.Web.Pages.BookStorePage
@model Acme.BookStore.Web.Pages.Books.IndexModel
@section scripts
{
    <abp-script src="/Pages/Books/index.js" />
}
<abp-card>
    <abp-card-header>
        <h2>@L["Books"]</h2>
    </abp-card-header>
    <abp-card-body>
        <abp-table striped-rows="true" id="BooksTable">
            <thead>
                <tr>
                    <th>@L["Name"]</th>
                    <th>@L["Type"]</th>
                    <th>@L["PublishDate"]</th>
                    <th>@L["Price"]</th>
                    <th>@L["CreationTime"]</th>
                </tr>
            </thead>
        </abp-table>
    </abp-card-body>
</abp-card>
  • abp-script tag helper for external  script  added to the page. It is more than a standard scripta lot more extra features label. It can handle  minimize and  version View bundling & compression documentation for more information.
  • abp-card And  abp-table for the Twitter Bootstrap's card component package  Tag helpers .ABP have a lot of tag helpers, you can easily use most of bootstrap components. You can also use native HTML tags instead of the tag helpers. Use tag helper can be smart tips and compile-time type checking to prevent errors and reduce HTML code. check tag helpers document .
  • You can localize menu like the one above as  localized  column names.

Adding a script file

In Pages/Books/creating folders in the  index.jsfile

bookstore-index-js-file

index.jsIt reads as follows:

$(function () {
    var dataTable = $('#BooksTable').DataTable(abp.libs.datatables.normalizeConfiguration({
        ajax: abp.libs.datatables.createAjax(acme.bookStore.book.getList),
        columnDefs: [
            { data: "name" },
            { data: "type" },
            { data: "publishDate" },
            { data: "price" },
            { data: "creationTime" }
        ]
    }));
});
  • abp.libs.datatables.createAjaxABP is to help the helper dynamic JavaScript API proxy with Datatable format compatible.
  • abp.libs.datatables.normalizeConfigurationAnother helper method. Is not necessary, but it simplifies the configuration by providing a conventional data table values ​​for the missing option.
  • acme.bookStore.book.getListThe method is to obtain a list of books (above has been introduced)
  • View  Datatable documentation  for more configuration items.

The next chapter

Click to see  the next chapter  introduction.

Published 87 original articles · won praise 69 · Views 600,000 +

Guess you like

Origin blog.csdn.net/S2T11Enterprise/article/details/104009840