注意: 由于vs code对razor的自能提示不是很友好,所以直接换回vs studio进行开发
- c# :提供语法高亮
- c# Extensions :方便创建和管理文件
- NuGet Package Manager :包管理工具
- Razor Snippets: Razor智能提示
vs cod 使用的 .net core 编译器和调试器分别是 omnisharp 和 debugger,这两个会在 .net core 项目启动的时候进行下载
另外还需要用到两个配置文件launch.json和tasks.json,这两个也可以由vs code自动添加(vs code右下角会有提示添加)
- ctrl+` :打开终端
- ctrl+p :打开顶部命令行
安装 .net core sdk
vs code 中打开一个文件夹,打开终端(ctrl+`)
>dotnet new sln
会在文件夹中创建一个同名的sln文件
>dotnet new mvc -o Host/FHCore.MVC
>dotnet new xunit -o Tests/FHCore.Test
直接会在打开的文件夹中创建一个名为FHCore.MVC 的 .net core mvc 项目
>dotnet sln add Host/FHCore.MVC/FHCore.MVC.csproj
>dotnet sln add Tests/FHCore.Test/FHCore.Test.csproj
>dotnet add Tests/FHCore.Test/FHCore.Test.csproj reference Host/FHCore.MVC/FHCore.MVC.csproj
launch.json在点击调试时会提示创建
tasks.json可以通过命令行创建
打开命令行(ctrl+p)
>Tasks:Configure Tasks
-使用模板创建tasks.json文件
-.net core
然后修改launch.json文件
"program": "${workspaceFolder}/Host/FHCore.MVC/bin/Debug/netcoreapp2.0/FHCore.MVC.dll",
"cwd": "${workspaceFolder}/Host/FHCore.MVC",
"sourceFileMap": {
"/Views": "${workspaceFolder}/Host/FHCore.MVC//Views"
}
- 打开命令行(ctrl+p)
- 输入>nuget,选择安装包
- 输入包名(会模糊查询)按回车
- 选择要安装的包
- 选择版本号
Program文件中修改
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
//指定使用Kestrel服务器
//.UseKestrel()
//.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
//指定端口号
.UseUrls("http://*:6606")
.Build();
这个配置bundleconfig.json文件就行了
通过nuget安装用于 .net core mvc 的autofac扩展库Autofac.Extensions.DependencyInjection
public IContainer ApplicationContainer { get; private set; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
var builder = new ContainerBuilder();
builder.Populate(services);
//让HomeController能通过属性进行注入
builder.RegisterType<HomeController>().PropertiesAutowired();
//builder.RegisterModule(new LoggingModule());
//builder.RegisterType<MyType>().As<IMyType>();
this.ApplicationContainer = builder.Build();
// Create the IServiceProvider based on the container.
return new AutofacServiceProvider(this.ApplicationContainer);
}
在Program文件中配置log4net
static Program()
{
ILoggerRepository repository=LogManager.CreateRepository("console");
FileInfo config=new FileInfo("log4net.config");
log4net.Config.XmlConfigurator.ConfigureAndWatch(repository,config);
}
新建LoggingModule类
public class LoggingModule: Autofac.Module
{
private static void InjectLoggerProperties(object instance)
{
var instanceType = instance.GetType();
// Get all the injectable properties to set.
// If you wanted to ensure the properties were only UNSET properties,
// here's where you'd do it.
var properties = instanceType
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(ILog) && p.CanWrite && p.GetIndexParameters().Length == 0);
// Set the properties located.
foreach (var propToSet in properties)
{
propToSet.SetValue(instance, LogManager.GetLogger("console",instanceType), null);
}
}
private static void OnComponentPreparing(object sender, PreparingEventArgs e)
{
e.Parameters = e.Parameters.Union(
new[]
{
new ResolvedParameter(
(p, i) => p.ParameterType == typeof(ILog),
(p, i) => LogManager.GetLogger("console",p.Member.DeclaringType)
),
});
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
// Handle constructor parameters.
// 处理构造器参数
registration.Preparing += OnComponentPreparing;
// Handle properties.
//处理属性
registration.Activated += (sender, e) => InjectLoggerProperties(e.Instance);
}
}
进行依赖注入
builder.RegisterModule(new LoggingModule());
在tasks.json中添加单元测试任务
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet build",
"type": "shell",
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "test",
"command":"dotnet test ${workspaceFolder}/Tests/FHCore.Test/FHCore.Test.csproj",
"type":"shell",
"group": "test",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}
任务->运行任务->选择test
.net单元测试常用的mock框架,用来模拟一些外部对象,有时候我们要测试的一些方法中需要用到一些外部对象,就可以用mock框架来模拟这些外部对象
[Fact]
public void TestIndexAction()
{
var mockRepo = new Mock<ILog>();
HomeController Controller=new HomeController(mockRepo.Object);
IActionResult result= Controller.Index();
Assert.True(true);
}
使用coverlet查看测试覆盖率
通过nuget安装coverlet.msbuild
在json配置文件的dotnet test命令中添加/p:CollectCoverage=true
{
"label": "test",
"command":"dotnet test ${workspaceFolder}/Tests/FHCore.Test/FHCore.Test.csproj /p:CollectCoverage=true",
"type":"shell",
"group": "test",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
在运行测试之后会在测试结果后面添加上测试覆盖率信息
在tasks.json中添加发布任务
{
"label": "publish",
"command":"dotnet publish",
"type": "shell",
"group":"build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
如果需要发布到指定平台(如linux),可以在dotnet publish命令后添加参数来进行发布。
任务->运行任务->选择publish
dotnet publish -c Release -o ./publish ${workspaceFolder}/Host/FHCore.MVC/FHCore.MVC.csproj
发布后目录下会有publish文件夹,把文件夹拷贝到linux上
# microsoft/dotnet:2.1-aspnetcore-runtime镜像上搭建镜像
FROM microsoft/dotnet:2.1-aspnetcore-runtime
# 工作路径
WORKDIR /app
# 复制到工作路径
COPY ./publish /app
# 监听端口
EXPOSE 6606/tcp
# 由于文件都在工作路径上,所以可以直接dotnet FHCore.MVC.dll
# 如果dll不在工作路径上,需要加上路径,否则会误认为指令是SDK指令,提示安装SDK
ENTRYPOINT dotnet FHCore.MVC.dll
把Dockerfile拷贝到linux上的publish同级目录上。
docker build -t myapp/fhcore:1.0 .
最后的.是指Dockerfile在当前目录下,也可以指定Dockerfile
docker run --name fhcore -p 6606:6606 --restart always -d myapp/fhcore:1.0
端口号随意,映射的端口号(也就是docker内端口号)需要和WebHost定义的端口号一致。
dotnet core中静态文件默认是在wwwroot目录下,其他目录下的文件是无法通过http访问的,如果有其他的静态文件夹需要通过http访问,可以自定义静态文件
app.UseStaticFiles(new StaticFileOptions()
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), @"images")),
RequestPath = new PathString("/images")
});
上面配置的静态文件夹是在项目目录下的images文件夹,通过[http://host/images/*]可以访问images目录下文件
docker run --name fhcore -p 6606:6606 -v /home/dockerpublish/fhcore/images:/app/images --restart always -d myapp/fhcore:1.0
把主机/home/dockerpublish/fhcore/images目录映射到容器/app/images路径中,容器的工作路径是在/app,所以/app/images就是容器中项目的images路径了。 项目在访问images目录的时候,直接访问的是主机/home/dockerpublish/fhcore/images目录
Docker支持直接用Dockerfile进行项目的部署,支持版本是1.7以上
修改Dockerfile内容如下
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 6606/tcp
FROM microsoft/dotnet:2.1-sdk AS build
WORKDIR /src
COPY Host/FHCore.MVC/FHCore.MVC.csproj Host/FHCore.MVC/
RUN dotnet restore Host/FHCore.MVC/FHCore.MVC.csproj
COPY . .
RUN dotnet build Host/FHCore.MVC/FHCore.MVC.csproj -c Release -o /app
FROM build AS publish
COPY Host/FHCore.MVC/layui /app/layui
RUN dotnet publish Host/FHCore.MVC/FHCore.MVC.csproj -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT dotnet FHCore.MVC.dll
个人理解: publish和final的虚拟空间是隔离开的,而base和final在同一个虚拟空间内,build和publish也在同一个虚拟空间内。所以最后的COPY --from=publish /app .
是指把publish的文件系统的/app目录下的文件复制到当前文件系统的工作路径下(WORKDIR /app
当前工作路径是/app目录)。
Dockerfile文件路径是在解决方案同目录下 这样方便自动化部署
docker run -d --privileged -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/portainer:/data portainer/portainer
安装node
windows下直接下载安装包安装
安装bower
$ npm install -g bower
初始化bower
$ bower init
会在当前项目根目录下多出一个bower.json的文件
添加bower配置文件
在当前项目的根目录中创建一个.bowerrc文件,在window下创建的话需要把文件名命名为".bowerrc."
配置信息如下
{
"directory" : "Host/FHCore.MVC/wwwroot/lib",
"json" : "",
"endpoint" : "",
"searchpath" : "",
"shorthand_resolver" : ""
}
directory是包管理时的安装路径
安装requirejs
$ bower install requirejs --save
内存字典对象、json文件、init文件、xml文件
配置
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
var dict = new Dictionary<string, string>
{
{"test", "DEV_1111111-1111"},
{"test1", "PROD_2222222-2222"}
};
config.AddInMemoryCollection(dict);
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddIniFile("config.ini", optional: true, reloadOnChange: true);
config.AddJsonFile("config.json", optional: true, reloadOnChange: true);
config.AddXmlFile("config.xml", optional: true, reloadOnChange: true);
})
.UseStartup<Startup>();
}
使用
public IConfiguration configuration;
public HomeController(IConfiguration configuration)
{
this.configuration=configuration;
}
public IActionResult Index()
{
string message= configuration.GetValue<string>("test");
//ViewData["Message"] = "Your application description page.";
ViewData["Message"] = message;
return View();
}
IOptions、IOptionsSnapshot