今天微軟正式發布了ASP.NET 5 RC1(詳見Announcing ASP.NET 5 Release Candidate 1),.NET跨平臺邁出了關鍵一步。
緊跟這次RC1的發布,我們成功地將運行在Linux上的示例站點(http://about.cnblogs.com)升級到了ASP.NET 5 RC1,并且增加了數據庫訪問功能——基于Entity Framework 7 RC1訪問SQL Server數據庫。
示例站點頁面左側的導航是從數據庫讀取數據動態加載的,數據庫服務器用的是阿里云RDS(注:創建數據庫時需要將支持的字符集設置為SQL_Latin1_General_CP1_CS_AS,這是針對SqlClient中一個bug的臨時解決方法)。數據庫表是通過EF遷移功能生成的,所用命令如下:
dnx ef migrations add FirstMigration dnx ef database update
數據庫連接字符串是從config.json中讀取的。
后端Web服務器用的是kestrel,前端Web服務器用的是阿里云負載均衡,使用中發現一個很奇怪的問題:瀏覽器直接訪問kestrel,速度飛快;而訪問阿里云負載均衡,頁面雖然顯示出來,但頁面一直牌加載狀態,長達1分鐘。
懷疑是阿里云負載均衡與kestrel在TCP通信上存在某些問題,這個問題暫時沒有找到解決方法(更新:這是kestrel的一個bug,詳見 Don't wait to consume the entire request body for Connection: close requests )。
SQL Server數據庫終于能跨平臺訪問了,接下來就看kestrel的穩定性了。如果kestrel穩定,我們就開始將一些實際使用的小站點遷移至ASP.NET 5,并部署在Linux服務器上。
下面分享一下這個示例ASP.NET 5站點的主要代碼。
文件結構:
. ├── config.json ├── Controllers │ ├── AboutController.cs │ └── HomeController.cs ├── Data │ ├── EfDbContext.cs │ ├── ITabNavRepository.cs │ └── TabNavRepository.cs ├── Extensions │ └── HtmlHelperExtensions.cs ├── Models │ └── TabNav.cs ├── project.json ├── project.lock.json ├── Startup.cs ├── Views │ ├── About │ │ ├── Ad.cshtml │ │ ├── Contact.cshtml │ │ ├── Intro.cshtml │ │ └── Job.cshtml │ ├── Shared │ │ └── _Layout.cshtml │ └── _ViewStart.cshtml └── wwwroot
project.json文件的內容:
{ "webroot": "wwwroot", "exclude": ["wwwroot"], "commands":{ "kestrel": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.Kestrel --server.urls http://*:8001", "ef": "EntityFramework.Commands" }, "dependencies":{ "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", "Microsoft.AspNet.Mvc": "6.0.0-*", "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final", "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final", "EntityFramework.Commands": "7.0.0-rc1-final", "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final", "System.Runtime.Serialization.Primitives": "4.0.10-*", "System.Net.Security":"4.0.0-*" }, "frameworks":{ "dnxcore50": {}, } }
Startup.cs中的代碼:
using System; using System.Linq; using Microsoft.AspNet.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Data.Entity; using CNBlogs.AboutUs.Data; using Microsoft.Dnx.Runtime; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.Configuration; using System.Data.SqlClient; using Microsoft.Extensions.Logging; namespace CNBlogs.AboutUs.Web { public class Startup { public Startup(IApplicationEnvironment appEnv) { IConfigurationBuilder builder = new ConfigurationBuilder() .SetBasePath(appEnv.ApplicationBasePath) .AddJsonFile("config.json", false); Configuration = builder.Build(); } public IConfiguration Configuration { get; set; } public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); app.UseDeveloperExceptionPage(); app.UseMvcWithDefaultRoute(); app.UseStaticFiles(); app.UseRuntimeInfoPage(); } public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddEntityFramework() .AddSqlServer() .AddDbContext<EfDbContext>(options => { options.UseSqlServer(Configuration["data:ConnectionString"]); }); services.AddTransient<ITabNavRepository, TabNavRepository>(); } } }
文章列表