Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Azure中继服务总线,带有webHttpRelayBinding和REST/JSON和POST_C#_Wcf_Tcp_Https_Azure Servicebusrelay - Fatal编程技术网

C# Azure中继服务总线,带有webHttpRelayBinding和REST/JSON和POST

C# Azure中继服务总线,带有webHttpRelayBinding和REST/JSON和POST,c#,wcf,tcp,https,azure-servicebusrelay,C#,Wcf,Tcp,Https,Azure Servicebusrelay,下面的文章解释了如何使用Azure中继服务总线构建简单的WCF服务: 该示例显示了如何使用TCP绑定。我复制了它,它工作得完美无缺。现在,我希望webHttpRelayBinding也能做到这一点,但它不能像预期的那样工作。 我将代码拆分为公共dll、WCFServiceWebRole项目、命令行主机(作为web.config的替代)和客户端中的服务: 带有接口定义的公共dll和带有总线密钥、命名空间和协议(tcp或http)的设置文件 名称空间wcfrelaycomon { 使用System.

下面的文章解释了如何使用Azure中继服务总线构建简单的WCF服务: 该示例显示了如何使用TCP绑定。我复制了它,它工作得完美无缺。现在,我希望webHttpRelayBinding也能做到这一点,但它不能像预期的那样工作。 我将代码拆分为公共dll、WCFServiceWebRole项目、命令行主机(作为web.config的替代)和客户端中的服务:

带有接口定义的公共dll和带有总线密钥、命名空间和协议(tcp或http)的设置文件 名称空间wcfrelaycomon { 使用System.ServiceModel; 使用System.ServiceModel.Web

    [ServiceContract(Namespace = "urn:ps")]
    public interface IProblemSolver
    {
        [OperationContract
        WebInvoke(UriTemplate = "/solver", Method = "POST",
            RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped)]
        int AddNumbers(int a, int b);
    }

    public interface IProblemSolverChannel : IProblemSolver, IClientChannel { }

    public enum BusProtocol { tcp, http };

    public class Utils
    {   
        public static BusProtocol Protocol
        {
            get
            {
                BusProtocol mode;
                if (!Enum.TryParse(AzureSettings.Default.Protocol, out mode))
                {
                    throw new ArgumentException("wrong input, exiting");
                }
                return mode;
            }
        }
    }
}
WCFServiceWebRole项目。我首先在Web.config中定义了所有服务设置(行为、出价),因此应该是自给自足的

namespace WCFServiceWebRoleRelay
{
    public class ProblemSolver : WCFRelayCommon.IProblemSolver
    {
        public int AddNumbers(int a, int b)
        {
            return a + b;
        }
    }
}
但是我还定义了一个替代的主机项目,它通过代码进行所有设置,更易于调试,所以只需要使用设置文件的命令行项目。 2种实现:使用NetCPRelayBinding或WebHttpRelayBinding。使用安全传输

namespace WCFRelayHost
{
    class Program
    {
        static void Main(string[] args)
        {
            var transportClientEndpointBehavior = new TransportClientEndpointBehavior
            {
                TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", AzureSettings.Default.BusKey)
            };

            ServiceHost sh;
            switch (Utils.Protocol)
            {
                case BusProtocol.http:
                    sh = CreateWebHost(AzureSettings.Default.BusNamespace, transportClientEndpointBehavior);
                    break;
                case BusProtocol.tcp:
                    sh = CreateTcpBindingHost(AzureSettings.Default.BusNamespace, transportClientEndpointBehavior);
                    break;
                default:
                    throw new Exception("wrong mode");
            }
            sh.Open();
            Console.WriteLine("Press ENTER to close");
            Console.ReadLine();
            sh.Close();
        }

        static ServiceHost CreateTcpBindingHost(string busNamespace, TransportClientEndpointBehavior transportClientEndpointBehavior)
        {
            Uri tcpAddress = ServiceBusEnvironment.CreateServiceUri("sb", busNamespace, "solver");
            ServiceHost sh = new ServiceHost(typeof(ProblemSolver));            
            var binding = new NetTcpRelayBinding(EndToEndSecurityMode.Transport, new RelayClientAuthenticationType());            
            return AddServiceEndpoint(sh, binding, tcpAddress, transportClientEndpointBehavior);
        }

