Split message and promote properties via Biztalk pipeline - c#

I am polling a well formatted xml messages from SQL Server table using sqlserver stored procedure that returnes me xml like the following one
<PolledMessage xmlns="http://SomeNamespace.ru/">
<Message>
<MessageNode>
<MasterDataMemberAddRequest xmlns="http://AnotherNamespace">
...
</MasterDataMemberAddRequest>
</MessageNode>
</Message>
<Message>
<MessageNode>
<MasterDataMemberAddRequest xmlns="http://AnotherNamespace">
...
</MasterDataMemberAddRequest>
</MessageNode>
</Message>
</PolledMessage>
Where the MessageNode is a node, containing the message that i want to extract. I have done that using Envelope schema with XmlReceive pipeline, and it worked well. But after that i need to write some custom values to the message context of each of that extracted messages. i've wrote a custom pipeline, that takes property name, namespace and value and writes it to the message context, but i can't figure out how to put together that disassembling and promoting properties of disassembled messages.
Thanks for any advice!

Arsen,
The XMLReceive pipeline debatches your envelope using the XML dissembler component, and will promote individual message properties providing they are correctly marked as context properties (and assuming they are in the message!)
If you need to push custom non-message properties into each message, you could create a custom pipeline and place your pipeline component that acts on each disassembled message in the resolve party stage.
Here's a link to a custom context property promotion component. You'll see in the example that it is placed in the validate stage - I believe validate or resolve party are both ok. Hope this helps!

Related

Logging to Azure Log Analytics custom fields using Serilog

I'm new to azure and also a rookie in .net, so this may be a noob question :)
Anyway, I have successfully managed to log to Azure Log Analytics using this code snippet:
var loggerConfig = new LoggerConfiguration().
Enrich.WithExceptionDetails().
Enrich.WithApplicationInformation(serviceName).
MinimumLevel.Debug().
MinimumLevel.Override("Microsoft", LogEventLevel.Information).
Enrich.FromLogContext().
Destructure.ByTransforming<ExpandoObject>(JsonConvert.SerializeObject).
//Enrich.WithProperty("ErrorMsg_CF","test").
WriteTo.AzureAnalytics(workspaceId: "MyWorkSpaceID",
authenticationId: "MyAuthID",
logName: "MyCustomLog_CL",
restrictedToMinimumLevel: LogEventLevel.Debug)
And:
Logging.Logger.Initialize(serviceName: "Logging Web Test v1.1");
Logging.Logger.GetLogger().Log(LogLevel.Debug, "{ErrorMsg_CF}:{TraceID_CF}:{UserName_CF}", errorMsg,traceID,userName);
I have, in my Log Analytics custom log table, created 3 custom fields: "ErrorMsg_CF", "TraceID_CF" and "UserName_CF", and I want to either be able to directly log to these custom fields, or somehow split my errormsg into these three custom fields.
When I import a file, I see that the message is stored in the "RawData" field, and with that field I am able to use the custom field generator and create custom fields, and also let Log Analytics split the message into the fields for me. But, when I do it through my application, the message is stored in the "LogMEssage_s" field, and seems like it's not possible to create custom fields from that field.
So, anyone know how I can log to my custom fields from my application?
The default formatting configuration is a line by line event logging. ALN can be ingested using JSON so that will be the best way to format log entry in that way.
.WriteTo.DESTINATION(new CompactJsonFormatter(), OTHER OPTIONS HERE)
Serilog formatting

How to add a parameter to .Net Core structured logging without referencing it in a message?

I can do this in .net core
_logger.LogInformation("Token validated {clientId}", "MyId");
And then logging libraries like NLog will know that there is a property called clientId with the value MyId in the message and can render it in a special way.
I am trying to do the same without including the property in the message itself, but cannot manage to nail it. This is what I have done so far and it does not result in a property in NLog:
LogEventInfo info = new LogEventInfo
{
Properties = {{"clientId", "MyId"}},
};
_logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, "Token validated", info, null, info.MessageFormatter);
This results in a message without property. Is there a better way to do this or have I done something wrong?
The whole idea with Microsoft-Extension-Logging (MEL) ILogger-interface is not being dependent on a specific Logging-Framework.
If you start creating NLog LogEventInfo-objects, then you might as well call NLog.LogManager.GetCurrentClassLogger() and use that as Logger.
But maybe this wiki-page can give you some ideas:
https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-properties-with-Microsoft-Extension-Logging

How to ignore UnknownElements on deserialization (XmlSerializer) by using a WCF SoapClient?

