/SimpleWebDiscoveryInspector.cs
C# | 172 lines | 126 code | 27 blank | 19 comment | 10 complexity | 6664f5da37cecba23588565ce00ac9e0 MD5 | raw file
- // Copyright 2011 Microsoft Corporation
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
-
- using System;
- using System.Collections.Generic;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Description;
- using System.ServiceModel.Dispatcher;
- using System.Text;
- using System.Xml;
-
- namespace Microsoft.Data.Services.Client
- {
- class SimpleWebDiscoveryInspector : IDispatchMessageInspector
- {
- // Assume utf-8, note that Data Services supports
- // charset negotation, so this needs to be more
- // sophisticated (and per-request) if clients will
- // use multiple charsest
- private static Encoding encoding = Encoding.UTF8;
-
- private IDictionary<string, string[]> endpoints;
-
- private const string swdPath = "/$wellknown/simple-web-discovery";
-
- public SimpleWebDiscoveryInspector(IDictionary<string, string[]> endpoints)
- : base()
- {
- this.endpoints = endpoints;
- }
-
- #region IDispatchMessageInspector Members
-
- public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
- {
- if (request.Properties.ContainsKey("UriTemplateMatchResults"))
- {
- HttpRequestMessageProperty httpmsg = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
- UriTemplateMatch match = (UriTemplateMatch)request.Properties["UriTemplateMatchResults"];
-
- string pathAfterSvc = match.RequestUri.AbsolutePath.Replace(match.BaseUri.AbsolutePath, "");
- if (pathAfterSvc.Equals(swdPath))
- {
- httpmsg.Headers["Accept"] = "application/json";
-
- string service = match.QueryParameters["service"];
- if (this.endpoints.ContainsKey(service))
- {
- return this.endpoints[service];
- }
- }
- }
- return null;
- }
-
- public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
- {
- if (correlationState != null && correlationState is string[])
- {
- string[] addresses = correlationState as string[];
- string content = "{ \"locations\" : " + ToJsonArray(addresses) + " }";
-
- Message newreply = Message.CreateMessage(MessageVersion.None, "", new Writer(content));
- newreply.Properties["WebBodyFormatMessageProperty"] = new WebBodyFormatMessageProperty(WebContentFormat.Raw);
-
- HttpResponseMessageProperty prop = (HttpResponseMessageProperty)reply.Properties["httpResponse"];
- prop.StatusCode = System.Net.HttpStatusCode.OK;
- newreply.Properties["httpResponse"] = prop;
-
- reply = newreply;
- }
- }
-
- private string ToJsonArray(string[] array)
- {
- string content = "[ ";
- if (array.Length > 0)
- {
- content += "\"" + array[0] + "\"";
- for (int i = 1; i < array.Length; ++i)
- {
- content += ", \"" + array[i] + "\"";
- }
- }
- return content + " ]";
- }
-
- #endregion
-
- class Writer : BodyWriter
- {
- private string content;
-
- public Writer(string content)
- : base(false)
- {
- this.content = content;
- }
-
- protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
- {
- writer.WriteStartElement("Binary");
- byte[] buffer = SimpleWebDiscoveryInspector.encoding.GetBytes(this.content);
- writer.WriteBase64(buffer, 0, buffer.Length);
- writer.WriteEndElement();
- }
- }
- }
-
- // Simply apply this attribute to a DataService-derived class to allow
- // simple web discovery support in that service
- [AttributeUsage(AttributeTargets.Class)]
- public class SimpleWebDiscoveryBehaviorAttribute : Attribute, IServiceBehavior
- {
- private IDictionary<string, string[]> endpoints;
-
- public SimpleWebDiscoveryBehaviorAttribute(Type type) : base()
- {
- Endpoints endpointDictionary = (type.GetConstructor(new Type[] { }).Invoke(new object[] { })) as Endpoints;
- if (endpointDictionary == null)
- {
- throw new ArgumentException("Argument must be a subclass of the Endpoints class.");
- }
- endpoints = new Dictionary<string, string[]>();
- foreach (KeyValuePair<string, List<string>> p in endpointDictionary.EndpointDictionary)
- {
- this.endpoints[p.Key] = p.Value.ToArray();
- }
- }
-
- #region IServiceBehavior Members
-
- void IServiceBehavior.AddBindingParameters(
- ServiceDescription serviceDescription,
- ServiceHostBase serviceHostBase,
- System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints,
- System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
- {
- }
-
- void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
- {
- foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
- {
- foreach (EndpointDispatcher ed in cd.Endpoints)
- {
- ed.DispatchRuntime.MessageInspectors.Add(new SimpleWebDiscoveryInspector(this.endpoints));
- }
- }
- }
-
- void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
- {
- }
-
- #endregion
- }
-
- }