难度:简单
类型:step-by-step
适用:初学者
SDK:.NET Core SDK 1.1.1
编辑器:Visual Studio Code 1.1.1
关键词:.net core, mvc, solution, xunit
笔者环境:macOS
一. 环境准备:
1.1 sdk下载安装:
下载地址:https://www.microsoft.com/net/core
根据系统选择下载并安装。
运行命令查看安装是否成功:
>> dotnet --version
1.1.1
成功显示版本号,证明安装成功。
1.2 VSCode下载安装:
下载地址:https://code.visualstudio.com/
安装必要扩展:C#、C# Extensions、Asp.NET Helper
二. 工程搭建
2.1 新建解决方案
- 新建并打开文件夹
-
使用快捷键
Ctrl + '
唤出命令行:
在命令行输入命令,创建solution:
>> dotnet new sln
Content generation time: 242.8175 ms
The template "Solution File" created successfully.
2.2 创建web项目
- 命令行创建项目文件夹并进入:
>> mkdir web && cd web
- 创建mvc项目:
>> dotnet new mvc
The template "ASP.NET Core Web App" created successfully.
- 退到根目录并添加sln引用:
>> cd .. && dotnet sln add web/web.csproj
Project `web/web.csproj` added to the solution.
- 选择环境:按F5选择.net core环境
- 编辑启动项:
- 打开
.vscode/launch.json
文件 - 找到
"name": ".NET Core Launch (web)",
节点 - 编辑
program
字段
"program": "${workspaceRoot}/bin/Debug//",
改为:
"program": "${workspaceRoot}/bin/Debug/netcoreapp1.1/web.dll",
- 编辑cwd字段:
"cwd": "${workspaceRoot}",
改为:
"cwd": "${workspaceRoot}/web/",
- 编辑启动任务:
- 打开
.vscode/task.json
文件 - 编辑
tasks
下args
字段:
"args": [""]
改为:
"args": ["${workspaceRoot}/web/web.csproj"]
- 测试运行:
- 按
F5
运行项目,可以看到控制台打印出如下信息:
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.
web -> ~/dotnetcore_mvc_example/web/bin/Debug/netcoreapp1.1/web.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:03.30
- 浏览器会弹出http://localhost:5000/ 或者手动打开
- 修改启动端口:
.netcore mvc默认启动端口是5000,需要其他端口可以自行修改。
- 打开
Program.cs
文件 - 在
WebHostBuilder
中增加UserUrls
配置,例如改为8088:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup()
.UseUrls("http://localhost:8088")
.Build();
host.Run();
}
- 至此mvc项目初始化完毕。
2.3 创建data-service-model等项目
- 在项目根目录一次创建目录
>> mkdir datas && mkdir services && mkdir models
- 初始化类库项目:
>> cd datas && dotnet new classlib
The template "Class library" created successfully.
>> cd ../services && dotnet new classlib
The template "Class library" created successfully.
>> cd ../models && dotnet new classlib
The template "Class library" created successfully.
- 修改.netstandard版本号:
目前创建项目,默认类库使用netstandard1.4,需要修改为最新的1.6
- 打开
xxx.csproj
:
netstandard1.4
改为:
netstandard1.6
- 把项目添加到sln:
命令与web项目一样,添加到sln中:
>> dotnet sln add datas/datas.csproj
Project `datas/datas.csproj` added to the solution.
>> dotnet sln add services/services.csproj
Project `services/services.csproj` added to the solution.
>> dotnet sln add models/models.csproj
Project `models/models.csproj` added to the solution.
- 添加项目之间的引用:
-
web
引用services
和models
dotnet add web/web.csproj reference models/models.csproj
Reference..\models\models.csproj
added to the project.
dotnet add web/web.csproj reference services/services.csproj
Reference..\services\services.csproj
added to the project.
```
查看web.csproj
,可以看到引用添加如下:
- 添加
services
引用datas
和models
三. 完整示例
3.1 使用dapper
- datas项目添加dapper的引用:
>> dotnet add datas/datascsproj package dapper
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.
...
info : PackageReference for package 'dapper' version '1.50.2' added to file '~/dotnetc
ore_mvc_example/datas/datas.csproj'.
.net core 会自动下载引用nuget中的项目
- 配置数据库连接字符串
- 打开
web/appsettings.json
添加ConnectionStrings
字段,假定数据库为读写分离:
- 打开
"ConnectionStrings": {
"read": "your read database connection string",
"write": "your write database connection string"
}
- 编写Repository.cs
-
datas
项目添加Microsoft.Extensions.Configuration
的依赖
-
- 假定数据库中含有表`Greeting`,表字段为`Id`和`Greetings`,创建Greeting的ORM对象:
public class Greeting
{
public int Id { get; set; }
public string Greetings { get; set; }
}
- 读取配置中的数据库连接字符串,并且使用Dapper查询:
public class Repository
{
//注入IConfigurationRoot
public Repository(IConfigurationRoot configuration)
{
_configuration = configuration;
}
private IConfigurationRoot _configuration { get; }
private string _readConnStr => _configuration.GetConnectionString("read");
private string _writeConnStr => _configuration.GetConnectionString("write");
//通过id查询第一条记录并返回entity
public virtual Greeting GetGreeting(int id)
{
string sql = "SELECT Id,Greetings FROM Greeting WHERE Id=@id";
using (var conn = new SqlConnection(_readConnStr))
{
return conn.QueryFirst(sql, new { id });
}
}
}
3.2 编写model和service
- 在
models
项目中创建GreetingModel.cs
:
namespace models
{
public class GreetingModel
{
public string Greetings { get; set; }
}
}
- 在
services
项目中创建GreetingService.cs
:
namespace services
{
public class GreetingService
{
private Repository _repository;
//注入repository
public GreetingService(Repository repository)
{
_repository = repository;
}
public virtual GreetingModel GetGreetings(string name = "")
{
var data = _repository.GetGreeting(1);
return new GreetingModel()
{
Greetings = $"{data.Greetings} {name}!"
};
}
}
}
3.3 创建controller
- 在
web
项中创建Controllers/GreetingController.cs
:
namespace web.Controllers
{
public class GreetingController : Controller
{
private GreetingService _service;
//注入service
public GreetingController(GreetingService service)
{
_service = service;
}
//通过service获取model
public JsonResult Index(string name = "")
{
var model = _service.GetGreetings(name);
return Json(model);
}
}
}
3.4 添加依赖注入
- 打开
web
项目的Startup.cs
- 在
ConfigureServices.cs
添加依赖注入:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
//添加IConfigurationRoot的单例的依赖注入
services.AddSingleton(provider => Configuration);
//添加Repository的依赖注入
services.AddTransient();
//添加GreetingService的依赖注入
services.AddScoped();
}
3.5 运行
- 直接
F5
运行项目,如果遇到问题可以使用命令restore
后在运行
>> dotnet restore && dotnet build
- 启动后,可以打开地址:http://localhost:8088/greeting/?name=world 进行查看。运行正确会显示如下json:
{"greetings":"Hello world!"}
四. 单元测试
4.1 创建测试项目
- 创建目录
tests
并进入 - 初始化xunit单元测试项目
>> dotnet new xunit
Content generation time: 275.91 ms
The template "xUnit Test Project" created successfully.
- 添加工程内项目依赖,和
Moq
依赖
4.2 编写测试类和方法
- 创建
GreetingServiceUnitTest.cs
测试类
public class GreetingServiceUnitTest
{
[Fact]
public void TestGreetingService()
{
//moq相关依赖,并且执行service方法得到结果
var config = new Mock();
var repository = new Mock(config.Object);
repository.Setup(p=>p.GetGreeting(1)).Returns(MoqGreetingData());
var service = new GreetingService(repository.Object);
var result = service.GetGreetings("world");
Assert.NotNull(result);
Assert.Equal(result.Greetings, "hello world!");
}
private Greeting MoqGreetingData()
{
return new Greeting() { Greetings = $"hello" };
}
}
4.3 执行测试
执行dotnet test
命令:
>> dotnet test
Build started, please wait...
Build completed.
Test run for ~/dotnetcore_mvc_example/example_tests/bin/Debug/netcoreapp1.1/example_te
sts.dll(.NETCoreApp,Version=v1.1)
Microsoft (R) Test Execution Command Line Tool Version 15.0.0.0
Copyright (c) Microsoft Corporation. All rights reserved.
Starting test execution, please wait...
...
Total tests: 1. Passed: 1. Failed: 0. Skipped: 0.
Test Run Successful.
Test execution time: 2.7017 Seconds
五. 发布和部署
5.1 发布
-
cd
到web
项目目录 - 执行发布命令:
>> dotnet publish
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.
models -> ~/dotnetcore_mvc_example/models/bin/Debug/netstandard1.6/models.dll
datas -> ~/dotnetcore_mvc_example/datas/bin/Debug/netstandard1.6/datas.dll
services -> ~/dotnetcore_mvc_example/services/bin/Debug/netstandard1.6/services.dll
web -> ~/dotnetcore_mvc_example/web/bin/Debug/netcoreapp1.1/web.dll
-
发布成功后,会生成目录
~/web/bin/Debug/netcoreapp1.1/publish/
5.2 部署
- 准备好生产环境,如安装好.net core sdk的Linux机器
- 上传
~/publish/
目录所有文件到服务器 - 服务器上执行运行命令:
>> dotnet web.dll
Hosting environment: Production
Content root path: ~/wwwroot/dotnet_mvc_example/
Now listening on: http://localhost:8088
Application started. Press Ctrl+C to shut down.
- 访问测试页面,http://localhost:8088/greeting/?name=world
>> curl http://localhost:8088/greeting/?name=world
{"greetings":"Hello world!"}
- 配置Nginx的nginx.conf文件,增加内容:
server {
listen 80;
server_name xxx.xxx.com;#你的域名
location / {
root html;
index index.html index.htm;
proxy_pass http://127.0.0.1:8088;#.net core项目本地地址
#转发ip地址http头
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
重启Nginx,访问域名即可生效
六. 注意事项
- 添加项目后,需要添加到sln,否则项目无法正常使用
- 添加引用后,需要
dotnet restore
否则编码时无自动提示
七. 示例源码:
https://github.com/mcjiffy/dotnetcore_mvc_example