Skip to main content
 首页 » 编程设计

c#之自托管 Web Api C# 与 Windows 窗体错误

2024年02月13日108lautakyan007

我拿了一个示例项目webapi Self Hosting,微软的页面。 webapi正常启动,但是访问地址的时候报如下错误。我正在使用 VS2010 和 Windows 窗体。控制台应用程序正常工作,而 Windows 窗体不工作。

程序代码:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Web.Http.SelfHost; 
using System.Web.Http; 
using System.Net.Http; 
 
namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
 
        HttpSelfHostServer server; 
        HttpSelfHostConfiguration config; 
 
        public Form1() 
        { 
            InitializeComponent(); 
        } 
 
        private void button1_Click(object sender, EventArgs e) 
        { 
 
            var config = new HttpSelfHostConfiguration("http://localhost:9090"); 
 
            config.Routes.MapHttpRoute( 
                "API Default", "api/{controller}/{id}", 
                new { id = RouteParameter.Optional }); 
 
            using (HttpSelfHostServer server = new HttpSelfHostServer(config)) 
            { 
                server.OpenAsync().Wait(); 
            } 
        } 
 
        private void button2_Click(object sender, EventArgs e) 
        { 
            HttpClient client = new HttpClient(); 
            client.BaseAddress = new Uri("http://localhost:9090"); 
 
            //Console.WriteLine("Products in '{0}':", category); 
 
            string query = string.Format("api/products?category={0}", "testes"); 
 
            var resp = client.GetAsync(query).Result; 
            //resp.EnsureSuccessStatusCode(); 
 
            var products = resp.Content.ReadAsAsync<string>().Result; 
            MessageBox.Show(products); 
        } 
    } 
} 

Controller :

namespace SelfHost 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Net; 
    using System.Web.Http; 
 
 
    public class ProductsController : ApiController 
    { 
 
        public string GetProductsByCategory(string category) 
        { 
            return (category ?? "Vazio"); 
        } 
    } 
} 

错误:

This XML file does not appear to have any style information associated with it. The document tree is shown below. 
<Error> 
<Message>An error has occurred.</Message> 
<ExceptionMessage> 
Object reference not set to an instance of an object. 
</ExceptionMessage> 
<ExceptionType>System.NullReferenceException</ExceptionType> 
<StackTrace> 
at System.Web.Http.SelfHost.HttpSelfHostServer.ProcessRequestContext(ChannelContext channelContext, RequestContext requestContext) 
</StackTrace> 
</Error> 

请您参考如下方法:

我看到您的代码有很多错误,但我认为我无法将它们全部包含在评论中。也许如果你修复它们 - 这个异常就会消失。

问题:

  1. 在这段代码 server.OpenAsync().Wait(); 之后,您调用 server 上的 Dispose 方法(因为您将所有内容包装在 using 语句中)。这意味着当 OpenAsync 完成时(并且此任务将在服务器运行时完成)- 紧接着您将关闭服务器。

  2. 当您在任务上调用 Wait 时,您在主线程上遇到了一堆死锁。查看这篇文章http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx对此。

这是我尝试重写您的示例以解决这两个问题:

public partial class Form1 : Form 
{ 
    HttpSelfHostServer server; 
    HttpSelfHostConfiguration config; 
 
    public Form1() 
    { 
        InitializeComponent(); 
    } 
 
    private async void button1_Click(object sender, EventArgs e) 
    { 
        config = new HttpSelfHostConfiguration("http://localhost:9090"); 
 
        config.Routes.MapHttpRoute( 
            "API Default", "api/{controller}/{id}", 
            new { id = RouteParameter.Optional }); 
 
        HttpSelfHostServer server = new HttpSelfHostServer(config); 
        await server.OpenAsync(); 
        // Server is running: you can show something to user like - it is running 
        MessageBox.Show("Server is ready!"); 
    } 
 
    private async void button2_Click(object sender, EventArgs e) 
    { 
        HttpClient client = new HttpClient(); 
        client.BaseAddress = new Uri("http://localhost:9090"); 
 
        string query = string.Format("api/products?category={0}", "testes"); 
 
        var resp = await client.GetAsync(query); 
 
        var products = await resp.Content.ReadAsAsync<string>(); 
        MessageBox.Show(products); 
    } 
}