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 ...
随机推荐
- 浅谈IDEA搭建SSM框架的集成
前言 学习完MyBatis,Spring,SpringMVC之后,我们需要做的就是将这三者联系起来,Spring实现业务对象管理,Spring MVC负责请求的转发和视图管理, MyBatis作为数据 ...
- java多线程与并发(基础篇)
一.进程与线程 进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位. 线程:是进程的一个执行路径,一个进程中至少有一个线程,进程中的多个线程共享进程的 资源. 虽然系统是把资源 ...
- 写论文的第二天 Hbase集群搭建
日志______2019.1.24 Hbase分布式搭建 注意:hbase的使用基于hadoop,开启以及关闭需要注意顺序,由于我是的是自带的zookeeper,说以开启关闭顺序应如下 启动:hado ...
- VSCode 使用Settings Sync同步配置(最新版教程,非常简单)
VSCode 使用Settings Sync同步配置(最新版教程,非常简单) 之前无意中听到有人说,vsCode最大的缺点就是每次换个电脑或者临时去个新环境,就要配置一下各种插件,好不麻烦,以至于面试 ...
- xpath中normalize-space的用法【转载】
下面这个菜单中,要点击“货运表现”,我们来看一下xpath, 菜单中的所有项的id都是“vertab”,所以不能用id来定位,那么先用文本的xpath试试 //a[text()='货运表现'] 发现定 ...
- 利用QGIS下载地图数据
这段时间做了一些利用地理信息进行定位导航的系列工作,其中很重要的一部分是如何获取到地图数据,比如道路的矢量图.某一区域的栅格图,我用到的主要工具是QGIS.QGIS是一个跨平台的免费应用,其中集成了对 ...
- .NET Core 小程序开发零基础系列(1)——开发者启用并牵手成功
最近几个月本人与团队一直与小程序打交道,对小程序的实战开发算比较熟悉,也因一些朋友经常问我各种小程序问题,无不能一一回答,想了很久,决定还是空余时间来写写文章吧,偶尔发现一个人安静的时候写文章特爽 ...
- Vim高手,从来不用鼠标
Vim脱离鼠标第一步 平时不可缺少的会用到vim,但是避免不了鼠标,事实上,省略鼠标是完全可以的,没有想像中那么难,看我短短几行带大家一起省略鼠标. 对了,vim有三种模式,基本模式就是用来输入命令的 ...
- TensorFlow Slim 的常用操作
https://blog.csdn.net/mzpmzk/article/details/81706379
- java web基础 js、JSP、servlet之间的传递
@ JS 与 JSP :JSP无法直接获取JS的值,只能通过隐藏表单或者dom节点设置. JSP中设置隐藏表单input,或者设置任意一个隐藏或者不隐藏的节点比如div, 而JS就通过document ...