URL-Zuordnung mit C # HttpListener

Im Code unten warte ich auf einen Anruf an den 8080-Port.

<code>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();
  }
}
</code>

Ist es möglich, bestimmte URL-Muster einem anderen Verhalten zuzuordnen? Ich möchte einen Server im REST-Stil erreichen, d. H. Einen Anruf anlocalhost: 8080 / Person / 1 startet getPersonHandler (int)

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

DasMapping Syntax ist nur meine eigene Wunschanalogie zu JAX-RS-Bibliotheken, die ich kenne. Ich möchte dasselbe in C # tun (Desktop C #, nicht asp)

 emesx19. Apr. 2012, 13:57
in einer ausführbaren Datei?
 Scott Offen29. Okt. 2014, 18:37
Wenn sich die ASP.NET-Web-API in einer ausführbaren Datei selbst hosten kann, würde ich das gerne sehen! (Ich sage nicht, dass es nicht geht, nur dass ich nicht weiß, dass es geht).
 dcstraw18. Apr. 2012, 23:46
Zur Info: ASP.NET-Web-API kann selbst gehostet werden (kein IIS)
 emesx04. Apr. 2012, 21:53
Ich benötige eine eigenständige Anwendung.
 Sam Axe04. Apr. 2012, 21:35
Müssen Sie das Rad wirklich neu erfinden? Die Web-API in ASP.NET MVC 4 kann dies tun.
 Ian Mercer07. Nov. 2014, 21:18
Verwenden Sie OWIN, um sich selbst zu hosten:asp.net/web-api/overview/hosting-aspnet-web-api/…

Antworten auf die Frage(2)

Lösung für das Problem

Sie können einen ähnlichen Effekt ohne Attribute erzielen

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

Verwendung wäre:

<code>http://localhost:8080/getPersonHandler/333
</code>

Wenn Sie wirklich Attribute verwenden möchten, dann

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

Dann können Sie als verwendenhttp://localhost:8080/Person/333 und deine Definitionen wären

<code>class Mapping : Attribute
{
    public string Map;
    public Mapping(string s)
    {
        Map = s;
    }
}

[Mapping("Person")]
public void getPersonHandler(int id)
{
    Console.WriteLine("<<<<" + id);
}
</code>
 L.B04. Apr. 2012, 21:56
schon seitparams ist reserviertes Wort in c #, das ich verwendet habe@params
 emesx05. Apr. 2012, 17:12
Eine letzte Sache: Können Sie auch nach Anfragetyp filtern (GET, PUT ...)?
 L.B05. Apr. 2012, 18:58
@elmesctx.Request.HttpMethod
 emesx04. Apr. 2012, 21:55
Was ist das für ein @param-Variablenname?
 emesx04. Apr. 2012, 21:57
Ich wusste nicht, dass du es benutzen kannst@ in Variablennamen, danke. Ich mag diese Antwort. Vielen Dank.

denen REST-Serverlösung suchen, in die Sie eine Verbindung herstellen können (so wie es sich anhört), möchten Sie dies möglicherweise überprüfenWeinrebe. Sie können es mit NuGet erhalten, und dieProjekt-Wiki hat viele Beispielcode. Außerdem handelt es sich um Open Source. Wenn Sie also nur sehen möchten, wie dies erreicht werden kann, können Sie den gesamten Quellcode dort anzeigen.

Sie können Anforderungen nach Pfadinformationen (mit regulären Ausdrücken) und Anforderungsmethoden (GET, POST usw.) filtern.

Ich bin der Projektautor und hatte ein ähnliches Bedürfnis wie das, das Sie beschrieben haben. Mit den Ressourcen, die ich hier und anderswo gefunden habe, habe ich Grapevine so gebaut, dass ich immer eine Lösung in der Hosentasche habe, wenn ich sie wieder brauche (TROCKEN).

 Luke20. März 2017, 13:28
Wow, es ist großartig, danke!
 Shukri Adams02. Mai 2019, 13:04
Nettes Projekt - Ich musste eine REST-API in eine Befehlszeilenanwendung einfügen, und Grapevine war viel sauberer als die Standardklasse HttpListener in C #.

Ihre Antwort auf die Frage