        static ServiceHost CreateWebHost(string busNamespace, TransportClientEndpointBehavior transportClientEndpointBehavior)
        {
            // https://<namespace>.servicebus.windows.net/solver
            Uri webAddress = ServiceBusEnvironment.CreateServiceUri("https", busNamespace, "solver");
            var binding = new WebHttpRelayBinding(EndToEndWebHttpSecurityMode.Transport, new RelayClientAuthenticationType());
            WebServiceHost wsh = new WebServiceHost(typeof(ProblemSolver), webAddress);
            return AddServiceEndpoint(wsh, binding, webAddress, transportClientEndpointBehavior);
        }

        static ServiceHost AddServiceEndpoint(ServiceHost sh, Binding binding, Uri uri, TransportClientEndpointBehavior transportClientEndpointBehavior)
        {
            sh.AddServiceEndpoint(typeof(IProblemSolver), binding, uri).Behaviors.Add(transportClientEndpointBehavior);            
            return sh;
        }
    }
}
我错过了什么?
可能是Azure门户上的一些配置?我只是按照教程中的说明进行操作…

我可以通过更改
WCFRelayClient.Program.CreateChannel
方法,使您的示例在处理WebHttpBinding/WebHttpRelayBinding时使用
WebChannelFactory

static IProblemSolverChannel CreateChannel(Binding binding, Uri uri, TransportClientEndpointBehavior transportClientEndpointBehavior)
{
    ChannelFactory<IProblemSolverChannel> cf;
    if (binding is WebHttpBinding || binding is WebHttpRelayBinding)
    {
        cf = new WebChannelFactory<IProblemSolverChannel>(binding, uri);
    }
    else
    {
        cf = new ChannelFactory<IProblemSolverChannel>(binding, new EndpointAddress(uri));
    }

    cf.Endpoint.Behaviors.Add(transportClientEndpointBehavior);
    return cf.CreateChannel();
}
静态IProbleSolverChannel CreateChannel(绑定绑定、Uri Uri、TransportClientEndpointBehavior TransportClientEndpointBehavior)
{
信道工厂cf;
if(绑定是WebHttpBinding | |绑定是WebHttpRelayBinding)
{
cf=新的WebChannelFactory(绑定,uri);
}
其他的
{
cf=新的ChannelFactory(绑定,新的端点地址(uri));
}
cf.Endpoint.Behaviors.Add(transportClientEndpointBehavior);
返回cf.CreateChannel();
}
如果使用*HttpRelayBinding以外的HTTP客户端发送,并且中继端点需要客户端身份验证,则需要构建SAS令牌并将授权放入HTTP授权头中

NodeJs、JAVA、PHP、C#关于如何构建SAS令牌的示例和一般说明:

此页面似乎有一个Javascript示例(我尚未验证它是否有效):

在另一个项目中,我成功地使用了带有GET方法的webHttpRelayBinding,但仍然没有使用POST方法。好极了,WebChannelFactory确实是缺失的一点!很明显,我的CreateChannel方法不再那么有意义了,我将ChannelFactory调用直接放在上面的方法中。但是,由于答案是替换了ex实际上我的方法错了!使用WebChannelFactory很有意义。我还想知道ch.addNumber(第一,第二)是如何使用的方法在http示例中处理JSON。现在我知道它是由WebChannelFactory完成的!我只通过配置文件实现了同样的目标:可能有许多客户端端点,但只有一个具有完整地址的服务主机。下一步:如果我只使用浏览器REST客户端,如Chrome中的ARC/“Advanced REST client”,我应该如何“编码”JSON中的azure总线密钥?还是应该将其放在请求uri中?
System.InvalidOperationException was unhandled
HResult=-2146233079
  Message=Manual addressing is enabled on this factory, so all messages sent must be pre-addressed.
  Source=mscorlib
static IProblemSolverChannel CreateChannel(Binding binding, Uri uri, TransportClientEndpointBehavior transportClientEndpointBehavior)
{
    ChannelFactory<IProblemSolverChannel> cf;
    if (binding is WebHttpBinding || binding is WebHttpRelayBinding)
    {
        cf = new WebChannelFactory<IProblemSolverChannel>(binding, uri);
    }
    else
    {
        cf = new ChannelFactory<IProblemSolverChannel>(binding, new EndpointAddress(uri));
    }

    cf.Endpoint.Behaviors.Add(transportClientEndpointBehavior);
    return cf.CreateChannel();
}