I have a web service that I'm calling that returns a list of error messages. I'm then doing a foreach over this list, and matching based on the text of the error messages in a config file. However, some of the error messages returned from the web service contains some unknown data, such as a date, or a number.
How can I match this text, using C#? Would I have to split the string and try to match each individual word? How do I deal with an unknown variable such as a date or number when doing a ".Contains(...)"?
Here's an example:
Web service list might contain the following
"This is an example static error message"
"Another example static error message"
"This is an error message for employee 2"
"This is an error message dated 11/2/2017"
"Employee 3 does not work here anymore"
In my config file, I have the following:
<add errorText="This is an example static error message" field="N/A" />
<add errorText="Another example static error message" field="N/A" />
<add errorText="This is another example for employee **X**" field="N/A" />
<add errorText="This is an error message dated **X**" field="N/A" />
<add errorText="Employee **X** does not work here anymore" field="N/A" />
From your config files, you could build regular expressions as follows:
String configString = GetConfigString(3); // "This is another example for employee **X**"
String regexPattern = String.Concat("^", configString.Replace("**X**", ".+"), "$");
Boolean match = Regex.IsMatch("This is another example for employee John", regexPattern);
and then use such regex to match your text strings.
You could also build all of your regular expression patterns as soon as your application starts and cache them somewhere for future use:
String configStrings = GetConfigStrings();
String[] regexPatterns = new String[configStrings.Length];
for (Int32 i = 0; i < configStrings.Length; ++i)
regexPatterns[i] = String.Concat("^", configStrings[i].Replace("**X**", ".+"), "$");
Since you have a mixed type of possible string replacement within your framework, sticking to the .+ token is the better choice.
If course, it's up to you to eventually build a configuration file parsers and implement GetConfigString and GetConfigStrings methods (or only one, depending on the approach you want to use).
You can use Regex to match them:
Regex.IsMatch(message, "This is another example for employee .+")
Regex.IsMatch(message, "This is an error message dated .+")
If you don't like to take regex approach, like me, you can add the known error messages into a HashSet and keep them in memory and then lookup which error message matches the most with the error message on hand, like a match score.
Related
The application I'm building targets portuguese speaking users. The users can input a sentence which will be interpreted by ANTLR. To provide the users the best feedback from their input I will need to have errors displayed in portuguese.
I didn't found an configuration or file where i could change the error tokens like in some other libraries.
You cannot change the language of errors/exception coming out of an ANTLR generated parser. You will need to catch these exceptions yourself, and make (for your audience) human readable messages. ANTLR's exceptions have enough for you to do this: line number, column index, tokens: everything is available for you.
As i searched deeper the best alternative is to override the methods on DefaultErrorStrategy and build the message the way you want.
You can set an error Handler to your parser, it should be your new custom error strategy.
typescript DefaultErrorStrategy
Here is my override for reportInputMismatch method with custom translation:
reportInputMismatch(recognizer: Parser, e: InputMismatchException): void {
const expected = e.expectedTokens;
const expectedString = expected ? this.getFriendlyExpectedTokens(expected, recognizer.vocabulary) : '';
const input = this.getTokenErrorDisplay(e.getOffendingToken(recognizer));
const msg = `entrada ${input} não compatível, espera-se ${expectedString}`;
this.notifyErrorListeners(recognizer, msg, e);
}
I am currently working on a microservice that runs on DotNet6 and is using MailKit 3.1.0.
I have the following code snippet:
var from = "John Doe via noreply#company.com <noreply#company.com>";
var mailBoxAddress = MailboxAddress.Parse(from);
The second line of code leads to following Exception:
MimeKit.ParseException: Invalid addr-spec token at offset 0
I did some testing and found out that the following variations of the string work:
var fromAlternative1 = "John Doe via noreplycompany.com <noreply#company.com>"; // missing #
var fromAlternative2 = "JohnDoevianoreply#company.com<noreply#company.com>"; // no empty space
This leads me to the question wether it could exist a configuration that enables parsing the from string, there could be a bug or this behaviour is by design?
As a workaround im parsing the displayname and email-address by myself.
You need to properly quote the name if it contains # symbols or ..
Those are special characters that are required to be quoted by the email specifications.
In other words, the correct string would be:
"John Doe via noreply#company.com" <noreply#company.com>
Or, in C#:
var from = "\"John Doe via noreply#company.com\" <noreply#company.com>";
I am trying to understand the logging output of dotnet run for an ASP.NET Core project. There are many places showing a full type name followed by what appears to be the indexer syntax.
This page explains how array types are represented, but in that case there is no index.
Console.WriteLine(new string[100]); shows:System.String[]
This is an actual dotnet run output:info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[58]
How to interpret the previous text? What is 58?
Is it a general C# string representation? What code construct would output something like that?
In the example provided, there are three components:
info, which is the log level.
Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager, which is the log category.
58, which is the log event ID.
ASP.NET Core uses ILogger and ILogger<T> for logging, using calls such as:
logger.LogInformation(...);
The example log message you've shown is from a console provider, which has its own rules about how to format the message. By default, this starts with a header line of level: category[eventID], as I've shown.
As a crude example, you might imagine the following code being used to generate the final message:
var logLevel = "info";
var logCategory = "Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager";
var logEventId = 58;
Console.Writeline($"{logLevel}: {logCategory}[{logEventId}]");
I started with the solution here http://social.technet.microsoft.com/wiki/contents/articles/20547.biztalk-server-dynamic-schema-resolver-real-scenario.aspx
which matches my scenario perfectly except for the send port, but that isn't necessary. I need the receive port to choose the file and apply a schema to disassemble. From their the orchestration does the mapping, some of it custom, etc.
I've done everything in the tutorial but I keep getting the following error.
"There was a failure executing the receive pipeline... The body part is NULL"
The things I don't get from the tutorial but don't believe they should be an issue are:
I created a new solution and project to make the custompipeline component (reference figure 19) and thus the dll file. Meaning it is on it's own namespace. However, it looks like from the tutorial they created the project within the main biztalk solution (ie the one with the pipeline and the orchestration) and thus the namespace has "TechNetWiki.SchemaResolver." in it. Should I make the custompipeline component have the namespace of my main solution? I'm assuming this shouldn't matter because I should be able to use this component in other solutions as it is meant to be generic to the business rules that are associated with the biztalk application.
The other piece I don't have is Figure 15 under the "THEN Action" they have it equal the destination schema they would like to disassemble to but then they put #Src1 at the end of "http://TechNetWiki.SchemaResolver.Schemas.SRC1_FF#Src1". What is the #Src1 for?
In the sample you've linked to, the probe method of the pipeline component is pushing the first 4 characters from the filename into a typed message that is then passed into the rules engine. Its those 4 characters that match the "SRC1" in the example.
string srcFileName = pInMsg.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties This link is external to TechNet Wiki. It will open in a new window. ").ToString();
srcFileName = Path.GetFileName(srcFileName);
//Substring the first four digits to take source code to use to call BRE API
string customerCode = srcFileName.Substring(0, 4);
//create an instance of the XML object
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(string.Format(#"<ns0:Root xmlns:ns0='http://TechNetWiki.SchemaResolver.Schemas.SchemaResolverBRE This link is external to TechNet Wiki. It will open in a new window. '>
<SrcCode>{0}</SrcCode>
<MessageType></MessageType>
</ns0:Root>", customerCode));
//retreive source code in case in our cache dictionary
if (cachedSources.ContainsKey(customerCode))
{
messageType = cachedSources[customerCode];
}
else
{
TypedXmlDocument typedXmlDocument = new TypedXmlDocument("TechNetWiki.SchemaResolver.Schemas.SchemaResolverBRE", xmlDoc);
Microsoft.RuleEngine.Policy policy = new Microsoft.RuleEngine.Policy("SchemaResolverPolicy");
policy.Execute(typedXmlDocument);
So the matching rule is based on the 1st 4 characters of the filename. If one isn't matched, the probe returns a false - i.e. unrecognised.
The final part is that the message type is pushed into the returned message - this is made up of the namespace and the root schema node with a # separator - so your #src1 is the root node.
You need to implement IProbeMessage near to class
I forgot to add IProbeMessage in the code of article. It is updated now.
but it is there in sample source code
Src1 is the the root node name of schema. I mentioned that in article that message type is TargetNamespace#Root
I recommend to download the sample code
I hope this will help you
In my AppSettings in web.config, I have something like this:
<appSettings>
<add key="ExternalSystemUrl" value="http://example.com/page.aspx?id={0}&action=eat&object=bacon" />
</appSettings>
However, it seems that when an ampersand (&) is included in an AppSettings value, ASP.NET throws the following error:
An error occurred while parsing EntityName
Why does this happen, and how can I include URLs like this in App.config?
Replace & with & (escape it):
<add
key="ExternalSystemUrl"
value="http://example.com/page.aspx?id={0}&action=eat&object=bacon" />
That's the common requirement for any valid XML file.
See Where can I get a list of the XML document escape characters?
You can Try using & instead.
In XML an ampersand tells the parser "the data immediately following this ampersand is an entity which needs to be translated." If the data immediately following is not a valid XML entity, then you get this error. If possible, use & for your ampersand within the XML.