利用SelfHost实现小型HTTP服务器

本文详细介绍如何使用Microsoft OWIN和WebAPI创建自托管HTTP服务,包括添加Nuget包、配置路由、处理静态文件请求及实现跨域访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.创建应用,可以是Winform,WPF或者控制台的应用

创建控制台项目
创建控制台应用


 2.从Nuget添加下列引用
   (1) Microsoft.AspNet.Cors 
   (2) Microsoft.AspNet.WebApi.Core

   (3) Microsoft.Owin

   (4) Newtonsoft.Json
   (5)  Microsoft.AspNet.WebApi.Owin

   (6)  Microsoft.AspNet.WebApi.Cors
   (7)  Microsoft.AspNet.WebApi.WebHost
   (8)  Microsoft.AspNet.WebApi.SelfHost

   (9) Microsoft.Owin.Host.HttpListener

   (10) Microsoft.Owin.Hosting
 安装这些包时,其依赖项也一并安装.

安装依赖库
安装依赖库
依赖库安装完毕后
依赖库安装完毕后


 安装完毕后,package.config内容如下:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="FirebirdSql.Data.FirebirdClient" version="6.6.0" targetFramework="net452" />
  <package id="Microsoft.AspNet.Cors" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.Cors.zh-Hans" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.SelfHost" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.7" targetFramework="net452" />
  <package id="Microsoft.Owin" version="4.0.1" targetFramework="net452" />
  <package id="Microsoft.Owin.Host.HttpListener" version="4.0.1" targetFramework="net452" />
  <package id="Microsoft.Owin.Hosting" version="4.0.1" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net452" />
  <package id="Owin" version="1.0" targetFramework="net452" />
</packages>

3.接下来,在项目中创建目录WebApi

4.在WebApi下创建目录controllers

创建文件夹
创建文件夹

5.在WebApi下新建类Startup,内容如下:

 

using Microsoft.Owin;
using Owin;
using System;
using System.IO;
using System.Net.Http.Formatting;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;

namespace HttpSelfHost.WebApi
{

    class Startup
    {
        private static string _siteDir =
               System.Configuration.ConfigurationManager.AppSettings.Get("SiteDir");
        public void Configuration(IAppBuilder app)
        {
            // web api 接口
            HttpConfiguration config = InitWebApiConfig();
            app.UseWebApi(config);
            //静态文件
            app.Use((context, fun) =>
            {
                return StaticWebFileHandel(context, fun);
            });
        }
        /// <summary>
        /// 路由初始化
        /// </summary>
        public HttpConfiguration InitWebApiConfig()
        {
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                name: "Default",
                routeTemplate: "api/{controller}/{action}",
                defaults: new { id = RouteParameter.Optional }
            );
            // 配置 http 服务的路由
            var cors = new EnableCorsAttribute("*", "*", "*");//跨域允许设置
            config.EnableCors(cors);

            config.Formatters
               .XmlFormatter.SupportedMediaTypes.Clear();
            //默认返回 json
            config.Formatters
                .JsonFormatter.MediaTypeMappings.Add(
                new QueryStringMapping("datatype", "json", "application/json"));
            //返回格式选择
            config.Formatters
                .XmlFormatter.MediaTypeMappings.Add(
                new QueryStringMapping("datatype", "xml", "application/xml"));

            //json 序列化设置
            config.Formatters
                .JsonFormatter.SerializerSettings = new
                Newtonsoft.Json.JsonSerializerSettings()
                {
                    //NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
                    DateFormatString = "yyyy-MM-dd HH:mm:ss" //设置时间日期格式化
                };
            return config;
        }
        /// <summary>
        /// 客户端请求静态文件处理
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public Task StaticWebFileHandel(IOwinContext context, Func<Task> next)
        {
            //获取物理文件路径
            var path = GetFilePath(context.Request.Path.Value);
            //验证路径是否存在
            if (!File.Exists(path) && !path.EndsWith("html"))
            {
                path += ".html";
            }
            if (File.Exists(path))
            {
                return SetResponse(context, path);
            }
            //不存在返回下一个请求
            return next();
        }
        public static string GetFilePath(string relPath)
        {
            if (relPath.IndexOf("index") > -1)
            {
                String temp = relPath;
            }
            var basePath = AppDomain.CurrentDomain.BaseDirectory;
            var filePath = relPath.TrimStart('/').Replace('/', '\\');
            if (_siteDir == ".")
            {
                return Path.Combine(basePath, filePath);
            }
            else
            {
                return Path.Combine(
                  AppDomain.CurrentDomain.BaseDirectory
                  , _siteDir == "." ? "" : _siteDir
                  , relPath.Replace('/', '\\')).TrimStart('\\');
            }
        }

        public Task SetResponse(IOwinContext context, string path)
        {
            /*
                .txt text/plain
                RTF文本 .rtf application/rtf
                PDF文档 .pdf application/pdf
                Microsoft Word文件 .word application/msword
                PNG图像 .png image/png
                GIF图形 .gif image/gif
                JPEG图形 .jpeg,.jpg image/jpeg
                au声音文件 .au audio/basic
                MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
                RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
                MPEG文件 .mpg,.mpeg video/mpeg
                AVI文件 .avi video/x-msvideo
                GZIP文件 .gz application/x-gzip
                TAR文件 .tar application/x-tar
                任意的二进制数据 application/octet-stream
             */
            var perfix = Path.GetExtension(path);
            if (perfix == ".html")
                context.Response.ContentType = "text/html; charset=utf-8";
            else if (perfix == ".txt")
                context.Response.ContentType = "text/plain";
            else if (perfix == ".js")
                context.Response.ContentType = "application/x-javascript";
            else if (perfix == ".css")
                context.Response.ContentType = "text/css";
            else
            {
                if (perfix == ".jpeg" || perfix == ".jpg")
                    context.Response.ContentType = "image/jpeg";
                else if (perfix == ".gif")
                    context.Response.ContentType = "image/gif";
                else if (perfix == ".png")
                    context.Response.ContentType = "image/png";
                else if (perfix == ".svg")
                    context.Response.ContentType = "image/svg+xml";
                else if (perfix == ".woff")
                    context.Response.ContentType = "application/font-woff";
                else if (perfix == ".woff2")
                    context.Response.ContentType = "application/font-woff2";
                else if (perfix == ".ttf")
                    context.Response.ContentType = "application/octet-stream";

                return context.Response.WriteAsync(File.ReadAllBytes(path));
            }
            //truetype
            return context.Response.WriteAsync(File.ReadAllText(path));
        }
    }
}

  这里需要添加引用:System.Configuration:

