vue前端开发那些事——后端接口.net core web api
红花还得绿叶陪衬。vue前端开发离不开数据,这数据正来源于请求web api。为什么采用.net core web api呢?因为考虑到跨平台部署的问题。即使眼下部署到window平台,那以后也可以部署到Linux下。
.net core web api与mvc的web api类似。我把遇到的问题归纳下:
1、部署问题
都说.net core web api,后面我简称api。它有两种部署方式,一个是在iis上部署,另外一个是自托管,类似控制台,通过dotnet run 命令启动的。
1.1 自托管部署
dotnet myapp.dll
网上说,通过hosting.json
{
"server.urls": "http://localhost:60000;http://localhost:60001"
}
这种方式有个问题,在配置了urls,并没有走配置。
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("hosting.json", optional: true)
.Build(); var host = new WebHostBuilder()
.UseKestrel()
.UseConfiguration(config)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build(); host.Run();
}
不过人家是说在Linux环境下的部署,我在window下测试是不行的,不知道是哪的问题,后面可以再研究。
1.2、iis上部署
必须首先安装AspNetCoreModule,搜索这个模块,它的描述如下:
The ASP.NET Core Module allows ASP.NET Core apps to run in an IIS worker process (in-process) or behind IIS in a reverse proxy configuration (out-of-process). IIS provides advanced web app security and manageability features.
这句话大意:api有两种运行模式,一种是运行在iis工作进程中(In-process hosting model),另外一种是通过反向代理配置,运行在外(Out-of-process hosting model)。具体,可参考官方文档。

