vs2017
新建项目
.net framework 4.6.1
目录
包
Dapper 1.60.6 .NET对象映射器
FluentValidation 8.6.1 类型验证规则
Mysql.Data 8.0.32 mysql 数据库连接
FluentValidation 简单使用
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace netceshi.Filter
{
public class ParamsFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
//如果参数非法
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
//如果没有输入参数
else if (actionContext.ActionArguments.Values.First() == null)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "请输入参数!");
}
}
}
}
FluentValidationModelValidatorProvider.Configure(config);
using FluentValidation;
using FluentValidation.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace netceshi.Models
{
[Validator(typeof(PersonValidator))]
public class Person
{
public int Id {
get; set; }
public string Name {
get; set; }
public string Sex {
get; set; }
public int Age {
get; set; }
}
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(m => m.Id).NotEmpty().NotNull().WithMessage("Id不能为空");
RuleFor(m => m.Name).NotEmpty().NotNull().WithMessage("Name不能为空");
}
}
}
using netceshi.Filter;
using netceshi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace netceshi.Controllers
{
public class PersonController : ApiController
{
Person[] person = new Person[]
{
new Person {
Id = 1, Name = "张三", Sex = "男", Age = 18 },
new Person {
Id = 1, Name = "李四", Sex = "女", Age = 18 },
new Person {
Id = 1, Name = "王二", Sex = "男", Age = 22 },
new Person {
Id = 1, Name = "麻子", Sex = "男", Age = 23 },
};
[HttpGet]
public Person[] Index()
{
return person;
}
[HttpPost]
[ParamsFilter]
public Person Person([FromBody]Person p)
{
return p;
}
}
}
using FluentValidation.WebApi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace netceshi
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API 配置和服务
FluentValidationModelValidatorProvider.Configure(config);
// Web API 路由
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new {
id = RouteParameter.Optional }
);
var formatters = config.Formatters.Where(formatter =>
formatter.SupportedMediaTypes.Where(media =>
media.MediaType.ToString() == "application/xml" || media.MediaType.ToString() == "text/html").Count() > 0) //找到请求头信息中的介质类型
.ToList();
foreach (var match in formatters)
{
config.Formatters.Remove(match); //移除请求头信息中的XML格式
}
}
}
}
mysql 数据库的简单增删改操作
数据库连接配置
<connectionStrings>
<add name="test" connectionString="Database=cloud-user;Data Source=127.0.0.1;Port=3306;User Id=root;Password=123456;SslMode = none;Charset=utf8;"/>
</connectionStrings>
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
namespace netceshi.Filter
{
public class DapperTools
{
//数据库连接字符串
public static readonly string ConnectionString = ConfigurationManager.ConnectionStrings["test"].ConnectionString;
}
}
数据库结构 cloud-user(数据库名称)
/*
Navicat MySQL Data Transfer
Source Server : 111
Source Server Version : 50722
Source Host : localhost:3306
Source Database : cloud-user
Target Server Type : MYSQL
Target Server Version : 50722
File Encoding : 65001
Date: 2023-02-17 17:03:23
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL COMMENT '收件人',
`address` varchar(255) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
下面的,我是随便建的
using FluentValidation;
using FluentValidation.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace netceshi.Models
{
public class User
{
public int Id {
get; set; }
public string UserName {
get; set; }
public string Address {
get; set; }
}
}
using netceshi.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace netceshi.Server
{
interface UserServer
{
/*
* 列表
*/
Object GetUsers();
/*
* 添加
*/
Object AddUser(User u);
/*
* 删除
*/
Object DelUser(int id);
/*
* 修改
*/
Object UpdateUser(User u);
}
}
using Dapper;
using MySql.Data.MySqlClient;
using netceshi.Filter;
using netceshi.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
namespace netceshi.DAL
{
public class DALUser
{
static string getList = "SELECT * FROM `tb_user`";
static string del = "DELETE FROM `tb_user` WHERE (`id`=?id)";
static string add = "INSERT INTO `tb_user` (`username`, `address`) VALUES (?username, ?address)";
static string update = "UPDATE `tb_user` SET `username`=?UserName, `address`=?Address WHERE (`id`=?Id)";
public Object GetUsers()
{
using (IDbConnection connection = new MySqlConnection(DapperTools.ConnectionString))
{
var result = connection.Query<User>(getList);
return result;
}
}
public Object DelUsers(int id)
{
using (IDbConnection connection = new MySqlConnection(DapperTools.ConnectionString))
{
User u = new User();
u.Id = id;
var result = connection.Execute(del, u);
return result;
}
}
public Object UpdteUsers(User u)
{
using (IDbConnection connection = new MySqlConnection(DapperTools.ConnectionString))
{
var result = connection.Execute(update, u);
return result;
}
}
public Object AddUsers(User u)
{
using (IDbConnection connection = new MySqlConnection(DapperTools.ConnectionString))
{
var result = connection.Execute(add, u);
return result;
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using netceshi.Models;
namespace netceshi.Server.Impl
{
class UserServerImpl : UserServer
{
DAL.DALUser daluser = new DAL.DALUser();
public Object AddUser(User u)
{
return daluser.AddUsers(u);
}
public Object DelUser(int id)
{
return daluser.DelUsers(id);
}
public Object GetUsers()
{
return daluser.GetUsers();
}
public Object UpdateUser(User u)
{
return daluser.UpdteUsers(u);
}
}
}
using netceshi.Server.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace netceshi.Controllers
{
public class UserController : ApiController
{
UserServerImpl userServerImpl = new UserServerImpl();
[HttpGet]
public Object Index()
{
return userServerImpl.GetUsers();
}
[HttpDelete]
public Object Del(int id)
{
return userServerImpl.DelUser(id);
}
[HttpPost]
public Object Add(Models.User u)
{
return userServerImpl.AddUser(u);
}
[HttpPut]
public Object Update(Models.User u)
{
return userServerImpl.UpdateUser(u);
}
}
}
测试
统一响应
后面可能没使用统一响应
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace netceshi.Models
{
public interface IHttpResponseResult
{
}
/// <summary>
/// 响应数据输出泛型接口
/// </summary>
/// <typeparam name="T"></typeparam>
// ReSharper disable once UnusedTypeParameter
public interface IHttpResponseResult<T> : IHttpResponseResult
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace netceshi.Models
{
public class HttpResponseResult<T> : IHttpResponseResult<T>
{
/// <summary>
/// 状态码
/// </summary>
public int Code {
get; set; }
/// <summary>
/// 消息
/// </summary>
public string Message {
get; set; }
/// <summary>
/// 数据
/// </summary>
public T Data {
get; set; }
/// <summary>
/// 成功
/// </summary>
/// <param name="data">数据</param>
/// <param name="msg">消息</param>
public HttpResponseResult<T> Success(T data = default, string msg = null)
{
Code = 0;
Data = data;
Message = msg;
return this;
}
/// <summary>
/// 失败
/// </summary>
/// <param name="code">状态码</param>
/// <param name="msg">消息</param>
/// <param name="data">数据</param>
/// <returns></returns>
public HttpResponseResult<T> Fail(T data = default, int code = -1, string msg = null)
{
Code = code;
Message = msg;
Data = data;
return this;
}
}
/// <summary>
/// 响应数据静态输出
/// </summary>
public static class HttpResponseResult
{
/// <summary>
/// 成功
/// </summary>
/// <param name="data">数据</param>
/// <param name="msg">消息</param>
/// <returns></returns>
public static IHttpResponseResult Success<T>(T data, string msg = "message")
{
return new HttpResponseResult<T>().Success(data, msg);
}
/// <summary>
/// 失败
/// </summary>
/// <param name="data">数据</param>
/// <param name="msg">消息</param>
/// <param name="code">状态码</param>
/// <returns></returns>
public static IHttpResponseResult Fail<T>(T data, string msg = null, int code = -1)
{
return new HttpResponseResult<T>().Fail(data, code, msg);
}
}
}
jwt
登录数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace netceshi.Models
{
public class LoginUser
{
public string UserName {
get; set;}
public string PassWord {
get; set; }
}
}
jwt 工具
using JWT.Algorithms;
using JWT.Exceptions;
using JWT.Serializers;
using JWT;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace netceshi.Filter
{
public class JWTHelper
{
private static string Key {
get; set; } = "bfdhargrtjuykreawtuyjtretryjgafasdgrth";
private IJwtAlgorithm algorithm {
get; set; } // 这是 HMACSHA256加密算法
private IJsonSerializer serializer {
get; set; }// 这是JSON序列化工具
private IBase64UrlEncoder urlEncoder {
get; set; } // 这是BASE64编码工具
private IDateTimeProvider provider {
get; set; }// 时间提供器 用来提供 格式一致的时间
private IJwtValidator validator {
get; set; }
public JWTHelper()
{
Key = "klklergsflergldsarertlherdsigerklgld";// 这个密钥
algorithm = new HMACSHA256Algorithm(); // 这是 HMACSHA256加密算法
serializer = new JsonNetSerializer();// 这是JSON序列化工具
urlEncoder = new JwtBase64UrlEncoder(); // 这是BASE64编码工具
provider = new UtcDateTimeProvider(); // 时间提供器
validator = new JwtValidator(serializer, provider); // 令牌校验器,用来验证有效期和签名
}
public string GetToken(Dictionary<string, object> payload, int expSeconds)
{
var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // or use JwtValidator.UnixEpoch
var now = provider.GetNow();
payload["exp"] = Math.Round((now - unixEpoch).TotalSeconds) + expSeconds;// exp 有效期
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);// JWT加密工具
var token = encoder.Encode(payload, Key); // 加密生成TOKEN
return token;
}
// 解密
public string GetPayload(string token)
{
try
{
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm); // 创建解密工具
var json = decoder.Decode(token, Key, verify: true);//token 中的载体的 JSON 格式字符串
return json; // payload
}
catch (TokenExpiredException)
{
Console.WriteLine("Token has expired");
return null;
}
catch (SignatureVerificationException)
{
Console.WriteLine("Token has invalid signature");
return null;
}
catch(Exception e)
{
Console.WriteLine(e);
return null;
}
}
}
}
认证操作
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Controllers;
using System.Web.Http;
using netceshi.DAL;
namespace netceshi.Filter
{
public class MyAuth : AuthorizeAttribute
{
JWTHelper jwt = new JWTHelper();
static string name = null;
//public override void OnActionExecuting(ActionExecutingContext filterContext)
//{
//}
public override void OnAuthorization(HttpActionContext actionContext)
{
try
{
var header = actionContext.Request.Headers.GetValues("Authorization");
if (header != null)
{
string token = header.First();
var json = jwt.GetPayload(token);
if (json != null)
{
Dictionary<string, object> dic = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
actionContext.ControllerContext.RouteData.Values["username"] = dic["username"];
name = dic["username"].ToString();
}
else
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK);
var x = new ResponseData() {
code = 0, message = "token错误" };
actionContext.Response.Content = new StringContent(JsonConvert.SerializeObject(x), Encoding.UTF8, "appliaction/json");
}
}
else
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK);
var x = new ResponseData() {
code = 0, message = "没有token" };
actionContext.Response.Content = new StringContent(JsonConvert.SerializeObject(x), Encoding.UTF8, "appliaction/json");
}
}
catch
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.OK);
var x = new ResponseData() {
code = 0, message = "错误 0099999" };
actionContext.Response.Content = new StringContent(JsonConvert.SerializeObject(x), Encoding.UTF8, "appliaction/json");
}
}
public static string Username()
{
return name;
}
}
public class ResponseData
{
public int code {
get; set; }
public object data {
get; set; }
public string message {
get; set; }
}
}
用户登录,没操作数据库,只是写固定的
[HttpPost]
public IHttpResponseResult Login(LoginUser loginUser)
{
JWTHelper jWT= new JWTHelper();
Dictionary<string, object> payload = new Dictionary<string, object>();
payload.Add("username", loginUser.UserName);
var jst = jWT.GetToken(payload,30);
return HttpResponseResult.Success(jst, "成功");
}
[MyAuth] // 走认证
[HttpGet]
public IHttpResponseResult Index2()
{
//MyAuth.Username() 认证成功在jwt里取出来的,,,,可以去看看jwt工具和认证MyAuth
return HttpResponseResult.Success(MyAuth.Username(), "成功");
}
[MyAuth]// 走认证
[HttpGet]
public Object Index()
{
return userServerImpl.GetUsers();
}
跨域配置
<httpProtocol>
<customHeaders>
<remove name="Access-Control-Allow-Origin" />
<remove name="Access-Control-Allow-Headers" />
<remove name="Access-Control-Allow-Methods" />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="*" />
</customHeaders>
</httpProtocol>
/// <summary>
/// 跨域设置
/// </summary>
public void Application_BeginRequest()
{
//OPTIONS请求方法的主要作用:
//1、获取服务器支持的HTTP方法;也就是黑客经常用的方法。
//2、用来检查服务器的性能。如Ajax进行跨域请求是的预检,需要想另外一个域名的资源发送OPTIONS请求头,用以判断发送的请求是否安全
if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
{
//表示对输出的内容进行缓冲,执行page.Response.Flush()时,会等所有内容缓冲完毕,将内容发送到客户端
//这样就不会出错,造成页面卡死状态,让用户无限制等下去
Response.Flush();
}
}
安装 IIS
可能需要等一会,如果失败那就在试一次
IIS 可能出现的错误
IIS运行.net web程序报错:不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。锁定是默认设置的(overrideModeDefault=“Deny“),或...
以管理员身份运行命令行:
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/handlers
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/modules
HTTP 错误 500.21 - Internal Server Error
处理程序“ExtensionlessUrlHandler-Integrated-4.0”在其模块列表中有一个错误模块“ManagedPipelineHandler”
最可能的原因:
使用了托管处理程序,但是未安装或未完整安装 ASP.NET。
处理程序模块列表的配置中存在书写错误。
在应用程序初始化期间,要么应用程序初始化功能已将 skipManagedModules 设置为 True,要么重写规则设置了映射到托管处理程序的 URL 并且还设置了 SKIP_MANAGED_MODULES=1。
可尝试的操作:
如果要使用托管处理程序,请安装 ASP.NET。
请确保正确指定处理程序模块的名称。模块名称区分大小写,并使用 modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" 格式。
设置映射到托管处理程序的 URL (例如 .aspx)时,请确保所有应用程序初始化重写规则都设置 SKIP_MANAGED_MODULE=0
作为替代方法,请确保应用程序初始化重写规则将请求映射到非托管处理程序(例如,映射到 .htm 文件,该文件映射到 StaticFileHandler。)
执行命令:
dism /online /enable-feature /featurename:IIS-ISAPIFilter
dism /online /enable-feature /featurename:IIS-ISAPIExtensions
dism /online /enable-feature /featurename:IIS-NetFxExtensibility45
dism /online /enable-feature /featurename:IIS-ASPNET45
当前标识(IIS APPPOOL\.NET v4.5)没有对"C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files"的写访问权限。
以管理员身份运行命令行:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Aspnet_regiis.exe -ga 'IIS APPPOOL\.NET v4.5'
需要和报错信息对应
部署 IIS
打开iis,添加网站