一、Web API跨域支持
因為瀏覽器有CROS(跨域資源共享)的問題,所以我們開發的Web API接口需要添加跨域功能。
1. 在Startup.cs的ConfigureServices方法里添加如下代碼:
//支持跨域
services.AddCors(options =>
{
options.AddPolicy("any", builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
//.AllowCredentials(); //指定處理cookie
});
});
any為策略名稱,可以自己起名。
2. 在Startup.cs的Configure方法里添加如下代碼:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseStaticFiles();
app.UseCors("any");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireCors("any");
});
注意,app.UseCors("any"); 必須放入app.UseRouting和app.UseEndpoints方法之間。
3. 在Controller里啟用跨域,添加[EnableCors("any")],如下所示:
[EnableCors("any")]
[Route("api/[controller]")]
[ApiController]
public class RegInfoController : ControllerBase
{
//省略控制器代碼
}
這樣將該Web API發布到IIS,就可以支持跨域訪問該接口服務了。
二、uniapp跨域訪問
這里我主要用到uniapp的兩個方法,uploadFile和request方法。具體的用法可以參考官方文檔:https://uniapp.dcloud.io/api/request/request.html 。
a. uploadFile示例:
uni.chooseImage({
sourceType: sourceType[this.sourceTypeIndex],
sizeType: sizeType[this.sizeTypeIndex],
count4: this.imageList4.length + this.count4[this.countIndex4] > 1 ? 1 - this.imageList4.length : this.count4[this.countIndex4],
success: (res) => {
var size = res.tempFiles[0].size;
console.log(size);
if (size > 2097152) {
uni.showToast({
title: "圖片大小不能超過2M",
icon: 'none',
duration: 1000,
mask: true
});
return
}
if(size < 100000){
uni.showToast({
title: "圖片大小不能少於100K",
icon: 'none',
duration: 1000,
mask: true
});
return
}
this.imageList4 = this.imageList4.concat(res.tempFilePaths);
uni.showLoading({
title: '圖片上傳中'
});
var imageSrc = res.tempFilePaths[0]
uni.uploadFile({
url: 'http://ip:端口/api/RegInfo/UploadImage',
formData: {
'd': 'Images4' //傳參到Web API
},
filePath: imageSrc,
fileType: 'image',
name: 'data',
success: (res) => {
console.log('uploadImage success, res is:', res.data)
this.image4 = res.data
uni.hideLoading();
uni.showToast({
title: '上傳成功',
icon: 'success',
duration: 1000,
mask: true
})
},
fail: (err) => {
console.log('uploadImage fail', err);
uni.showModal({
content: err.errMsg,
showCancel: false
});
}
});
},
fail: (err) => {
console.log("err: ", err);
// #ifdef APP-PLUS
if (err['code'] && err.code !== 0 && this.sourceTypeIndex === 2) {
this.checkPermission(err.code);
}
// #endif
// #ifdef MP
if (err.errMsg.indexOf('cancel') !== '-1') {
return;
}
uni.getSetting({
success: (res) => {
let authStatus = false;
switch (this.sourceTypeIndex) {
case 0:
authStatus = res.authSetting['scope.camera'];
break;
case 1:
authStatus = res.authSetting['scope.album'];
break;
case 2:
authStatus = res.authSetting['scope.album'] && res.authSetting['scope.camera'];
break;
default:
break;
}
if (!authStatus) {
uni.showModal({
title: '授權失敗',
content: 'Hello uni-app需要從您的相機或相冊獲取圖片,請在設置界面打開相關權限',
success: (res) => {
if (res.confirm) {
uni.openSetting()
}
}
})
}
}
})
// #endif
}
})
后台控制器方法接收上傳的圖片代碼片段:
[HttpPost("UploadImage")]
public string UploadImage()
{
var file = Request.Form.Files[0];
byte[] bytes = new byte[file.OpenReadStream().Length];
file.OpenReadStream().Read(bytes, 0, bytes.Length);
MemoryStream ms = new MemoryStream(bytes);
Bitmap bitmap = new Bitmap(ms);
string d = Request.Form["d"]; //類型對應不同的目錄
string path = Directory.GetCurrentDirectory() + "/Images/" + d + "/" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";
bitmap.Save(path);
ms.Close();
bitmap.Dispose();
return path; //返回路徑給uniapp,可保存該路徑到數據庫
}
b. request示例:
uni.request({
url: 'https://xxx.xxx.xxx.xxx:8098/api/RegInfo/AddRegInfo', //僅為示例,並非真實接口地址,前面的xxx為服務器ip或者改成域名。
data: {
text1: 'text1',
text2: 'text2'
},
success: (res) => {
console.log(res.data);
this.text = 'request success';
}
});
這里的參數data,里面可以封裝成一個json對象傳給Web API后台,后台方法參數為對象,該對象的屬性跟text1,text2對應即可,可自由設置這里僅作演示。
后台控制器方法接收代碼片段:
[HttpPost("AddRegInfo")]
public string AddRegInfo(RegInfo regInfo)
{
using (_context as IDisposable)
{
_context.RegInfos.Add(regInfo); //_context為EF數據庫操作對象
int flag = _context.SaveChanges();
return flag>0?"添加成功":"添加失敗";
}
}
RegInfo類里有兩個屬性Text1和Text2,分為對應如上的text1和text2。
三、發布到IIS的一些問題
1. .net core HTTP Error 500.31-Failed to load ASP.NET Core runtime錯誤
在服務器運行cmd,輸入dotnet --version,查看.net core版本號。在發布Web API設置目標框架的時候,選擇匹配這個版本號的.NET Core版本即可。
2. .net core HTTP Error 500.30 -ANCM In-Process Handler Load Failure
a. 找到發布過的Web API里的web.config文件並將 hostingModel="InProcess" 配置結點刪除
b. 在IIS該應用的應用程序池中,打開啟用32位應用程序
c. 快速故障防護是否關閉
參考資料:
1. uniapp官方首頁: https://uniapp.dcloud.io/
2. 微軟官方Web API教程:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-6.0&tabs=visual-studio