红花还得绿叶陪衬。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的更多相关文章

  1. vue前端开发那些事——vue组件开发

    vue的学习曲线不是很陡(相比其它框架,如anglarjs),官方文档比较全面,分为基础篇和高级篇.我们刚开始学习的时候,肯定像引用jquery那样,先把vue的js引进来,然后学习基础内容.如果仅仅 ...

  2. vue前端开发那些事——vue开发遇到的问题

    vue web开发并不是孤立的.它需要众多插件的配合以及其它js框架的支持.本篇想把vue web开发的一些问题,拿出来讨论下.  1.web界面采用哪个UI框架?项目中引用了layui框架.引入框架 ...

  3. vue前端开发那些事——前言

    如上图所示,用vue开发一个小型网站所涉及到的知识点.这只是前端部分已经这么多了.接下来我分解开来说. 1.Node 当我们开发vue项目的时候,首先要安装Node.js,那么我们即使当时不理解为什么 ...

  4. vue前端开发那些事(1)

    如上图所示,用vue开发一个小型网站所涉及到的知识点.这只是前端部分已经这么多了.接下来我分解开来说. 1.Node 当我们开发vue项目的时候,首先要安装Node.js,那么我们即使当时不理解为什么 ...

  5. 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& ...

  6. ASP.NET Core 实战:使用 ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目

    一.前言 这几年前端的发展速度就像坐上了火箭,各种的框架一个接一个的出现,需要学习的东西越来越多,分工也越来越细,作为一个 .NET Web 程序猿,多了解了解行业的发展,让自己扩展出新的技能树,对自 ...

  7. C#开发微信门户及应用(47) - 整合Web API、微信后台管理及前端微信小程序的应用方案

    在微信开发中,我一直强调需要建立一个比较统一的Web API接口体系,以便实现数据的集中化,这样我们在常规的Web业务系统,Winform业务系统.微信应用.微信小程序.APP等方面,都可以直接调用基 ...

  8. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  9. 购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NE ...

随机推荐

  1. javascript 的dateObj.getTime() 在为C#的获取方式

    public string GetTime(DateTime dt) { Int64 retval = 0; DateTime st = new DateTime(1970, 1, 1); TimeS ...

  2. zoj2432

    /* 首先,dp的最开始是定义状态 dp[i][j] 表示A串的前i个,与B串的前j个,并以B[j]为结尾的LCIS 的长度. 状态转移方程: if(A[i]==B[j]) dp[i][j]=max( ...

  3. Apache 访问控制

    Apache访问控制 通过设置访问控制,可对网站进行权限管理,提高安全性. 参数介绍 <Directory />: 行为对根目录的限制 Options:允许使用控制目录特征的指令.他们包括 ...

  4. Linux 下的 core dump

    core dump 的基本概念      当一个进程要异常终止时 ,可以选择把进程的用户空间内存数据全部保存到磁盘上 ,文件名通常是 core, 这叫做 Core Dump.通常情况下,core文件会 ...

  5. Book Review of “The practice of programming” (Ⅱ)

    The practice of programming Chapter 2 Algorithms and Data Structures Searching sequential search (li ...

  6. sublime使用sublimelint-luacheck屏蔽指定警告

    在成功安装SublimeLinter-lua与luacheck以后,如果没有语法error,则会进行警告提示. 如下图 waring: line contains trailing whitespac ...

  7. sem学习

    关键字的选取搜索引擎营销的关键字选取是非常重要的一步,合适的关键字可以为企业带来可观的咨询量.关键字一般分4种,品牌词,产品词,行业词,竞品词,对于这四类词不同的推广策略有着不同的侧重点,根据市场情况 ...

  8. Java 获取路径的几种方法 - 转载

    1.获取当前类所在的“项目名路径” String rootPath = System.getProperty("user.dir"); 2.获取编译文件“jar包路径”(反射) S ...

  9. BOOST编译方法

    Windowsbjam --toolset=msvc-9.0 --prefix=C:\vc9_boost\vc9 --build-type=complete link=static threading ...

  10. Linux嵌入式 -- 内核简介(x86)

    0. 嵌入式系统 以应用为中心,软硬件可裁剪,对功耗.对体积.对成本等都有严格要求的专用计算机系统. 1.  linux体系结构 2. 为什么 划分为 用户空间 和 内核控件 ?  分两级,内核和应用 ...