gpt4 book ai didi

c# - 通过实现 IWsdlExporteExtension 来定义具有选择性端点的 WCF 服务 WSDL

转载 作者:太空宇宙 更新时间:2023-11-03 13:45:40 24 4
gpt4 key购买 nike

我有一个有两个端点的服务:

<service name="WcfService4.Service1">
<endpoint bindingConfiguration="myBinding"
contract="WcfService4.IService1"
binding="basicHttpBinding">
</endpoint>
<endpoint name="wsEndpoint"
contract="WcfService4.IService1"
binding="wsHttpBinding">
</endpoint>
<service>

此服务将由 Framework 2.0 和 4.0 客户端使用。从 2.0 客户端添加 Web 服务引用时,一切都很好。当我从 4.0 客户端添加服务引用时,会创建两个端点,使客户端指定它想要使用哪个端点。

我想要实现的是让用户可以选择下载服务的 basicHttpBinding 端点或 wsHttpBinding 端点,但不能同时下载,因此框架 4.0 客户端默认只有一个端点。

默认情况下,检索 wsdl 定义的路径是:

http://[server]:8080/MyApp/service.svc?wsdl

是否可以在另一个 url 上提供 wsdl 定义?

例如:

http://[server]:8080/service.svc/basic?wsdl
http://[server]:8080/service.svc/ws?wsdl

通过使用 IWsdlExportExtension 实现实现自定义端点行为,我可能会根据请求隐藏端点不被导出。

我想知道这是否可能,我的方法是否正确,或者我是否完全错误,或者这无法完成,或者我把事情复杂化了。谢谢

最佳答案

AFAIK 在 WSDL 导出扩展上,您没有收到发起 WSDL 创建过程的请求。但是您可以通过使用非 SOAP(也称为 REST)端点来公开 WSDL 来做到这一点。在此示例中,它只是向服务本身发送 HTTP 请求以获取 WSDL,然后“修剪”未请求的端点的结果 WSDL (XML)。

运行这段代码后,如果你运行

svcutil http://localhost:8000/service/conditionalwsdl/getwsdl?endpoint=basic

你只会得到带有 BasicHttpBinding 的端点,而如果你运行

svcutil http://localhost:8000/service/conditionalwsdl/getwsdl?endpoint=ws

您只能使用 WSHttpBinding 获取端点。

public class StackOverflow_15434117
{
[ServiceContract]
public interface ITest
{
[OperationContract]
string Echo(string text);
}
[ServiceContract]
public interface IConditionalMetadata
{
[WebGet]
XmlElement GetWSDL(string endpoint);
}
public class Service : ITest, IConditionalMetadata
{
public string Echo(string text)
{
return text;
}

public XmlElement GetWSDL(string endpoint)
{
WebClient c = new WebClient();
string baseAddress = OperationContext.Current.Host.BaseAddresses[0].ToString();
byte[] existingMetadata = c.DownloadData(baseAddress + "?wsdl");
XmlDocument doc = new XmlDocument();
doc.Load(new MemoryStream(existingMetadata));
XmlElement result = doc.DocumentElement;
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/");
nsManager.AddNamespace("soap11", "http://schemas.xmlsoap.org/wsdl/soap/");
nsManager.AddNamespace("soap12", "http://schemas.xmlsoap.org/wsdl/soap12/");

List<XmlNode> toRemove = new List<XmlNode>();

// Remove all SOAP 1.1 endpoints which are not the requested one
XmlNodeList toRemove11 = result.SelectNodes("//wsdl:service/wsdl:port/soap11:address", nsManager);
XmlNodeList toRemove12 = result.SelectNodes("//wsdl:service/wsdl:port/soap12:address", nsManager);
foreach (XmlNode node in toRemove11)
{
if (!node.Attributes["location"].Value.EndsWith(endpoint, StringComparison.OrdinalIgnoreCase))
{
toRemove.Add(node);
}
}

foreach (XmlNode node in toRemove12)
{
if (!node.Attributes["location"].Value.EndsWith(endpoint, StringComparison.OrdinalIgnoreCase))
{
toRemove.Add(node);
}
}

List<string> bindingsToRemove = new List<string>();
foreach (XmlNode node in toRemove)
{
string binding;
RemoveWsdlPort(node, out binding);
bindingsToRemove.Add(binding);
}

toRemove.Clear();
foreach (var binding in bindingsToRemove)
{
string[] parts = binding.Split(':');
foreach (XmlNode node in result.SelectNodes("//wsdl:binding[@name='" + parts[1] + "']", nsManager))
{
toRemove.Add(node);
}
}

foreach (XmlNode bindingNode in toRemove)
{
bindingNode.ParentNode.RemoveChild(bindingNode);
}

return result;
}

static void RemoveWsdlPort(XmlNode wsdlPortDescendant, out string binding)
{
while (wsdlPortDescendant.LocalName != "port" && wsdlPortDescendant.NamespaceURI != "http://schemas.xmlsoap.org/wsdl/")
{
wsdlPortDescendant = wsdlPortDescendant.ParentNode;
}

binding = wsdlPortDescendant.Attributes["binding"].Value;

var removed = wsdlPortDescendant.ParentNode.RemoveChild(wsdlPortDescendant);
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "basic");
host.AddServiceEndpoint(typeof(ITest), new WSHttpBinding(), "ws");
host.AddServiceEndpoint(typeof(IConditionalMetadata), new WebHttpBinding(), "conditionalWsdl")
.Behaviors.Add(new WebHttpBehavior());
host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });
host.Open();
Console.WriteLine("Host opened");

ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress + "/basic"));
ITest proxy = factory.CreateChannel();
Console.WriteLine(proxy.Echo("Hello"));

((IClientChannel)proxy).Close();
factory.Close();

Console.WriteLine("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

关于c# - 通过实现 IWsdlExporteExtension 来定义具有选择性端点的 WCF 服务 WSDL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15434117/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com