Simple implementation of netcore mvc

  • Realization of functions

    • Simple routing system
    • Middleware Support
    • Simple Filter Support
    • Only supports HttpPost, HttpGet
    • Use Dotliquid view as the rendering engine
  • Core implementation

    • HttpChannel

      • Tcp monitor replication request, and in accordance with the data transmission tcp Http protocol data parsed into HttpRequest example, parsed the call processing to the next step HttpHandler
    • HttpRequest

      • Single Http request information, including HttpMethod, Version, Url, HttpHeader, Cookies and other information
    • HttpResponse

      • Http response information
    • DefaultHttpHandler

      • Achieve IHttpHandler, responsible for creating Middleware responsibility chain, execution

      •   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

      • Built middleware, mvc function embodied [Mode FIlter achieved]

      • 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

      • The easiest route to achieve resolve [URL ---> IController / Method]

      • Controller own instantiation uses IOC framework implemented netcore

      • 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

      • Abstract results of the implementation of the MVC analogy IActionResult

      • Built-in type

        • HttpStatusCodeResult: return only specific StatusCode, no specific content

        • JsonResult: return JSON result, content-type: application / json

        • RedirectResult: 302 return

        • ViewResult: Use DotLiquid as the view rendering engine

          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 Controller Interface
    • HttpCookie

      • cookie action class
    • IFilter

      • Filter Interface

         public interface IFilter
         {
             int Order { get; set; }
             Task OnActionExecutingAsync(ActionExecuteContext context);
             Task OnActionExecutedAsync(ActionExecuteContext context);
         }
  • other

    • This project is just learning to use, if wrong, please point out
    • This project is another project EasyProxy subsidiary products, so there is no independent github repository, specific directories for HttpServer

Guess you like

Origin www.cnblogs.com/zcode/p/11527485.html