/// <summary> /// Called after an inbound message has been received but before the message is dispatched /// to the intended operation. /// </summary> /// <param name="request">The request message.</param> /// <param name="channel">The incoming channel.</param> /// <param name="instanceContext">The current service instance.</param> /// <returns> /// An instance of <see cref="WcfExecutionContext" />. This object is passed back to method /// <see cref="BeforeSendReply(ref Message, object)" />. /// </returns> public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { /* * */ MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue); request = buffer.CreateMessage(); /* * */ WcfExecutionContext ctx = WcfExecutionContext.Read(request); /* * TODO: pull from config */ var config = new MethodRawLoggingConfiguration() { Enabled = true, Request = true, Response = true }; if (config.Enabled == true) { string message = ToMessage(config.Response, buffer); Journal(ctx, false, message); } return(ctx); }
/// <summary> /// Looks for 'svc:ExecutionHeader' header in the message. If the header is /// not present, will throw exception. /// </summary> /// <param name="message">WCF message.</param> /// <returns> /// Always returns an instance of <see cref="WcfExecutionContext" />. /// </returns> public static WcfExecutionContext Read(Message message) { #region Validations if (message == null) { throw new ArgumentNullException(nameof(message)); } #endregion int ix = message.Headers.FindHeader(HeaderName, Zn.Namespace); // TODO: check ix != -1 var content = message.Headers.GetHeader <XmlNode[]>(ix); // TODO: check content.Length WcfExecutionContext ctx = new WcfExecutionContext(); ctx.ActivityId = new Guid(content[0].InnerText); ctx.AccessToken = content[1].InnerText; ctx.ExecutionId = new Guid(content[2].InnerText); ctx.Action = content[3].InnerText; ctx.MomentStart = DateTime.ParseExact(content[4].InnerText, "o", CultureInfo.InvariantCulture); return(ctx); }
/// <summary /> public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { /* * */ WcfExecutionContext ctx = new WcfExecutionContext(); ctx.ActivityId = Guid.Empty; ctx.AccessToken = null; ctx.ExecutionId = Guid.NewGuid(); ctx.Action = request.Headers.Action; ctx.MomentStart = PreciseDateTime.UtcNow; /* * Don't read the header using a deserializer, because we don't want to trust * the request. */ int ix = request.Headers.FindHeader("EndpointHeader", Zn.Namespace); if (ix > -1) { var xr = request.Headers.GetReaderAtHeader(ix); XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); manager.AddNamespace("zn", Zn.Namespace); XmlDocument doc = new XmlDocument(); doc.Load(xr); var activityElem = doc.DocumentElement.SelectSingleNode(" zn:ActivityId ", manager); if (activityElem != null) { try { ctx.ActivityId = new Guid(activityElem.InnerText); } catch { // Snuff! } } var accessTokenElem = doc.DocumentElement.SelectSingleNode(" zn:AccessToken ", manager); if (accessTokenElem != null) { ctx.AccessToken = accessTokenElem.InnerText; } } /* * */ request.Headers.Add(ctx); return(ctx); }
/// <summary> /// Writes the message to the database. /// </summary> /// <param name="context">Current execution context.</param> /// <param name="direction">Direction of message.</param> /// <param name="message">XML message.</param> private static void Journal(WcfExecutionContext context, bool direction, string message) { const string Database = "SqlServerLogging"; if (ConfigurationManager.ConnectionStrings[Database] == null) { throw new ZincException(ER.ServiceModel_SqlServer_ConnectionMissing, Database); } /* * */ SqlConnection conn = new SqlConnection(); conn.ConnectionString = ConfigurationManager.ConnectionStrings[Database].ConnectionString; try { conn.Open(); } catch (SqlException ex) { throw new ZincException(ER.ServiceModel_SqlServer_Open, ex, Database); } catch (ConfigurationErrorsException ex) { throw new ZincException(ER.ServiceModel_SqlServer_Open, ex, Database); } catch (InvalidOperationException ex) { throw new ZincException(ER.ServiceModel_SqlServer_Open, ex, Database); } /* * */ SqlCommand cmd = conn.CreateCommand(); cmd.CommandText = "insert into ZN_SOAP_JOURNAL ( Application, ActivityId, AccessToken, ExecutionId, Action, Direction, XmlMessage, Moment )" + "values ( @Application, @ActivityId, @AccessToken, @ExecutionId, @Action, @Direction, @XmlMessage, @Moment ) "; cmd.CommandType = CommandType.Text; cmd.Parameters.Add("@Application", SqlDbType.VarChar).Value = App.Name; cmd.Parameters.Add("@ActivityId", SqlDbType.UniqueIdentifier).Value = context.ActivityId; cmd.Parameters.Add("@AccessToken", SqlDbType.VarChar).Value = context.AccessToken; cmd.Parameters.Add("@ExecutionId", SqlDbType.UniqueIdentifier).Value = context.ExecutionId; cmd.Parameters.Add("@Action", SqlDbType.NVarChar).Value = context.Action; cmd.Parameters.Add("@Direction", SqlDbType.Bit).Value = direction; cmd.Parameters.Add("@XmlMessage", SqlDbType.Xml).Value = message; cmd.Parameters.Add("@Moment", SqlDbType.DateTime).Value = DateTime.UtcNow; try { cmd.ExecuteNonQuery(); } catch (SqlException ex) { throw new ZincException(ER.ServiceModel_SqlServer_ExecuteNonQuery, ex, Database); } /* * */ try { conn.Close(); } catch (SqlException) { } }