从 WCF 测试客户端调用时,WebBrowser 控件未在自承载 WCF 服务中导航

WebBrower control is not navigating in self-hosted WCF service when called from WCF test client

我在 WinForms 项目中托管了一个简单的 WCF 服务。我正在尝试更新 WebBrowser 控件以导航到服务接收到的指定 url。

namespace DocumentViewer
{
    public partial class FormMain : Form, IDocumentViewerService
    {
        private WfcServiceManager _service = new WfcServiceManager();

        public FormMain()
        {
            InitializeComponent();

            this.Load += FormMain_Load;
        }

        void FormMain_Load(object sender, EventArgs e)
        {
            _service.Start();

            webBrowser1.Navigate("http://www.example1.com");
        }

        public void ShowDocumentPreview(string path)
        {
            webBrowser1.Navigate("http://www.example2.com");
        }
    }
}

应用加载后,它会按预期成功导航到 www。example1.com。

当我通过 WCF 测试客户端发送请求并在 ShowDocumentPreview(string path) 上放置断点时,该方法被命中但 WebBrowser 控件没有导航到 www。example2.com

知道这里的问题是什么吗?

服务代码:

namespace DocumentViewer
{
    [ServiceContract]
    public interface IDocumentViewerService
    {
        [OperationContract]
        void ShowDocumentPreview(string path);
    }
}

namespace DocumentViewer
{
    public class WfcServiceManager
    {
        private Uri baseAddress = new Uri("http://localhost:30303/DocumentViewerService");

        private ServiceHost _host;

        public void Start()
        {
            _host = new ServiceHost(typeof(FormMain), baseAddress);

            // Enable metadata publishing.
            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            _host.Description.Behaviors.Add(smb);

            _host.Open();
        }

        public void Stop()
        {
            if (_host != null)
            {
                _host.Close();
                _host = null;
            }
        }
    }
}

注意:我使用 WCF 的原因是因为 WebBrowser 控件是 32 位的,而我正在开发的主要应用程序需要是 64 位的,所以我想出的解决方案是有一个单独的带有 WebBrowser 控件的 32 位应用程序和 64 位应用程序通过 WCF 将 url 发送到 WebBrowser 控件。

首先,首先,运行在 WCF 服务中设置 WebBrowser 控件实例并不是一个好主意。它不能很好地扩展并且具有安全隐患。 WebBrowser 控件从未用于服务器端使用。您可能想看看一些替代方案,例如 PhantonJS.

也就是说,如果您仍想在 WCF 服务环境(或只是一个控制台应用程序)中使用 WebBrowser,则需要创建 运行 WebBrowser 的实例在泵送 windows 消息的 STA 线程中。目前您不这样做,这就是导航不起作用的原因。你可以使用我的 MessageLoopApartment 来自 this related answer.

另请注意,WebBrowser控件有 32 位和 64 位版本,与 Internet Explorer 本身相同。将您的 .NET 编译为 64 位,将使用 64 位版本的 WebBrowser ActiveX 控件。