使用C#HttpListener进行URL映射

在下面的代码中,我正在等待对8080端口的任何调用。

static void Main() { HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://*:8080/"); listener.Start(); while(isRunning) { HttpListenerContext ctx = listener.GetContext(); new Thread(new Worker(ctx).ProcessRequest).Start(); } } 

是否可以将特定的URL模式映射到不同的行为? 我想实现一个REST风格的服务器,即调用localhost:8080 / person / 1将启动getPersonH​​andler(int)

 [Mapping("*:8080/person/$id")] public void getPersonHandler(int id){...} 

我知道, Mapping语法只是我自己对JAX-RS库的一厢情愿。 我想在C#中做同样的事情(桌面C#,而不是asp)

没有属性,您可以获得类似的效果

 HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://*:8080/"); listener.Start(); while (true) { HttpListenerContext ctx = listener.GetContext(); ThreadPool.QueueUserWorkItem((_) => { string methodName = ctx.Request.Url.Segments[1].Replace("/", ""); string[] strParams = ctx.Request.Url .Segments .Skip(2) .Select(s=>s.Replace("/","")) .ToArray(); var method = this.GetType().GetMethod(methodName); object[] @params = method.GetParameters() .Select((p, i) => Convert.ChangeType(strParams[i], p.ParameterType)) .ToArray(); object ret = method.Invoke(this, @params); string retstr = JsonConvert.SerializeObject(ret); }); 

用法是:

 http://localhost:8080/getPersonHandler/333 

如果你真的想使用属性那么

 HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://*:8080/"); listener.Start(); while (true) { HttpListenerContext ctx = listener.GetContext(); ThreadPool.QueueUserWorkItem((_) => { string methodName = ctx.Request.Url.Segments[1].Replace("/", ""); string[] strParams = ctx.Request.Url .Segments .Skip(2) .Select(s=>s.Replace("/","")) .ToArray(); var method = this.GetType() .GetMethods() .Where(mi => mi.GetCustomAttributes(true).Any(attr => attr is Mapping && ((Mapping)attr).Map == methodName)) .First(); object[] @params = method.GetParameters() .Select((p, i) => Convert.ChangeType(strParams[i], p.ParameterType)) .ToArray(); object ret = method.Invoke(this, @params); string retstr = JsonConvert.SerializeObject(ret); }); } 

然后你可以使用http://localhost:8080/Person/333 ,你的定义就是

 class Mapping : Attribute { public string Map; public Mapping(string s) { Map = s; } } [Mapping("Person")] public void getPersonHandler(int id) { Console.WriteLine("<<<<" + id); } 

如果您正在使用.NET 4.0或更高版本并且正在寻找可以插入的预先存在的REST服务器解决方案(听起来就像这样),您可能需要查看Grapevine 。 您可以使用NuGet获取它, 项目维基有很多示例代码。 另外,它是开源的,所以如果你只是想看看它是如何实现的,你可以在那里看到所有的源代码。

您可以按路径信息(使用正则表达式)和请求方法(GET,POST等)过滤请求。

我是项目作者,我和你描述的那个人有类似的需求。 利用我在这里和其他地方找到的资源,我建立了Grapevine,这样每当我再次需要时,我就可以在后面的口袋中找到解决方案( DRY )。