I have a C#-Project where I added a WCF Service References via a WSDL-File. Because I don't want to use the "DataContractSerializer", I changed the "Reference.svcmap" and set the Serializer to "XmlSerializer". At this Point all works perfectly.
Now to the Problem. The Service is not my Service and it can be, that the programmer of the service adds properties to the result classes and I can't update my reference at the same time. So it can be, that my imported WSDL is out of date. In this case the result after deserialization is not correct.
For example the result has the properties "Name", "Street" and "Town". If the service now returns...
<?xml version="1.0" encoding="UTF-8"?>
<TestResult xmlns="http://test.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Tim</Name>
<Street>Samplestreet</Street>
<Town>Sampletown</Town>
</TestResult>
my result has the values:
Name=Tim
Street=Samplestreet
Town=Sampletown
If the service programmer now adds the property "Fullname" between "Name" and "Street" and my WSDL-import is out of date, the result will become incorrect. The service returns...
<?xml version="1.0" encoding="UTF-8"?>
<TestResult xmlns="http://test.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Tim</Name>
<FullName>Tim Brown</FullName>
<Street>Samplestreet</Street>
<Town>Sampletown</Town>
</TestResult>
but after deserializition my result has the values :
Name=Tim
Street=null
Town=null
It looks like the XmlSerialzier of WCF stops the deserializition at the point it founds a UnknownElement without an exception.
The question, is there a setting, a way to configure the service reference, SoapClient or Serializier to ignore the UnknownElement and continue with the deserializition like a standard XmlSerialzier how returns all the values it knows?
Or is there a way to use a own Serialzier on client side in a WCF SoapClient?
Because of the Answer of "Legart" I looked inside the generated file "Reference.cs" and find out, why I got a wrong deserialization result, when the Service sends me a result with a new element that is unknown for my service reference.
The Problem is that in the generated Reference file the "XmlElementArributes" has a parameter named "Order". If the Service sent me now a new, unknown element it could be, that this element changes the order of the elements and then the deserialisation will return a wrong result.
My current solution is to remove all the "Order"-Parameters in the Attributes. Then the changed order and added elements in the Server result has no effect to the deserialization. It’s like the new, unknown elements will be ignored.
It’s not the best solution because I must edit a generated file, but at the moment it works for me.
If you know a better way, please write a comment.
You can try to add additional property to you class TestResult and mark it with XmlAnyElement:
[XmlAnyElement]
public XmlElement[] AllElements;
XmlAnyElement
For DataContract, DataMember style you can implement IExtensibleDataObject interface:
IExtensibleDataObject

How to access a web service with the following parameters and client proxy generated based on a wsdl

I have been provided with a WSDL and have generated the proxy class based on this WSDL. Sorry cannot provide the WSDL due to security concerns. The method in the proxy class that I'd like to call is:
public HeaderValueType GetStatus(System.DateTime RequestorTrxTime, string RequestorContext, string MessageIdentifier, string ProfileNumber, string ProfileType, int RequestIndicator, out ResponseBodyType Response) {//Some code}
I am just wondering what the fields
string RequestorContext, string MessageIdentifier
Are meant to be because I have seen requestorContext being passed as an object like this:
OperationContext.Current.InstanceContext
But not as a string the same goes for MessageIdentifier.
I have not got access to the creators of this WSDL for a while and cant get access, so I thought if any one would have a clue.
Did you try calling the service just be passing some values into these fields? It looks more like naming coincidence. Check that linked XSDs from WSDL specify this as message content. Also check that WSDL contains policy assertion called CompositeDuplex and assertions for reliable messaging (it should be called RMAssertion). It it doesn't it is not WsDualHttpBinding where InstanceContext is used to expose callback contract and those parameters are only data related - meaning of those parameters must be described by service provider.

NHibernate Validation Localization with S#arp Architecture

I'm trying to localize error messages from NHibernate.Validator. From what I have read, the messages should automaticaly be localized if I set the CurrentCulture/CurrentUICultule ; wich I tried without success. I'm using S#arp Architecture with the default configuration. As I said, the only thnig I changed is the CurrentCulture/CurrentUICultule.
Do I have to create a custom message interpolator for nhibernate validator?
I have posted in my blog about creating a Custom Interpolator that overrides the default messages if they exist in your resources. It allows you to override the default messages and add new messages for your validators.
Check it out: NHibernate Validator Custom Messages
Changing the culture for was not a good idea, since all my website is in spanish, so the path that I took was to create a SpanishMessageInterpolator and then set it up in my nhv.config like:
<property name="message_interpolator_class">NHibernateValidator.SpanishMessageInterpolator, Assembly</property>
And finally I did modify my global.asax.cs file to include the nhv.config file on NHibernate initialization, like:
NHibernateSession.Init(
webSessionStorage,
new string[] { Server.MapPath("~/bin/Assembly.dll") },
new AutoPersistenceModelGenerator().Generate(),
Server.MapPath("~/NHibernate.config"), Server.MapPath("~/nhv.config"));

Categories

Resources