/// <summary> /// Close the connection /// </summary> public void Close() { #if WINDOWS_PHONE wcfClient.Abort(); #else wcfConfiguration = null; wcfClient.Close(); #endif }
public System.ServiceModel.Channels.Message ProcessInboundMessage(System.ServiceModel.Channels.Message m) { #if DEBUG Trace.TraceInformation("Received message on transport..."); #endif if (ListenConnector == null && OperationContext.Current.Host is WcfServiceHost) { ListenConnector = (OperationContext.Current.Host as WcfServiceHost).ConnectorHost; } if (ListenConnector != null) // In process { // Is this channel one way or two way? if (!(OperationContext.Current.Channel is IOutputChannel)) // Input only { return(null); } #if DEBUG Trace.TraceInformation("Message handoff to WcfServerConnector completed"); #endif WcfSendResult processResult = ListenConnector.ProcessMessage(m); Message retVal = null; // There is an error, so the return value must be a fault! if (processResult == null || processResult.Code != ResultCode.Accepted && processResult.Code != ResultCode.AcceptedNonConformant) { // Web based context? if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError; WebOperationContext.Current.OutgoingResponse.StatusDescription = "Internal Server Error"; } List <String> details = new List <string>(); if (processResult != null) { details = new List <String>(); foreach (var dtl in processResult.Details) { details.Add(dtl.Message); // Append details } } if (processResult == null) { retVal = Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateReceiverFaultCode(processResult.Code.ToString(), "http://marc.mohawkcollege.ca/hi"), new FaultReason("The receiver has constructed an invalid response that cannot be sent to the sender"), details), m.Headers.Action); } else { retVal = Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateSenderFaultCode("EPIC", "http://marc.mohawkcollege.ca/hi"), new FaultReason("Catastrophic failure occurred in the WcfServer send pipeline. This usually occurs when the connector does not receive a message in the allocated amount of time"), details), m.Headers.Action); } } else { retVal = processResult.Message; if (processResult.Headers != null) { retVal.Headers.Clear(); retVal.Headers.CopyHeadersFrom(processResult.Headers); } } #if DEBUG Trace.TraceInformation("Message sent to client"); #endif return(retVal); } else { // Get settings if (settings == null) { settings = System.Web.Configuration.WebConfigurationManager.GetSection("marc.everest.connectors.wcf") as MARC.Everest.Connectors.WCF.Configuration.ConfigurationSection; } // Now format the message and pass it on ... MemoryStream ms = new MemoryStream(); System.Xml.XmlWriter xw = System.Xml.XmlWriter.Create(ms); // Write to message memory stream for classification matching m.WriteMessage(xw); xw.Flush(); // Flush the Xml Writer ms.Seek(0, SeekOrigin.Begin); // Seek to start XPathDocument xpd = new XPathDocument(ms); // load xpath document XPathNavigator xpn = xpd.CreateNavigator(); IMessageReceiver receiver = null; // The receiver to use // Determine the receiver foreach (KeyValuePair <String, IMessageReceiver> kv in settings.Receiver) { if (xpn.SelectSingleNode(kv.Key) != null) { receiver = kv.Value; break; } } // Was a receiver found? if (receiver == null) { // Create a not implemented exception if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotImplemented; } return(Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateSenderFaultCode( "NotImplemented", "http://marc.mohawkcollege.ca/hi"), new FaultReason("No receiver understands the request message.")), m.Headers.Action)); } // Create a streams for deserialization ms = new MemoryStream(); XmlWriterSettings xws = new XmlWriterSettings(); xws.Indent = true; xw = XmlWriter.Create(ms, xws); // Deserialize body WcfReceiveResult rcv = new WcfReceiveResult(); try { // Because of classification, we need to process this in a wierd way, // Basically the formatter will classify the message based on the root element name // it receives. Because a SOAP message's root isn't what we really want to process, // the first child node under the 'body' must be passed to the xml writer xpn.SelectSingleNode("//*[local-name() = 'Body']/child::node()").WriteSubtree(xw); xw.Flush(); ms.Seek(0, SeekOrigin.Begin); var serResult = settings.Formatter.Parse(ms); rcv.Structure = serResult.Structure; rcv.Details = serResult.Details; if (rcv.Details.Count() == 0) { rcv.Code = ResultCode.Accepted; } else { rcv.Code = ResultCode.AcceptedNonConformant; } } catch (Exception e) { rcv.Code = ResultCode.Error; rcv.Details = new IResultDetail[] { new ResultDetail(ResultDetailType.Error, e.Message, e) }; } // Process on the receiver IGraphable obj = receiver.MessageReceived(rcv.Structure, rcv.Code, rcv.Details); // Graph this back XmlSerializerSurrogate surrogate = new XmlSerializerSurrogate((IXmlStructureFormatter)settings.Formatter); // Serialize the response Message result = Message.CreateMessage(m.Version, m.Headers.Action, obj, surrogate); // Validate surrogate.WriteObject(new MemoryStream(), obj); // Surrogate result code is acceptable? if (surrogate.ResultCode != ResultCode.Accepted && surrogate.ResultCode != ResultCode.AcceptedNonConformant) { if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError; WebOperationContext.Current.OutgoingResponse.StatusDescription = "Internal Server Error"; } List <string> details = new List <String>(); foreach (var itm in surrogate.Details) { details.Add(itm.Message); // Append details } return(Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateReceiverFaultCode(surrogate.ResultCode.ToString(), "http://marc.mohawkcollege.ca/hi"), new FaultReason("The receiver has constructed an invalid response that cannot be returned to the sender"), details), m.Headers.Action)); } else { return(result); } } }
/// <summary> /// Sets up the connector so it is able to open connections to the remote endpoint, and opens the channel. /// </summary> public void Open() { //TODO: Check if the connector is already open, or if the connector is in a faulted state. // Connection string if (ConnectionString == null) throw new ConnectorException(ConnectorException.MSG_NULL_CONNECTION_STRING, ConnectorException.ReasonType.NullConnectionString); else if (Formatter == null) throw new ConnectorException(ConnectorException.MSG_NULL_FORMATTER, ConnectorException.ReasonType.NullFormatter); Dictionary<string, List<string>> parameters = ConnectionStringParser.ParseConnectionString(ConnectionString); string endpointName = null, endpointAddress = null, bindingClass = null, bindingConfiguration = null; // Parameters foreach (KeyValuePair<string, List<string>> parm in parameters) switch (parm.Key) { case "binding": bindingClass = parm.Value[0]; break; case "bindingConfiguration": bindingConfiguration = parm.Value[0]; break; case "endpointname": endpointName = parm.Value[0]; break; case "endpointaddress": endpointAddress = parm.Value[0]; break; } if (bindingClass != null) { Binding binding = null; switch (bindingClass) { case "wsHttpBinding": if (!String.IsNullOrEmpty(bindingConfiguration)) binding = new WSHttpBinding(bindingConfiguration); else binding = new WSHttpBinding(SecurityMode.None, false); break; case "basicHttpBinding": if (!String.IsNullOrEmpty(bindingConfiguration)) binding = new BasicHttpBinding(bindingConfiguration); else binding = new BasicHttpBinding(); break; default: throw new InvalidOperationException("Could not understand binding"); } if (endpointAddress == null) throw new InvalidOperationException("When manually specifying binding you must specify an endpointAddress"); else wcfClient = new ConnectorServiceClient(binding, new EndpointAddress(endpointAddress)); } // Create the client else if (endpointName == null) throw new InvalidOperationException("The connection string must include the 'endpointName' attribute!"); else if (endpointAddress == null) wcfClient = new ConnectorServiceClient(endpointName); else wcfClient = new ConnectorServiceClient(endpointName, endpointAddress); #if WINDOWS_PHONE ((ICommunicationObject)wcfClient).Open(); #else wcfClient.Open(); // Using the app.config wcfConfiguration = ConfigurationManager.GetSection("marc.everest.connectors.wcf") as MARC.Everest.Connectors.WCF.Configuration.ConfigurationSection; if (Formatter == null) Formatter = (wcfConfiguration.Formatter as ICloneable).Clone() as IStructureFormatter; #endif }
public System.ServiceModel.Channels.Message ProcessInboundMessage(System.ServiceModel.Channels.Message m) { #if DEBUG Trace.TraceInformation("Received message on transport..."); #endif if (ListenConnector == null && OperationContext.Current.Host is WcfServiceHost) ListenConnector = (OperationContext.Current.Host as WcfServiceHost).ConnectorHost; if (ListenConnector != null) // In process { // Is this channel one way or two way? if (!(OperationContext.Current.Channel is IOutputChannel)) // Input only return null; #if DEBUG Trace.TraceInformation("Message handoff to WcfServerConnector completed"); #endif WcfSendResult processResult = ListenConnector.ProcessMessage(m); Message retVal = null; // There is an error, so the return value must be a fault! if (processResult == null || processResult.Code != ResultCode.Accepted && processResult.Code != ResultCode.AcceptedNonConformant) { // Web based context? if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError; WebOperationContext.Current.OutgoingResponse.StatusDescription = "Internal Server Error"; } List<String> details = new List<string>(); if (processResult != null) { details = new List<String>(); foreach(var dtl in processResult.Details) details.Add(dtl.Message); // Append details } if (processResult == null) retVal = Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateReceiverFaultCode(processResult.Code.ToString(), "http://marc.mohawkcollege.ca/hi"), new FaultReason("The receiver has constructed an invalid response that cannot be sent to the sender"), details), m.Headers.Action); else retVal = Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateSenderFaultCode("EPIC", "http://marc.mohawkcollege.ca/hi"), new FaultReason("Catastrophic failure occurred in the WcfServer send pipeline. This usually occurs when the connector does not receive a message in the allocated amount of time"), details), m.Headers.Action); } else { retVal = processResult.Message; if (processResult.Headers != null) { retVal.Headers.Clear(); retVal.Headers.CopyHeadersFrom(processResult.Headers); } } #if DEBUG Trace.TraceInformation("Message sent to client"); #endif return retVal; } else { // Get settings if(settings == null) settings = System.Web.Configuration.WebConfigurationManager.GetSection("marc.everest.connectors.wcf") as MARC.Everest.Connectors.WCF.Configuration.ConfigurationSection; // Now format the message and pass it on ... MemoryStream ms = new MemoryStream(); System.Xml.XmlWriter xw = System.Xml.XmlWriter.Create(ms); // Write to message memory stream for classification matching m.WriteMessage(xw); xw.Flush(); // Flush the Xml Writer ms.Seek(0, SeekOrigin.Begin); // Seek to start XPathDocument xpd = new XPathDocument(ms); // load xpath document XPathNavigator xpn = xpd.CreateNavigator(); IMessageReceiver receiver = null; // The receiver to use // Determine the receiver foreach (KeyValuePair<String, IMessageReceiver> kv in settings.Receiver) if (xpn.SelectSingleNode(kv.Key) != null) { receiver = kv.Value; break; } // Was a receiver found? if (receiver == null) { // Create a not implemented exception if(WebOperationContext.Current != null) WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotImplemented; return Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateSenderFaultCode( "NotImplemented", "http://marc.mohawkcollege.ca/hi"), new FaultReason("No receiver understands the request message.")), m.Headers.Action); } // Create a streams for deserialization ms = new MemoryStream(); XmlWriterSettings xws = new XmlWriterSettings(); xws.Indent = true; xw = XmlWriter.Create(ms, xws); // Deserialize body WcfReceiveResult rcv = new WcfReceiveResult(); try { // Because of classification, we need to process this in a wierd way, // Basically the formatter will classify the message based on the root element name // it receives. Because a SOAP message's root isn't what we really want to process, // the first child node under the 'body' must be passed to the xml writer xpn.SelectSingleNode("//*[local-name() = 'Body']/child::node()").WriteSubtree(xw); xw.Flush(); ms.Seek(0, SeekOrigin.Begin); var serResult = settings.Formatter.Parse(ms); rcv.Structure = serResult.Structure; rcv.Details = serResult.Details; if (rcv.Details.Count() == 0) rcv.Code = ResultCode.Accepted; else rcv.Code = ResultCode.AcceptedNonConformant; } catch (Exception e) { rcv.Code = ResultCode.Error; rcv.Details = new IResultDetail[] { new ResultDetail(ResultDetailType.Error, e.Message, e) }; } // Process on the receiver IGraphable obj = receiver.MessageReceived(rcv.Structure, rcv.Code, rcv.Details); // Graph this back XmlSerializerSurrogate surrogate = new XmlSerializerSurrogate((IXmlStructureFormatter)settings.Formatter); // Serialize the response Message result = Message.CreateMessage(m.Version, m.Headers.Action, obj, surrogate); // Validate surrogate.WriteObject(new MemoryStream(), obj); // Surrogate result code is acceptable? if (surrogate.ResultCode != ResultCode.Accepted && surrogate.ResultCode != ResultCode.AcceptedNonConformant) { if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.InternalServerError; WebOperationContext.Current.OutgoingResponse.StatusDescription = "Internal Server Error"; } List<string> details = new List<String>(); foreach(var itm in surrogate.Details) details.Add(itm.Message); // Append details return Message.CreateMessage(m.Version, MessageFault.CreateFault(FaultCode.CreateReceiverFaultCode(surrogate.ResultCode.ToString(), "http://marc.mohawkcollege.ca/hi"), new FaultReason("The receiver has constructed an invalid response that cannot be returned to the sender"), details), m.Headers.Action); } else return result; } }
/// <summary> /// Sets up the connector so it is able to open connections to the remote endpoint, and opens the channel. /// </summary> public void Open() { //TODO: Check if the connector is already open, or if the connector is in a faulted state. // Connection string if (ConnectionString == null) { throw new ConnectorException(ConnectorException.MSG_NULL_CONNECTION_STRING, ConnectorException.ReasonType.NullConnectionString); } else if (Formatter == null) { throw new ConnectorException(ConnectorException.MSG_NULL_FORMATTER, ConnectorException.ReasonType.NullFormatter); } Dictionary <string, List <string> > parameters = ConnectionStringParser.ParseConnectionString(ConnectionString); string endpointName = null, endpointAddress = null, bindingClass = null, bindingConfiguration = null; // Parameters foreach (KeyValuePair <string, List <string> > parm in parameters) { switch (parm.Key) { case "binding": bindingClass = parm.Value[0]; break; case "bindingConfiguration": bindingConfiguration = parm.Value[0]; break; case "endpointname": endpointName = parm.Value[0]; break; case "endpointaddress": endpointAddress = parm.Value[0]; break; } } if (bindingClass != null) { Binding binding = null; switch (bindingClass) { case "wsHttpBinding": if (!String.IsNullOrEmpty(bindingConfiguration)) { binding = new WSHttpBinding(bindingConfiguration); } else { binding = new WSHttpBinding(SecurityMode.None, false); } break; case "basicHttpBinding": if (!String.IsNullOrEmpty(bindingConfiguration)) { binding = new BasicHttpBinding(bindingConfiguration); } else { binding = new BasicHttpBinding(); } break; default: throw new InvalidOperationException("Could not understand binding"); } if (endpointAddress == null) { throw new InvalidOperationException("When manually specifying binding you must specify an endpointAddress"); } else { wcfClient = new ConnectorServiceClient(binding, new EndpointAddress(endpointAddress)); } } // Create the client else if (endpointName == null) { throw new InvalidOperationException("The connection string must include the 'endpointName' attribute!"); } else if (endpointAddress == null) { wcfClient = new ConnectorServiceClient(endpointName); } else { wcfClient = new ConnectorServiceClient(endpointName, endpointAddress); } #if WINDOWS_PHONE ((ICommunicationObject)wcfClient).Open(); #else wcfClient.Open(); // Using the app.config wcfConfiguration = ConfigurationManager.GetSection("marc.everest.connectors.wcf") as MARC.Everest.Connectors.WCF.Configuration.ConfigurationSection; if (Formatter == null) { Formatter = (wcfConfiguration.Formatter as ICloneable).Clone() as IStructureFormatter; } #endif }