使用微信云托管快速部署一个.Net Core项目(一)
作者:多读书
前几天微信将小程序开发者工具内的云托管升级为微信云托管,新增了很多诸如 OpenApi、MySql 数据库、流水线构建、web 控制台等能力。看文档还是蛮激动的,对开发者来说确实是个好消息,因为之前的一些业务逻辑大都写在云函数或者部署在服务器里面,要管理好几套。看了这次发布的微信云托管有点动心要做一个迁移,微信云托管相比其它模式来说还是很有优势和前景的。关于微信云托管和云函数以及服务器、Kubernetes 的对比大家看这个链接就够了:https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/basic/intro.html
这次先拿一个小 demo 练手。话不多说,出于好奇心,今天带大家来体验一把:
第一步:开通环境
首先登陆微信云托管创建环境,微信云托管的地址为:https://cloud.weixin.qq.com/
首先需要创建一个环境,创建环境分为系统创建和私人网络,选择私人网络会罗列出该小程序对应的腾讯云账号之前创建过的环境,在这里我选择了私人网络里面和我目前小程序使用的相同环境。
这次咱们也看看 mysql,微信云托管相比之前增加了 MySql 服务,开通也是非常方便。如下图所示简单几步就可以开通成功了并且支持自动暂停:
开通之后是这样滴,支持内外网访问数据库,并且提供自动暂停服务,闲置的时候就帮你暂停了。
由于项目中需要使用到“云调用”获取小程序码的服务,所以这里安装一下微信云托管提供的OpenApi,这里一定要注意如果要使用“云调用”服务,微信令牌权限设置这里一定是要把要使用的接口先添加到白名单的。
小tips:大家在使用 OpenApi 接口的时候测试开发中可以把公网域名访问打开,线上环境启动内网访问就可以,这样相对比较安全。因为你调用 OpenApi 的接口不再像之前需要换取 Access_Token 啦,公网暴露风险大。
第二步:新建服务
流水线发布
选择流水线发布的话第一步需要新建流水线,选择流水线发布的代码中必须要包含 container.config.json 文件,关于写法根据文档自己定义即可:https://developers.weixin.qq.com/miniprogram/dev/wxcloudrun/src/basic/guide.html
GitHub 授权访问之后并在仓库中包含 container.config.json 文件,然后根据自己实际情况勾选其它配置以后这样一条流水线就定义好了,当代码推送触发 main 分支的时候就会自动构建镜像,构建好之后别忘了最后还要把最新版本部署发布,流水线不会自动帮你去将最新版本发布上去的。
版本发布
版本发布也是很方便的,定义好 Dockerfile 文件之后可以在腾讯云个人仓库构建配置那里配置从 GitHub 拉取或者本地构建好 docker 镜像后推送到腾讯云。我这里选择的是微信云托管代码拉取:
在版本列表里面选择新建版本,从代码库拉取,把我们写好的程序拉取下来:
代码拉取之后会在微信云托管自动帮助我们构建镜像,点击查看日志就可以看到详细的构建过程,又是熟悉的操作。
等版本构建完毕之后,之后就是发布,无论是选择流水线发布还是版本发布,最后一步一定要选择发布上线。
第三步:开发
这里我创建一个.Net Core 项目,选择 WebApp 模版。
接下来编辑 Dockerfile 文件:
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS build
WORKDIR /src
COPY ["HtArtGoWebApp.csproj", "."]
RUN dotnet restore "./HtArtGoWebApp.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "HtArtGoWebApp.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "HtArtGoWebApp.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "HtArtGoWebApp.dll"]
然后安装数据库驱动
<ItemGroup>
<PackageReference Include="FreeSql" Version="2.5.200" />
<PackageReference Include="FreeSql.Provider.MySql" Version="2.5.200" />
</ItemGroup>
注入 FreeSql 以及定义实体,先定义实体,我在项目中新建了 Models 文件夹,实体都放在 Models 文件夹中,首先定义一个基础类 BaseEntity.cs
public class BaseEntity where TKey : IEquatable
{
[Column(IsPrimary = true, IsIdentity = true)]
public TKey Id { get; set; }
[Column(ServerTime = DateTimeKind.Utc, CanUpdate = false)]
public DateTime CreateTime { get; set; }
[Column(ServerTime = DateTimeKind.Utc)]
public DateTime UpdateTime { get; set; }
public string OperatorId { get; set; }
public bool IsDelete { get; set; }
public bool Status { get; set; }
}
之后定义一个用于测试的类 Exhibitions.cs 类,让它继承 BaseEntity,主键可以自定义类型:
public class Exhbitions:BaseEntity
{
public string Title { get; set; }
}
接下来就是 FreeSql 的配置以及注入,在 Stratup.cs 文件里面进行注入:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
//FreeSql配置
fsql = new FreeSql.FreeSqlBuilder()
//链接字符串
.UseConnectionString(FreeSql.DataType.MySql,
Configuration.GetConnectionString("MySql"))
//自动同步实体打开
.UseAutoSyncStructure(true)
//SQL日志也打开
.UseMonitorCommand(cmd => Console.WriteLine(cmd.CommandText))
.Build();
}
public IConfiguration Configuration { get; }
public IFreeSql fsql;
最后在 ConfigureServices 里面进行注入一下,注入方式为单例模式:services.AddSingleton
这样数据库部分就配置注入成功了,然后就是调用数据库查询数据了,选一个 Index.cshtml 页面进行数据查询展示:
public class IndexModel : PageModel
{
private readonly ILogger _logger;
private IFreeSql _freeSql;
//前端要展示的数据定义为属性
public IList ExhbitionListList { get; set; }
public IndexModel(ILogger logger,IFreeSql freeSql)
{
_logger = logger;
_freeSql = freeSql;
}
//页面初始化的时候查询数据
public async Task OnGetAsync()
{
var data = await _freeSql.Select().ToListAsync();
//赋值
ExhbitionListList = data;
}
}
在前端 Index.cshtml 用一个 table 展示:
<table style="margin-left: 30%">
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>创建日期</th>
</tr>
</thead>
<tbody>
@foreach (var item in this.Model.ExhbitionListList)
{
<tr>
<td>@item.Id</td>
<td>@item.Title</td>
<td>@item.CreateTime</td>
</tr>
}
</tbody>
</table>
以上是数据库部分,接下来咱们使用微信云托管的 OpenApi 进行调用,关于 OpenApi 的部分放在 RestService 文件夹里面的 OpenApiService 类中
这个文件夹里面我只写了一个获取小程序码的接口用于测试,代码如下:
public class OpenApiService
{
private HttpClient _client;
public OpenApiService(HttpClient client)
{
client.BaseAddress =new Uri("http://替换成大家自己的");
_client = client;
}
public async Task GetgetUnlimited()
{
var body = new StringContent(JsonSerializer.Serialize(new
{
scene = "index",
page = "pages/index/index"
}), Encoding.UTF8, "application/json");
var response = await _client.PostAsync("/wxa/getwxacodeunlimit", body);
if (response.IsSuccessStatusCode)
{
MemoryStream ms = new MemoryStream();
await response.Content.CopyToAsync(ms);
return ms;
}
return null;
}
}
然后在 ConfigureService 中注入一下:services.AddHttpClient
调用该服务我们写一个 Controller 接口供前端调用,这里要在 Startup.cs 里面配置两处:
配置好之后在控制器里面调用即可:
[ApiController]
[Route("api/[controller]")]
public class WxController : Controller
{
private OpenApiService _openApiService;
public WxController(OpenApiService openApiService)
{
_openApiService = openApiService;
}
[HttpGet]
public async Task GetgetUnlimited()
{
var data = await _openApiService.GetgetUnlimited();
return new FileContentResult(data.ToArray(), "image/jpeg");
}
}
这里别忘了在微信云托管将获取小程序码的接口添加白名单:
好啦,到这里代码部分就结束了。先在本地调试一遍没问题就发布啦:
获取小程序码正常
数据库访问正常
页面看起来有点丑,用 Vue 和 ElementUI 优化一下首页,在_Layout.cshtml中引入Vue 和 ElementUI的 相关库,然后在前端 Index.cshtml.cs 中做如下修改:
public class IndexModel : PageModel
{
private readonly ILogger _logger;
private IFreeSql _freeSql;
public IList ExhbitionListList { get; set; }
public IndexModel(ILogger logger,IFreeSql freeSql)
{
_logger = logger;
_freeSql = freeSql;
}
// public async Task OnGetAsync()
// {
// var data = await _freeSql.Select().ToListAsync();
// ExhbitionListList = data;
// }
public async Task OnGetList()
{
var data = await _freeSql.Select().ToListAsync();
return new JsonResult(data);
}
}
Html 页面中用 element 的 Table 组件优化一下:
<div id="app">
<el-table v-bind:data="list" border style="width: 100%">
<el-table-column fixed prop="id" label="id">
</el-table-column>
<el-table-column prop="title" label="标题">
</el-table-column>
<el-table-column prop="createTime" label="创建时间">
</el-table-column>
<el-table-column
fixed="right"
label="操作"
width="100">
<template slot-scope="scope">
<el-button v-on:click="handleClick(scope.row)" type="text" size="small">查看</el-button>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
@section Scripts
{
<script type="text/javascript">
var app=new Vue({
el:'#app',
data:{
title:'主页',
list:[]
},
async created(){
const list= await this.loadData();
this.list = list
},
methods:{
loadData(){
return new Promise(((resolve, reject) =>
$.ajax({
url:'?handler=List',
success:(res)=>{
resolve(res)
},fail:(err)=>{
reject(err)
}
})
))
},
handleClick(row) {
console.log(row);
}}
})
</script>
}
呈现出来的页面如下所示,以后再把 CURD 相关操作添加上:
然后添加一个 API 管理工具 Swagger ,在这里为了演示添加一个最简易配置的的 Swagger, 添加 Swagger 首先需要在 Nuget 上面安装 Swagger 的包 Swashbuckle.AspNetCore。之后在 ConfigureServices 方法中注入services.AddSwaggerGen();,在 Configure 里面注册 Swagger 中间件:app.UseSwagger();
app.UseSwaggerUI(c=>{c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");});
然后访问 localhost:5000//swagger/index.html 即可
最后发布上线之后也一切正常,感觉未来可期,日志查询也非常方便,这个必须赞:
总结
总结起来微信云托管这个方向很好,很适合快速开发验证业务模型,希望后期尽快支持环境共享、自定义域名等,后续还有第二篇将如何将 CMS 接入项目中来,大家敬请期待~
交流群