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——标准异常
Throwable这个java类被用来表示任何可以作为异常被抛出的类,Throwable可以分为两种类型,Error用来表示编译时和系统错误,Exception是可以被抛出的基本类型. 1.Runti ...
- 算法与数据结构基础 - 分治法(Divide and Conquer)
分治法基础 分治法(Divide and Conquer)顾名思义,思想核心是将问题拆分为子问题,对子问题求解.最终合并结果,分治法用伪代码表示如下: function f(input x size ...
- Flutter学习笔记(16)--Scaffold脚手架、AppBar组件、BottomNavigationBar组件
如需转载,请注明出处:Flutter学习笔记(15)--MaterialApp应用组件及routes路由详解 今天的内容是Scaffold脚手架.AppBar组件.BottomNavigationBa ...
- Kubernetes-保障集群内节点和网络安全
13.1.在pod中使用宿主节点的Linux命名空间 13.1.1.在pod中使用宿主节点的网络命名空间 在pod的yaml文件中就设置spec.hostNetwork: true 这个时候pod使用 ...
- Flutter学习笔记(21)--TextField文本框组件和Card卡片组件
如需转载,请注明出处:Flutter学习笔记(21)--TextField文本框组件和Card卡片组件 今天来学习下TextField文本框组件和Card卡片组件. 只要是应用程序就少不了交互,基本上 ...
- JSP引擎、JSP容器、Web服务器
JSP引擎与JSP容器指的都是同一样的东西,他们都是用来同一管理和运行Web引用程序的“软件”.常见的JSP引擎有Tomcat.JRun.Resin 广义上来说,JSP引擎是用来管理和运行Web应用程 ...
- Kali-Linux-美化与优化
照理说,linux的桌面是不应当存在在这个世界上的,作为一个linux用户,一味捣鼓桌面显得hin-不专业.但是,虚拟机要用到,浏览器要用到--更何况,自己的老婆能不打扮一下么? update:201 ...
- Mybatis延迟加载的实现以及使用场景
首先我们先思考一个问题,假设:在一对多中,我们有一个用户,他有100个账户. 问题1:在查询用户的时候,要不要把关联的账户查出来? 问题2:在查询账户的时候,要不要把关联的用户查出来? 解答:在查询用 ...
- Python笔记_类
1.类 1.1 类的定义 # 类的定义 class 类名: pass # pass是空语句,不具有任何意义,仅为了保持程序结构完整性 # 创建对象 对象名 = 类名() 1.2 成员变量 # 成员变量 ...
- Redis学习总结(三)--Redis持久化
Redis 是将数据存储在内存中的,如果出现断电或系统故障的时候数据就会存在丢失的现象,Redis通过将数据持久化到硬盘中来避免这个问题的出现,我们今天就来学习下 Redis 持久化. Redis 持 ...