这是文档中 In-process hosting model图,我们可以看出,http请求首先到达kernel-mode HTTP.sys driver,http监听器,监听器把请求给iis,首先是Asp.NET Core Module接受,然后传递给IISHttpServer,它把请求转换为托管代码,进入.net core middelware pipline,最后才是我们的api代码。换句话说,Asp.NET Core Module类似中间件的作用,它先处理的一部分事情。这是我们项目中采取的部署方案,另外一种模式可能比较复杂,大家阅读官方文档。
2、全局异常处理
我们知道mvc中,有两种异常处理:
使用Global.asax的Application_Error事件进行全局异常处理以及使用HandleErrorAttribute特性捕获全局异常
.net core api中可以编写异常处理的中间件,如下:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Xml.Serialization; namespace ElectronInfoApi.Business {
public class GlobalExceptionMiddleware {
private readonly RequestDelegate next;
public GlobalExceptionMiddleware(RequestDelegate next) {
this.next = next;
} public async Task Invoke(HttpContext context) {
try {
await next(context);
}
catch (Exception ex) {
await HandleExceptionAsync(context, ex);
}
} private async Task HandleExceptionAsync(HttpContext context, Exception exception) {
if (exception == null)return;
await WriteExceptionAsync(context, exception).ConfigureAwait(false);
} private async Task WriteExceptionAsync(HttpContext context, Exception exception) {
//记录日志
this.Log().Error($"系统发生了异常:{exception.Message}, {exception.StackTrace}");
//返回友好的提示
var response = context.Response; //状态码
if (exception is UnauthorizedAccessException)
response.StatusCode = (int)HttpStatusCode.Unauthorized;
else if (exception is Exception)
response.StatusCode = (int)HttpStatusCode.BadRequest; response.ContentType = context.Request.Headers["Accept"]; response.ContentType = "application/json";
await response.WriteAsync(JsonConvert.SerializeObject(new {state=,message="出现未知异常"})).ConfigureAwait(false);
} } public static class VisitLogMiddlewareExtensions
{
public static IApplicationBuilder UseGlobalException(this IApplicationBuilder builder)
{
return builder.UseMiddleware<GlobalExceptionMiddleware>();
}
}
}
在startup>Configure中添加
app.UseGlobalException();
官网有文档,是这么定义中间件的:
Middleware is software that's assembled into an app pipeline to handle requests and responses
3、安全验证
接口验证,是为了安全性考虑,采用Jwt(Json web token)。
第一步,添加包引用:
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.2" />
第二步,配置:
"Issuer": "ElectronInfo",
"Audience": "ElectronInfo",
"SecretKey": "ElectronInfo is a web of shanxi dianzi qingbao weiyuanhui"
第三步,在Startup>ConfigureServices中添加授权服务:
var jwtSettings = new JwtSettings(){
Issuer=AppSetting.GetConfig("Issuer"),
Audience=AppSetting.GetConfig("Audience"),
SecretKey=AppSetting.GetConfig("SecretKey"),
};
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o => {
o.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters {
ValidIssuer = jwtSettings.Issuer,
ValidAudience = jwtSettings.Audience,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)),
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
第四步:在Startup>Configure中添加
app.UseAuthentication();
第五步:给整个Controller或者需要接口验证的action中添加
[Authorize]
附:AppSetting类,读取appsettings.json,如下:
using System.IO;
using Microsoft.Extensions.Configuration; namespace ElectronInfoApi.Business {
public class AppSetting {
private static readonly object objLock = new object();
private static AppSetting instance = null; private IConfigurationRoot Config {get; } private AppSetting() {
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional:false, reloadOnChange:true);
Config = builder.Build();
} public static AppSetting GetInstance() {
if (instance == null) {
lock (objLock) {
if (instance == null) {
instance = new AppSetting();
}
}
} return instance;
} public static string GetConfig(string name) {
return GetInstance().Config.GetSection(name).Value;
}
}}
4、日志log4
.net core中本来就支持console输出日志。不过今天我要说的是log4,在传统的.net中普遍使用。
第一步,添加包引用:
<PackageReference Include="log4net" Version="2.0.8" />
第二步,添加配置文件log4net.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- This section contains the log4net configuration settings -->
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
</appender> <!--<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="log-file.log" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender> --> <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="logfile/" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<staticLogFileName value="false" />
<datePattern value="yyyyMMdd'.log'" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="1MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender> <!-- Setup the root category, add the appenders and set the default level -->
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
<!--<appender-ref ref="FileAppender" />-->
<appender-ref ref="RollingLogFileAppender" />
</root> </log4net>
</configuration>
第三步,包装以及扩展log4,为了更方便使用:
首先定义一个接口IMLog:
using System;
namespace ElectronInfoApi.Business {
public interface IMLog {
// Methods
void Debug(string message);
void Error(string message, Exception exception);
void Error(string message);
void Fatal(string message);
void Info(string message);
void Warn(string message);
}
public interface IMLog < T > {
}
再定义包装器Log4NetWapper:
using System;
using log4net;
using log4net.Core; namespace ElectronInfoApi.Business {
public class Log4NetWapper:IMLog, IMLog < Log4NetWapper > { private ILog _logger; public Log4NetWapper(string loggerName) {
this._logger = LogManager.GetLogger(Startup.repository.Name, loggerName);
} public void Debug(string message) {
_logger.Debug(message);
} public void Error(string message, Exception exception) {
_logger.Error(message, exception);
} public void Error(string message) {
_logger.Error(message);
} public void Fatal(string message) {
_logger.Fatal(message);
} public void Info(string message) {
_logger.Info(message);
} public void Warn(string message) {
_logger.Warn(message);
}
} }
最后定义扩展方法 LogExtensions:
using System.Collections.Concurrent;
namespace ElectronInfoApi.Business {
public static class LogExtensions {
// Fields
private static readonly ConcurrentDictionary < string, IMLog > _dictionary = new ConcurrentDictionary < string, IMLog > ();
// Methods
public static IMLog Log(this string objectName) {
if ( ! _dictionary.ContainsKey(objectName)) {
IMLog log = new Log4NetWapper(objectName);
_dictionary.TryAdd(objectName, log);
}
return _dictionary[objectName];
}
public static IMLog Log < T > (this T type) {
return typeof(T).FullName.Log();
}
}}
第四步,在Startup中使用:
public static ILoggerRepository repository {get; set; }
public Startup(IConfiguration configuration) {
repository = LogManager.CreateRepository("NETCoreRepository");
XmlConfigurator.Configure(repository, new FileInfo("log4net.config"));
Configuration = configuration;
}
public IConfiguration Configuration {get; }
5、.对net core中startup理解,见官方文档
好了,关于.net core api也是第一次正式使用,就总结到这里。
vue前端开发那些事——后端接口.net core web api的更多相关文章
- vue前端开发那些事——vue组件开发
vue的学习曲线不是很陡(相比其它框架,如anglarjs),官方文档比较全面,分为基础篇和高级篇.我们刚开始学习的时候,肯定像引用jquery那样,先把vue的js引进来,然后学习基础内容.如果仅仅 ...
- vue前端开发那些事——vue开发遇到的问题
vue web开发并不是孤立的.它需要众多插件的配合以及其它js框架的支持.本篇想把vue web开发的一些问题,拿出来讨论下. 1.web界面采用哪个UI框架?项目中引用了layui框架.引入框架 ...
- vue前端开发那些事——前言
如上图所示,用vue开发一个小型网站所涉及到的知识点.这只是前端部分已经这么多了.接下来我分解开来说. 1.Node 当我们开发vue项目的时候,首先要安装Node.js,那么我们即使当时不理解为什么 ...
- vue前端开发那些事(1)
如上图所示,用vue开发一个小型网站所涉及到的知识点.这只是前端部分已经这么多了.接下来我分解开来说. 1.Node 当我们开发vue项目的时候,首先要安装Node.js,那么我们即使当时不理解为什么 ...
- List多个字段标识过滤 IIS发布.net core mvc web站点 ASP.NET Core 实战:构建带有版本控制的 API 接口 ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目 Using AutoFac
List多个字段标识过滤 class Program{ public static void Main(string[] args) { List<T> list = new List& ...
- ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目
一.前言 这几年前端的发展速度就像坐上了火箭,各种的框架一个接一个的出现,需要学习的东西越来越多,分工也越来越细,作为一个 .NET Web 程序猿,多了解了解行业的发展,让自己扩展出新的技能树,对自 ...
- C#开发微信门户及应用(47) - 整合Web API、微信后台管理及前端微信小程序的应用方案
在微信开发中,我一直强调需要建立一个比较统一的Web API接口体系,以便实现数据的集中化,这样我们在常规的Web业务系统,Winform业务系统.微信应用.微信小程序.APP等方面,都可以直接调用基 ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session
原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NE ...
随机推荐
- 手机调取摄像头问题(getUserMedia)
先说坏消息,苹果机没法玩这个!!! 而且,必须拥有 https 的安全协议!!! 而安卓机想完成这个功能倒是很 easy 的,看一眼代码 主要传入三个参数,配置对象,成功,失败 var mediaOp ...
- zero-base coordinate 和one-base coordinate
zero-base和one-base是生信会经常碰到的两套坐标系统. zero-base是半开放式的,是不包括该点的,zero-base的文件有:bed;bam one-base是封闭式的,是包括该点 ...
- javascript onclick 函数不执行
今天被这个问题搞伤了. 原本是要给table中的元素添加onclick事件处理函数,刚开始还可以,后来就不行了,百试不得其解,反复检查,程序也没问题,耗了一个多小时,偏偏我就不信电脑会扯拐,就要看看还 ...
- Flume-NG源码阅读之AvroSink
org.apache.flume.sink.AvroSink是用来通过网络来传输数据的,可以将event发送到RPC服务器(比如AvroSource),使用AvroSink和AvroSource可以组 ...
- Treflection02_getMethods()_getMethod()
1. package reflectionZ; import java.lang.reflect.Constructor; import java.lang.reflect.Method; impor ...
- crm开发(基于ssh)(五)
1 信息查询 (1)多条件组合查询 -拼接hql语句 -使用离线对象 2 添加数据字典表 (1)改造添加客户功能 3 统计分析 (1)调用普通sql实现 (2)结果处理操作 4 使用ssh注解整合 ( ...
- 智课雅思词汇---二十四、名词性后缀ary(也是形容词后缀)
智课雅思词汇---二十四.名词性后缀ary(也是形容词后缀) 一.总结 一句话总结:很多词缀即是名词词缀也是形容词词缀,很多词即是名词也是形容词 1.名词性后缀-tude? 词根词缀:-tude [来 ...
- python学习笔记(xlwt/xlrd下载安装)
python支持处理Excel 可以使用xlwt xlrd 模块 分别在https://pypi.python.org/pypi/xlwt 和 https://pypi.python.org/pyp ...
- Django进阶Model篇006 - 多表关联查询
接着前面的例子,举例多表查询实例如下: 1.查询作战的所有完整信息. >>> AuthorDetail.objects.values('sex','email','address', ...
- Mybatis输入和输出映射(parameterType和resultType的区别)
parameterType resultType ...