c# - 使用 HttpWebRequest 连接 Azure 服务总线中继(WCF 终结点)

标签 c# wcf rest azure azureservicebus

请帮忙。我试图使用 HttpWebRequest 访问暴露给服务总线中继端点的 WCF 服务。

我通过 OAuth WRAP 协议(protocol)成功从 ACS 获取了 token 。使用该 token 作为请求 header 中的授权,我创建了一个 WebRequest 来与 WCF 服务进行通信,其中端点配置为 WebHttpRelayBinding,并应用了 OperationContractAttribute 和 WebGetAttribute 的 WCF 服务方法。

当我运行客户端应用程序时,出现以下错误:

The message with To 'https://namespace.servicebus.windows.net/Student/GetInfo/GetStudentInfo/1' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.

我在谷歌上搜索并找到了将以下属性应用于服务类的建议:

[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]

虽然这解决了之前的错误,但现在客户端应用程序最终出现以下错误:

The message with Action 'GET' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).

我认为我在 WCF 服务方面遗漏了一些东西。共享客户端和服务代码以供您审阅。

WCF 服务代码:

[ServiceContract]
interface IStudentInfo
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "/GetStudentInfo/{studentId}")]
    string GetStudentInfo(string studentId);
}

        [ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
        private class StudentInfo : IStudentInfo
        {
            string IStudentInfo.GetStudentInfo(string studentId)
            {
                string returnString = null;

                // .....

                return returnString;
            }
        }

        public void Run()
        {
            Console.WriteLine("LISTENER");
            Console.WriteLine("========");

            string serviceNamespace = "namespace";
            string issuerName = "owner";
            string issuerKey = "key";
            string servicePath = "Student/GetInfo";

            ServiceHost sh = new ServiceHost(typeof(StudentInfo));

            // Binding
            WebHttpRelayBinding binding2 = new WebHttpRelayBinding();

            Uri uri = ServiceBusEnvironment.CreateServiceUri(Uri.UriSchemeHttps, serviceNamespace, servicePath);
            Console.WriteLine("Service Uri: " + uri);
            Console.WriteLine();

            sh.AddServiceEndpoint(typeof(IStudentInfo), binding2, uri);

            // Create the ServiceRegistrySettings behavior for the endpoint.
            var serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);

            // Create the shared secret credentials object for the endpoint matching the 
            // Azure access control services issuer 
            var sharedSecretServiceBusCredential = new TransportClientEndpointBehavior()
            {
                TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerKey)
            };

            // Add the service bus credentials to all endpoints specified in configuration.
            foreach (var endpoint in sh.Description.Endpoints)
            {
                endpoint.Behaviors.Add(serviceRegistrySettings);
                endpoint.Behaviors.Add(sharedSecretServiceBusCredential);
            }

            sh.Open();

            Console.WriteLine("Press ENTER to close");
            Console.ReadLine();

            sh.Close();
        }

服务消费代码:

    static void Main(string[] args)
    {
        var studentId = "1";

        string _token = GetToken();
        Console.WriteLine(_token);

        // Create and configure the Request
        var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://namespace.servicebus.windows.net/Student/GetInfo/GetStudentInfo/" + studentId);
        httpWebRequest.ContentType = "text/json";
        httpWebRequest.Method = "GET";
        httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, string.Format("WRAP access_token=\"{0}\"", _token));

        // Get the response using the Request
        HttpWebResponse response = httpWebRequest.GetResponse() as HttpWebResponse;

        // Read the stream from the response object
        Stream stream = response.GetResponseStream();
        StreamReader reader = new StreamReader(stream);

        // Read the result from the stream reader
        string result = reader.ReadToEnd();

        Console.WriteLine("Result: " + result);

        Console.ReadLine();
    }

    static string GetToken()
    {
        string base_address = string.Format("https://namespace-sb.accesscontrol.windows.net");
        string wrap_name = "owner";
        string wrap_password = "key";
        string wrap_scope = "http://namespace.servicebus.windows.net/";

        WebClient client = new WebClient();
        client.BaseAddress = base_address;

        NameValueCollection values = new NameValueCollection();
        values.Add("wrap_name", wrap_name);
        values.Add("wrap_password", wrap_password);
        values.Add("wrap_scope", wrap_scope);

        byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
        string response = Encoding.UTF8.GetString(responseBytes);

        string token = response.Split('&')
         .Single(value => value.StartsWith("wrap_access_token="))
         .Split('=')[1];

        string _token = HttpUtility.UrlDecode(token);

        return _token;
    }

最佳答案

终于完成了!

我缺少将 WCF 服务公开为 REST 端点所需的端点的​​ WebHttpBehavior

endpoint.Behaviors.Add(new WebHttpBehavior());

或者,我可以在 WebServiceHost 中托管一个服务,而不是“ServiceHost”,以使 REST 绑定(bind)能够正常工作。

WebServiceHost sh = new WebServiceHost(typeof(StudentInfo));

关于c# - 使用 HttpWebRequest 连接 Azure 服务总线中继(WCF 终结点),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37215416/

相关文章:

c# - 具有可为空总和的 Linq 查询

c# - 将不同的方法/函数传递给后台工作人员的 DoWork 事件

c# - 找不到引用契约(Contract)的默认端点元素 - 托管 wcf

javascript - 在 JavaScript 中进行 REST 调用而不使用 JSON?

rest - 如何在 REST API 中表示实际上不是资源的函数?

java - 通信选项 : Android client- Java server

c# - 弹性视频编解码器(断电)

c# - 使用 Clipboard.SetData() 放入剪贴板的内容的第一个字节和最后一个字节是什么意思?

.net - 无法使用Web Service Studio客户端获取WCF服务的操作列表

wcf idispatchmessageinspector BeforeSendReply 未调用