2 // MetadataExchangeClient.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
6 // Ankit Jain <jankit@novell.com>
8 // Copyright (C) 2005 Novell, Inc. http://www.novell.com
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.ServiceModel;
33 using System.ServiceModel.Channels;
34 using System.ServiceModel.Description;
35 using System.Web.Services.Description;
36 using System.Web.Services.Discovery;
37 using System.Web.Services.Protocols;
39 using System.Xml.Serialization;
44 using SMBinding = System.ServiceModel.Channels.Binding;
45 using SMMessage = System.ServiceModel.Channels.Message;
47 namespace System.ServiceModel.Description
49 public class MetadataExchangeClient
53 EndpointAddress address;
55 MetadataExchangeClientMode mode = MetadataExchangeClientMode.MetadataExchange;
59 [MonoTODO ("use empty configuration")]
60 public MetadataExchangeClient ()
64 public MetadataExchangeClient (SMBinding mexBinding)
69 public MetadataExchangeClient (EndpointAddress address)
71 this.address = address;
74 public MetadataExchangeClient (string endpointConfigurationName)
76 throw new NotImplementedException ();
79 [MonoTODO ("MetadataExchangeClientMode is not considered")]
80 public MetadataExchangeClient (Uri address, MetadataExchangeClientMode mode)
82 this.address = new EndpointAddress (address.AbsoluteUri);
87 public ICredentials HttpCredentials { get; set; }
89 public int MaximumResolvedReferences { get; set; }
91 public TimeSpan OperationTimeout { get; set; }
94 public bool ResolveMetadataReferences { get; set; }
96 public ClientCredentials SoapCredentials { get; set; }
98 [MonoTODO ("use dialect and identifier (but how?)")]
99 protected internal virtual ChannelFactory<IMetadataExchange> GetChannelFactory (EndpointAddress metadataAddress, string dialect, string identifier)
101 var se = new ServiceEndpoint (ContractDescription.GetContract (typeof (IMetadataExchange)), CreateBinding (metadataAddress), metadataAddress);
102 if (SoapCredentials != null) {
103 se.Behaviors.RemoveAll<ClientCredentials> ();
104 se.Behaviors.Add (SoapCredentials);
106 return new ChannelFactory<IMetadataExchange> (se);
110 protected internal virtual HttpWebRequest GetWebRequest (Uri location, string dialect, string identifier)
112 throw new NotImplementedException ();
115 SMBinding CreateBinding (EndpointAddress address)
117 return address.Uri.Scheme == Uri.UriSchemeHttps ?
118 MetadataExchangeBindings.CreateMexHttpsBinding () :
119 MetadataExchangeBindings.CreateMexHttpBinding ();
124 public MetadataSet GetMetadata ()
126 return GetMetadata (address);
129 public MetadataSet GetMetadata (EndpointAddress address)
131 //FIXME: default mode?
132 return GetMetadataInternal (address, mode);
135 public MetadataSet GetMetadata (Uri address, MetadataExchangeClientMode mode)
137 return GetMetadataInternal (new EndpointAddress (address.AbsoluteUri), mode);
140 internal MetadataSet GetMetadataInternal (EndpointAddress address, MetadataExchangeClientMode mode)
142 // FIXME: give dialect and identifier
143 var cf = GetChannelFactory (address, null, null);
145 var proxy = cf.CreateChannel ();
146 var asClientChannel = proxy as IClientChannel;
147 if (asClientChannel == null)
148 throw new InvalidOperationException ("The channel factory must return an IClientChannel implementation");
149 asClientChannel.OperationTimeout = OperationTimeout;
150 asClientChannel.Open ();
152 SMMessage msg = SMMessage.CreateMessage (
153 MessageVersion.Soap12WSAddressing10,
154 "http://schemas.xmlsoap.org/ws/2004/09/transfer/Get");
156 msg.Headers.ReplyTo = new EndpointAddress (
157 "http://www.w3.org/2005/08/addressing/anonymous");
158 //msg.Headers.From = new EndpointAddress ("http://localhost");
159 msg.Headers.To = address.Uri;
160 msg.Headers.MessageId = new UniqueId ();
164 ret = proxy.Get (msg);
165 } catch (Exception e) {
166 throw new InvalidOperationException (
167 "Metadata contains a reference that cannot be resolved : " + address.Uri.AbsoluteUri, e);
170 return MetadataSet.ReadFrom (ret.GetReaderAtBodyContents ());
175 Func<Func<MetadataSet>,MetadataSet> getter;
177 void PrepareGetter ()
180 getter = new Func<Func<MetadataSet>,MetadataSet> (GetMetadata);
183 public MetadataSet EndGetMetadata (IAsyncResult result)
185 return getter.EndInvoke (result);
188 MetadataSet GetMetadata (Func<MetadataSet> func)
193 public IAsyncResult BeginGetMetadata (AsyncCallback callback, object asyncState)
196 return getter.BeginInvoke (() => GetMetadata (), callback, asyncState);
199 public IAsyncResult BeginGetMetadata (EndpointAddress address, AsyncCallback callback, object asyncState)
202 return getter.BeginInvoke (() => GetMetadata (address), callback, asyncState);
205 public IAsyncResult BeginGetMetadata (Uri address, MetadataExchangeClientMode mode, AsyncCallback callback, object asyncState)
208 return getter.BeginInvoke (() => GetMetadata (address, mode), callback, asyncState);
212 interface IMetadataExchangeClient : IMetadataExchange, IClientChannel