netcore mvc 的简单实现
实现的功能
- 简单的路由系统
- 支持中间件
- 简单Filter支持
- 只支持HttpPost、HttpGet
- 使用Dotliquid做为视图渲染引擎
核心实现
HttpChannel
- 复制监听Tcp请求,并按照Http协议将tcp数据传输解析为HttpRequest数据实例,解析完调用HttpHandler继续下一步处理
HttpRequest
- 单次Http请求信息,包含 HttpMethod、Version、Url、HttpHeader、Cookies等信息
HttpResponse
- Http响应信息
DefaultHttpHandler
实现IHttpHandler,负责Middleware责任链的创建、执行
private IMiddleware BuildMiddlewareChain()
{
var builder = new MiddlewareChainBuilder();
builder.Use(new StaticFileMiddleware());
builder.Use(new MvcMiddleware(route));
return builder.Build();
} public async Task<HttpResponse> ProcessAsync(HttpRequest httpRequest)
{
var chain = BuildMiddlewareChain();
return await chain.Invoke(httpRequest);
}
MvcMiddleware
内置的中间件,mvc功能具体实现[FIlter模式实现]
public override async Task<HttpResponse> Invoke(HttpRequest httpRequest)
{
try
{
var context = new ActionExecuteContext
{
HttpRequest = httpRequest
}; var (controller, methodInfo, parameter) = route.Route(httpRequest);
if (controller == null)
{
return await HttpResponseHelper.CreateNotFoundResponseAsync();
} context.Controller = controller;
context.Action = methodInfo;
((ControllerBase)controller).Request = httpRequest; var filterList = GetFilters(controller, methodInfo);
var stack = new Stack<IFilter>();
for (var i = 0; i < filterList.Count; i++)
{
var filter = filterList[i];
await filter.OnActionExecutingAsync(context);
if (context.Final)
{
return context.HttpResponse;
}
stack.Push(filter);
} await controller.OnActionExecutingAsync(context); if (context.Final)
{
return context.HttpResponse;
} var parameters = new List<object>();
if (parameter != null)
{
parameters.Add(parameter);
} if (methodInfo.ReturnType.IsGenericType) //Task<IActionResult>
{
var actionResult = await (methodInfo.Invoke(controller, parameters.ToArray()) as Task<IActionResult>);
context.HttpResponse = await actionResult.ExecuteResultAsync();
}
else
{
var actionResult = methodInfo.Invoke(controller, parameters.ToArray()) as IActionResult;
context.HttpResponse = await actionResult.ExecuteResultAsync();
} context.HttpResponse.Cookies.AddRange(controller.ResponseCookie); await controller.OnActionExecutedAsync(context); if (context.Final)
{
return context.HttpResponse;
} while (stack.Count != 0)
{
var filter = stack.Pop();
await filter.OnActionExecutedAsync(context); if (context.Final)
{
return context.HttpResponse;
}
}
return context.HttpResponse;
}
catch (Exception e)
{
return await HttpResponseHelper.CreateDefaultErrorResponseAsync(e);
}
}
EasyRoute
实现最简单的路由解析【URL---> IController/Method】
Controller实例化使用netcore自带的IOC框架实现
public (IController, MethodInfo, object) Route(HttpRequest request)
{
var path = request.AbsolutePath;
Type controllerType;
MethodInfo methodInfo;
switch (request.HttpMethod)
{
case HttpMethod.Get:
if (httpGetRoutes.ContainsKey(path))
{
(controllerType, methodInfo) = httpGetRoutes[path];
}
else
{
return (null, null, null);
}
break;
case HttpMethod.Post:
if (httpPostRoutes.ContainsKey(path))
{
(controllerType, methodInfo) = httpPostRoutes[path];
}
else
{
return (null, null, null);
}
break;
default://Unsupport httpmethod
return (null, null, null);
}
var controllerObj = ServiceLocator.Instance.GetService(controllerType) as IController;
//var controllerObj = Activator.CreateInstance(controllerType) as IController;
object parameter = null;
var parameterType = methodInfo.GetParameters().SingleOrDefault()?.ParameterType;
if (parameterType != null)
{
parameter = ResolveParameter(parameterType, request);
} return (controllerObj, methodInfo, parameter);
}
IActionResult
执行结果的抽象,类比MVC的IActionResult
内置类型
HttpStatusCodeResult:只返回特定StatusCode,没有具体内容
JsonResult:返回JSON结果,content-type:application/json
RedirectResult:返回302
ViewResult:使用DotLiquid作为视图渲染引擎
public async Task<HttpResponse> ExecuteResultAsync()
{
var absoluteName = $"Views/{ViewName}";
Template template;
if (viewCache.ContainsKey(absoluteName))
{
template = viewCache[absoluteName];
}
else
{
var templateStr = Template.FileSystem.ReadTemplateFile(new Context(CultureInfo.CurrentCulture), absoluteName);
template = Template.Parse(templateStr);
viewCache.Add(absoluteName, template);
}
var content = template.Render(Hash.FromAnonymousObject(ViewData)); var res = new HttpResponse(); await res.WriteBodyAsync(Constants.DefaultEncoding.GetBytes(content)); return res;
}
IController
- mvc控制器接口
HttpCookie
- cookie操作类
IFilter
过滤器接口
public interface IFilter
{
int Order { get; set; }
Task OnActionExecutingAsync(ActionExecuteContext context);
Task OnActionExecutedAsync(ActionExecuteContext context);
}
其他
- 本项目只为学习使用,如有错误,请指出
- 本项目为另一个项目 EasyProxy 的附属产物,所以没有独立的github仓库,具体目录为 HttpServer
netcore mvc 的简单实现的更多相关文章
- .NetCore MVC中的路由(2)在路由中使用约束
p { margin-bottom: 0.25cm; direction: ltr; color: #000000; line-height: 120%; orphans: 2; widows: 2 ...
- .NetCore MVC中的路由(1)路由配置基础
.NetCore MVC中的路由(1)路由配置基础 0x00 路由在MVC中起到的作用 前段时间一直忙于别的事情,终于搞定了继续学习.NetCore.这次学习的主题是MVC中的路由.路由是所有MVC框 ...
- .netcore mvc docker环境jenkins一键部署(DevOps)
[前言] DevOps方面的文章很早之前就想分享了,挤出一点时间把前段时间搭建的一些提高开发效率的东西给大家分享一下吧. 本文介绍了一个.netcore mvc web项目,从项目push到githu ...
- windows 下开发的 .netCore MVC 部署到 Linux(Mint)
这两天在公司跟同事偶然聊到 .netCore,说到一些趋势什么的.但是说来说去自己也没试过在Linux 机子上部署过,所以就试一下. 尝试之前也在网上看了一些文章,包括 Linux 上.netCore ...
- ASP.NETCORE MVC模块化
ASP.NETCORE MVC模块化编程 前言 记得上一篇博客中跟大家分享的是基于ASP.NETMVC5,实际也就是基于NETFRAMEWORK平台实现的这么一个轻量级插件式框架.那么今天我主要分享的 ...
- NETCORE MVC模块化
NETCORE MVC模块化 ASP.NETCORE MVC模块化编程 前言 记得上一篇博客中跟大家分享的是基于ASP.NETMVC5,实际也就是基于NETFRAMEWORK平台实现的这么一个轻量级插 ...
- netcore mvc菜单,角色,权限
netcore mvc快速开发系统(菜单,角色,权限[精确到按钮])开源 AntMgr https://github.com/yuzd/AntMgr 基于netcore2.0 mvc 开发的 快速搭建 ...
- Nancy和MVC的简单对比
Nancy和MVC的简单对比 在上一篇的.NET轻量级MVC框架:Nancy入门教程(一)——初识Nancy中,简单介绍了Nancy,并写了一个Hello,world.看到大家的评论,都在问Nancy ...
- [.Net Core] 在 Mvc 中简单使用日志组件
在 Mvc 中简单使用日志组件 基于 .Net Core 2.0,本文只是蜻蜓点水,并非深入浅出. 目录 使用内置的日志组件 简单过渡到第三方组件 - NLog 使用内置的日志 下面使用控制器 Hom ...
随机推荐
- java并发编程(四)----(JUC)Lock锁初探
首先我们来回忆一下上一节讲过的synchronized关键字,该关键字用于给代码段或方法加锁,使得某一时刻它修饰的方法或代码段只能被一个线程访问.那么试想,当我们遇到这样的情况:当synchroniz ...
- java并发编程(十三)----(JUC原子类)引用类型介绍(CAS和ABA的介绍)
这一节我们将探讨引用类型原子类:AtomicReference, AtomicStampedRerence, AtomicMarkableReference.AtomicReference的使用非常简 ...
- 【win】【qt5打包】【qt程序打包成一个可执行文件(带图标任何win都可以运行哦)】
[前言] 业务需求将qt程序打包成win可执行文件.咱是做linux的,奈何用的麒麟系统,程序运行在win,好嘛,重新在win qtcreator编译后打包呗. [目标] 1.给qt程序添加一个图标. ...
- 手写Struts,带你深入源码中心解析
个人剖析,不喜勿喷 扫码关注公众号,不定期更新干活 在此申明本博文并非原创,原文:http://blog.csdn.net/lenotang/article/details/3336623,本文章是在 ...
- 洛谷 P1960 列队
题意简述 有一个n × m 的矩阵,第i行第j列元素编号为(i - 1)× m +j 每次将一个数取出,其他元素依次向左,向上填补空缺,最后将取出的数放入矩阵最后一格 求每次取出数的编号 题解思路 由 ...
- 小白学Python(7)——利用Requests下载网页图片、视频
安装 Requests 如果安装了Requests就已经可用了,否则要安装 Requests,只要在你的CMD中运行这个简单命令即可: pip install requests requests使用 ...
- python学习笔记(6)--面向对象学习
本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引言 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做(人狗大战)的游戏,你就思 ...
- Spring-Boot:Profile简单示例
//Resources目录下创建 application.properties spring.profiles.active=prod //Resources目录下创建 application-pro ...
- Linux系统启动流程(重要!)
Linux系统启动流程 从上至下为: BIOS MBR:Boot Code 执行引导程序-GRUB(操作系统) 加载内核 执行init run level 1.BIOS(Basic Input ...
- python 07 数据类型
目录 1. 基础数据类型填充 1.str:(不可变) 2. list: 3. tuple: 4. dict: 5. set: 6. bool: 7. 数据类型之间转换 2.删除列表/字典的代码坑: 3 ...