建立3个项目,分别是类库WebSite、控制台TestWebSite、win服务WinService,目标框架均为.NET Framework 4.8.1。
其中控制台方便开发调试,win服务作为宿主服务,类库为自定义webservice的主体代码。
TestWebSite和WinService 引用nuget包 Microsoft.Owin.Host.HttpListener 4.2.2,不然启动的时候会提示错误消息:
The server factory could not be located for the given input
WebSite引用nuget包:
Microsoft.AspNet.Cors
Microsoft.AspNet.WebApi.Core
Microsoft.Owin
Microsoft.AspNet.WebApi.Owin
Microsoft.AspNet.WebApi.Cors
Microsoft.AspNet.WebApi.WebHost
Microsoft.AspNet.WebApi.SelfHost
Microsoft.Owin.Host.HttpListener
Microsoft.Owin.Hosting
Newtonsoft.Json
在WebSite中增加目录Controllers和wwwroot
using System;
using System.Web.Http;
namespace ConfigTool.WebSite.Controllers
{
[Route("api/[controller]")]
public class ValuesController : ApiController
{
[HttpGet]
[Route("Time")]
public string Time()
{
return DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
}
}
}
在wwwroot下放入index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
</script>
</head>
<body>
<p>
<input type="text" id="curtime" value="1"/>
<button id="submit">从api接口获取当前服务器时间</button>
</p>
<p>
<image src="images/1.jpg" alt="验证静态资源" width="300" height="300"/>
</p>
</body>
<script>
$("#submit").click(function(){
$.get("api/Values/Time",function(data,status){
$("#curtime").val(data);
});
});
</script>
</html>
新增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 ConfigTool.WebSite
{
internal class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = InitWebApiConfig();
app.UseWebApi(config);
//静态文件
app.Use((context, fun) =>
{
return StaticFileHandler(context, fun);
});
}
/// <summary>
/// 路由初始化
/// </summary>
HttpConfiguration InitWebApiConfig()
{
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "api/{controller}/{action}",
defaults: new { id = RouteParameter.Optional }
);
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"));
config.Formatters
.JsonFormatter.SerializerSettings = new
Newtonsoft.Json.JsonSerializerSettings()
{
DateFormatString = "yyyy-MM-dd HH:mm:ss"
};
return config;
}
/// <summary>
/// 客户端请求静态文件处理
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public Task StaticFileHandler(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 StaticFileResponse(context, path);
}
//不存在,返回下一个请求
return next();
}
static string GetFilePath(string path)
{
var basePath = AppDomain.CurrentDomain.BaseDirectory;
var filePath = path.TrimStart('/').Replace('/', '\\');
return Path.Combine(basePath, "wwwroot", filePath);
}
Task StaticFileResponse(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";
else
context.Response.ContentType = "application/octet-stream";
return context.Response.WriteAsync(File.ReadAllBytes(path));
}
return context.Response.WriteAsync(File.ReadAllText(path));
}
}
}
新增WebServer类文件
using Microsoft.Owin.Hosting;
using System;
namespace ConfigTool.WebSite
{
public class WebServer : IDisposable
{
IDisposable server;
int port = 8080;
public WebServer(int port)
{
this.port = port;
}
public void Start()
{
Console.WriteLine("WebServer Starting");
var host = "*";
var addr = $"http://{host}:{port}";
server = WebApp.Start<Startup>(url: addr);
Console.WriteLine($"WebServer Started @ {addr}");
}
public void Stop()
{
Console.WriteLine("WebServer Stopping");
server.Dispose();
Console.WriteLine("WebServer Stopped");
}
public void Dispose()
{
server?.Dispose();
}
}
}
修改控制台程序TestWebSite的Program.cs文件代码如下:
using ConfigTool.WebSite;
using System;
namespace ConfigTool.TestWebSite
{
internal class Program
{
static void Main(string[] args)
{
WebServer server = new WebServer(8080);
server.Start();
Console.ReadLine();
}
}
}
修改win服务程序WinService的MainService.cs(默认Service1.cs)文件代码如下:
using ConfigTool.WebSite;
using System.Configuration;
using System.ServiceProcess;
namespace ConfigTool.WinService
{
public partial class MainService : ServiceBase
{
public MainService()
{
InitializeComponent();
}
WebServer server;
protected override void OnStart(string[] args)
{
var port = ConfigurationManager.AppSettings.Get("PORT");
if (!int.TryParse(port, out int iport))
{
iport = 5000;
}
server = new WebServer(iport);
server.Start();
}
protected override void OnStop()
{
server?.Stop();
}
}
}
编写服务安装卸载脚本
echo.service installing......
echo off
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe "ConfigTool.WinService.exe"
@sc config ConfigTool.WinService start= auto
@net Start ConfigTool.WinService
echo on
echo.service started
pause
echo.uninstall service......
echo off
@net Stop ConfigTool.WinService
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u "ConfigTool.WinService.exe"
echo on
echo.service uninstalled
pause