2016年7月21日 星期四

[ASP.NET Core] Build MVC website with Entity Framework Core

 ASP.NET Core    MVC 6    Entity Framework Core  






▌Introduction


The ASP.NET Core 1.0.0 was released. Still lots of frameworks are in preview version, I makes this tutorial to take a first look at the new architecture and functions of .NET Core.

In this tutorial, we will learn how to build a development environment for .NET Core applications and create a MVC website with Entity Framework Core and NLog.

▌Environment

l   Visual Studio 2015 Update 3
l   Visual Studio 2015 DotNetCore tools – preview 2
l   DotNetCore 1.0.0 Runtime



Prepare


Update Visual Studio (Code)


Install .NET Core SDK

Find it on Microsoft .NET Framework Downloads.

Install .NET Core SDK

Download it here.


Build


Create ASP.NET Core website project




n   appsettings.json
Most settings in WebConfig was moved to this file. We will later add connctionString into appsettings.json.

n   bundleconfig.json
IN ASP.NET Core RC2 website tooling template, it uses Gulp to minify the javascripts and CSS. However in the release version, the ASP.NET Core uses BundlerMinifier to do the jobs.

Simply use the following command to bundle and minify the scripts and CSS.

$ dotnet bundle








 



n   project.json
project.json is the file which is for managing the packages and dependencies.
We can still use NUGET to install the package, or just editing the project.json and let the framework to restore or remove the packages for us.


n   web.config

WebConfig is still here.
(I am thinking that we can still use the old-school settings in WebConfig?)
Anyway, there is a critical setting here:

<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>

Set stdoutLogEnabled="true" (default is false) to log the IIS or Self-hosting message on the server.

 

NLog


Package



Injection

Then inject the NLog provider into loggerFactory in Startup.cs : Configure

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//add NLog to ASP.NET Core
    loggerFactory.AddNLog();
    //needed for non-NETSTANDARD platforms: configure nlog.config in your project root
    env.ConfigureNLog("NLog.config");
}


Usage

Usage in MVC Controller:

public class StoreController : Controller
{
        protected static Logger _logger = LogManager.GetCurrentClassLogger();
public IActionResult Index()
        {
           _logger.Debug($"Debug message from current logger!");
            _logger.Error($"Error message from current logger!");
}
}


Entity Framework Core


Package

DO NOT install EntityFramework.Core *, we have to install Microsoft.EntityFrameworkCore.SqlServer.

PS. EntityFramework.Core currently (2016/7/20) is in RC1. I had encountered compatibility problems with it in ASP.NET Core 1.0.0


ConnectionString

Add the connectionString in appsettings.json. For example,

 

Create DbContext and DAO

l   DbContext
public class DefaultDbContext : DbContext
{
    public DefaultDbContext(DbContextOptions options) : base(options)
    {}
    public DbSet<Store> Stores { get; set; }
}


l   DAO
[Table("Stores")]
public class Store
{
       [Key]
        public int Id { get; set; }
        [StringLength(200)]
        [Required]
        public string Name { get; set; }
        [StringLength(500)]
        public string Description { get; set; }
}


Injection

In this step, we will create DbContext and inject it to IServiceCollection.
In Startup.cs : ConfigureServices, add the following code.

public void ConfigureServices(IServiceCollection services)
{
   // Add Entity Framework
   services.AddDbContext<DefaultDbContext>(
                options => options.UseSqlServer(
                    Configuration["Data:DefaultConnection:ConnectionString"]));
}

Usage

Since we inject the EntityFrameworkCore.SqlServer provider, we can use the DbContext like this,

public class StoreController : Controller
{
    private DefaultDbContext _dbContext = null;
    public StoreController(DefaultDbContext dbContext)
    {
            this._dbContext = dbContext;
            //Do something with this._dbContext ...
    }
}

However, I didn’t make many tests on the connection pooling in this way.
So I would follow the old-school ways – create a new DbContext every time I use it, so I would like to make a Factory for this purpose.

l   DbContextFactory
public static class DbContextFactory
{
        public static string ConnectionString { get; set; }

        public static void SetConnectionString(string connStr)
        {
            ConnectionString = connStr;
        }

        public static DefaultDbContext Create(string newConnectionStr="")
        {
            var finalConnStr = string.Empty;
            if (string.IsNullOrEmpty(newConnectionStr))
                finalConnStr = ConnectionString;
            else
                finalConnStr = newConnectionStr;

            if (!string.IsNullOrEmpty(finalConnStr))
            {
                var optionsBuilder = new DbContextOptionsBuilder<DefaultDbContext>();
                optionsBuilder.UseSqlServer(finalConnStr);
                return new DefaultDbContext(optionsBuilder.Options);
            }
            else
            {
                throw new ArgumentNullException("ConnectionString");
            }
        }
}


Implement a Hello world


Okay, we have logger and ORM now. It’s time to implement a simple web page!

View

l   index.cshtml

@model  IEnumerable<JB.Sample.AspNetCore.DAL.Store>
<table class="list">
    <thead>
        <tr>
            <th>@Html.DisplayNameFor(model => Model.First().Id)</th>
            <th>@Html.DisplayNameFor(model => Model.First().Name)</th>
            <th>@Html.DisplayNameFor(model => Model.First().Description)</th>
        </tr>
    </thead>

    <tbody>
        @if (Model != null)
        {
            foreach (var item in Model)
            {
                <tr>
                    <td>@Html.DisplayFor(model => item.Id)</td>
                    <td>@Html.DisplayFor(model => item.Name)</td>
                    <td>@Html.DisplayFor(model => item.Description)</td>
                </tr>
            }
        }
    </tbody>
</table>


Controller (& DAL service)

l   StoreController.cs

public IActionResult Index()
{
    using (var storeService = new StoreService(DbContextFactory.Create()))
    {
        var stores = storeService.GetAll();
        return View(stores);
    }
}


l   StoreService.cs

public class StoreService : IDisposable
{
        private DefaultDbContext _dbContext = null;
        public StoreService(DefaultDbContext dbContext)
        {
            if(dbContext!=null)
            {
                this._dbContext = dbContext;
            }
        }

        public IEnumerable<Store> GetAll()
        {
            return this._dbContext.Stores;
        }
}


Result

 

And create page~

 




Tag Helpers


There is another new feature of ASP.NET Core MVC 6 – Tag Helpers.
Tag Helpers ain’t created to replace Html Helpers, but enhance them.

For more details, take a look at



Reference


沒有留言:

張貼留言