使用 C# HttpListener 映射 URL

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10017564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:08:59  来源:igfitidea点击:

URL mapping with C# HttpListener

c#httpurl-mapping

提问by emesx

In the code below I'm waiting for any call to the 8080 port.

在下面的代码中,我正在等待对 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();
  }
}

Is it possible to map specific URL patterns to different behaviour? I want achieve a REST-style server i.e. a call to localhost:8080/person/1will launch getPersonHandler(int)

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

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

The Mappingsyntax is just my own wishful analogy to JAX-RS libraries that I know. I'd like to do the same in C# (desktop C#, not asp)

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

采纳答案by L.B

You can get a similar effect without attributes

没有属性也可以得到类似的效果

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);
    });

Usage would be:

用法是:

http://localhost:8080/getPersonHandler/333

if you really want to use Attributes then

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

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);
    });
}

Then you can use as http://localhost:8080/Person/333and your definitions would be

然后你可以使用 ashttp://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);
}

回答by Scott Offen

If you are working in .NET 4.0 or higher and looking for a pre-existing REST server solution that you can plug into (which it sounds like you are), you might want to check out Grapevine. You can get it using NuGet, and the project wikihas lots of sample code. Plus, it is open source, so if you just wanted to see how it can be accomplished, you can see all the source code there.

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

You can filter requests by path info (using regular expressions) and request methods (GET, POST, etc.).

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

I am the project author, and I had a similar need as the one you described. Using resources I found here and elsewhere, I built Grapevine so that I would have a solution in my back pocket whenever I needed it again (DRY).

我是项目的作者,我和你描述的有类似的需求。使用我在这里和其他地方找到的资源,我构建了 Grapevine,这样当我再次需要它时,我的后口袋里就有一个解决方案 ( DRY)。