添加System.Configuration引用
添加System.Configuration引用

5.在WebApi下新建类WebServer,内容如下:

using System;
using Microsoft.Owin.Hosting;

namespace HttpSelfHost.WebApi
{
    public class WebServer
    {
        static IDisposable server = null;
        public static event EventHandles.MessageEventHandle MessageEvent = null;
        public static void Start()
        {
            StartOptions opt = new StartOptions();
            opt.Port = int.Parse(System.Configuration.ConfigurationManager.AppSettings.Get("Port"));
            string baseAddress = string.Format("http://{0}:{1}/",
                   "*",
                   System.Configuration.ConfigurationManager.AppSettings.Get("Port"));
            server = WebApp.Start<Startup>(url: baseAddress);
            MessageEvent?.Invoke(String.Format("host 已启动:{0}", baseAddress));
        }
    }
}

6. App.config中添加配置节

  <appSettings>
    <add key="Domain" value="localhost" />
    <add key="port" value="9000" />
    <add key="SiteDir" value="." />
  </appSettings>

     其中的port为HttpSelfHost监听的端口

App.config内容
App.config内容

7.在controllers目录下创建控制器DemoController,然后添加几个方法:

using HttpSelfHost.model;
using System;
using System.Collections.Generic;
using System.Web.Http;

namespace HttpSelfHost.WebApi.controllers
{
    public class DemoController:ApiController
    {
        [HttpGet]
        [HttpPost]
        public dynamic allStudents()
        {
            return new
            {
                result = true,
                desc =  "请求成功",
                data = new List<StudentInfo>()
                {
                    new StudentInfo
                    {
                        ClassId="ClassID982712311231",
                        Sex="男",
                        StudentId=Guid.NewGuid().ToString(),
                        StudentName="男学生一枚",
                        StudentNumber="XH2018090001"
                    },
                    new StudentInfo
                    {
                        ClassId="ClassID982712311232",
                        Sex="女",
                        StudentId=Guid.NewGuid().ToString(),
                        StudentName="女学生一枚",
                        StudentNumber="XH2018090002"
                    }
                }
            };
        }
        [HttpGet]
        [HttpPost]
        public dynamic queryStudents([FromBody]string name)
        {
            return new
            {
                result = true,
                desc = "查询请求成功,参数name:"+name,
                data = new List<StudentInfo>()
                {
                    new StudentInfo
                    {
                        ClassId="ClassID982712311231",
                        Sex="男",
                        StudentId=Guid.NewGuid().ToString(),
                        StudentName="男学生一枚",
                        StudentNumber="XH2018090001"
                    },
                    new StudentInfo
                    {
                        ClassId="ClassID982712311232",
                        Sex="女",
                        StudentId=Guid.NewGuid().ToString(),
                        StudentName="女学生一枚",
                        StudentNumber="XH2018090002"
                    }
                },
                page=1,
                total=2,
                pageCount=1
            };
        }
        [HttpGet]
        [HttpPost]
        public dynamic saveStudents([FromBody]StudentInfo info)
        {
            info.StudentId = Guid.NewGuid().ToString();
            return new
            {
                result = true,
                desc = "保存成功,学生姓名:" + info.StudentName,
                data = info.StudentId
            };
        }
    }
}

添加控制器

8. 接下来就可以在应用中启动HTTP服务了:

using System;

namespace HttpSelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            StartServer();
            String inputStr = null;
            while ((inputStr = Console.ReadLine()).ToLower() != "exit")
            {

            }
        }
        static public void StartServer()
        {
            WebApi.WebServer.MessageEvent += WebServer_MessageEvent;
            WebApi.WebServer.Start();
        }

        private static void WebServer_MessageEvent(string msg)
        {
            Console.WriteLine(msg);
        }
    }
}

运行一下:

运行SelfHostHttp
运行SelfHostHttp

我们在浏览器中测试一下接口:

Get测试
Get测试

带参数Get测试

Post测试
Post测试
Post对象提交
Post对象提交
Post对象提交
Post对象提交

 

接下来,我们测试静态文件请求

9.在生成的输出目录创建文件夹HttpPages:

创建静态文件目录
创建静态文件目录

10. 然后将HTML文件和需要的CSS,JS一股脑儿拷贝进去:

11.在VS的解决方案管理器中,点击右上角的"显示所有文件":

然后展开bin/Debug,右键选择HttpPages,弹出的菜单中选择"包括在项目中":

在pages目录下添加一个测试的html文件,包含vue,iview等脚本和css,注意引用的相对位置:

OK,接下来启动程序,看看打开网页是什么情况:

静态文件请求
静态文件请求

 

看起来还不错.

其中部分代码参考了本站许多大神的帖子,希望大神看到后留下帖子地址,本人可以修改帖子具名出处.

 

本文代码下载:点此去优快云下载

抱歉,下载要几点积分,最近积分不够用了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值