FileHelper library - custom error messages - filehelpers

I am use the FileHelper to parse CSV files. Error messages encountered when parsing the file are displayed to the end user. The end user may not be able to make sense of the technical error message. Not too many clerks know what an Int32 is or Class: UploadFooDto.
I would like to customize the error messages so they are more user friendly. Something like:
Line 1. Column 2. A string (a) was entered instead of a number
Line 2. Column 3. '13-14-15' is not a valid date
I cannot find anything in the API that would allow me to customize the error messages. The most I have so far are some extension methods to clean up the errors:
public static class FileHelperExceptionExtensions
{
public static string BuildMessage(this ErrorInfo error)
{
if (error.ExceptionInfo is ConvertException)
{
return ((ConvertException)error.ExceptionInfo).BuildMessage();
}
if (error.ExceptionInfo is BadUsageException)
{
var message = error.ExceptionInfo.Message;
var readTo = message.IndexOf("Class:");
return message.Substring(0, readTo);
}
return string.Format("Line: {0}. An unspecific error occured.", error.LineNumber);
}
public static string BuildMessage(this ConvertException exception)
{
return string.Format("Line: {0}. Column: {1}. Field: {2}. Cannot convert '{3}' to type: '{4}'", exception.LineNumber, exception.ColumnNumber, exception.FieldName, exception.FieldStringValue, exception.FieldType.Name);
}
}
but these extensions still leave a lot to be desired. Is it possible to customize the error messages?

It's hard to improve on your extension methods without it being more hassle than it's worth.
You cannot subclass the default converters (e.g., FileHelpers.ConvertHelpers.Int32Converter since they are internal and sealed). You could create your own custom converter for each type (and base it on the corresponding source code from FileHelpers, e.g., Int32Converter). Then you can raise an alternative to ConvertException (also sealed so you cannot subclass) which would format the message differently.

Related

Getting a client readable message from an Npgsql.PostgresException

I'm writing a web api using PostgreSQL and am checking database constraints as part of the validation process, but I also have a global exception filter as a fallback in case something gets by when saving. My problem is that the exception doesn't seem to have any message that I can present to the client without some processing. The added image is of the PostgresException data from a breakpoint. For example, in this case I would want something along the lines of "Asset Number x already exists" or just "Asset Number must be unique". Is this something that can be configured somewhere? The place that makes the most sense is at the constraint creation code, but I couldn't find an option to do so.
modelBuilder.Entity<AssetItem>().HasIndex(item => new { item.AssetNumber }).IsUnique();
public class DbExceptionFilter : IExceptionFilter
{
private const string UNIQUE_EXCEPTION = "23505";
public async void OnException(ExceptionContext context)
{
var exceptionType = context.Exception.InnerException.GetType().FullName;
if (exceptionType == "Npgsql.PostgresException")
{
var pgException = (PostgresException) context.Exception.InnerException;
switch(pgException.SqlState)
{
case UNIQUE_EXCEPTION:
var error = new {error = "Unique Error Here"};
await WriteJsonErrorResponse(context.HttpContext.Response, HttpStatusCode.BadRequest, error);
return;
}
}
else
{
var error = new { error = "Unexpected Server Error"};
await WriteJsonErrorResponse(context.HttpContext.Response, HttpStatusCode.InternalServerError, error);
return;
}
}
private async Task WriteJsonErrorResponse(HttpResponse response, HttpStatusCode statusCode, dynamic error)
{
response.ContentType = "application/json";
response.StatusCode = (int) statusCode;
await response.Body.WriteAsync(Encoding.ASCII.GetBytes(JsonConvert.SerializeObject(error)));
}
}
The closest thing to a user-readable message that PostgreSQL provides is the message text exposed on PostgresException.
However, as a general rule it is not a good idea to expose database errors directly to users (including web API users): these are intended to the application directly interacting with the database (i.e. your application). These messages generally don't mean much to the users of your API, and more importantly they leak potentially sensitive information about your database schema and are therefore not secure. It's especially problematic to dump/serialize the entire exception to the user as you seem to be doing (with JsonConvert.SerializeObject).
The best practice here would be to identify legitimate database exceptions that the user may trigger, intercept these and return and appropriately-worded message of your own (e.g. "A user with that name already exists").
As a side note, to identify PostgresException, rather than getting the name of the exception and comparing to that, you can simply use C# pattern matching:
if (context.Exception.InnerException is PostgresException postgresException)
{
// ...
}

Error try to access profile through .net code on sabre ProfileReadRQ

When we try to access profile through code we are getting message as below, please advice
The error is:
There was an error in serializing one of the headers in message
EPS_ProfileReadRQRequest: 'Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'CRM.ProfileReadRQ.BusinessSystemIdentityInfoSynchronizationCriterionTypeExcludeCombination' to 'CRM.ProfileReadRQ.BusinessSystemIdentityInfoSynchronizationCriterionTypeIncludeCombination'
error CS0029: Cannot implicitly convert type 'CRM.ProfileReadRQ.BusinessSystemIdentityInfoSynchronizationCriterionTypeIncludeCombination' to 'CRM.ProfileReadRQ.BusinessSystemIdentityInfoSynchronizationCriterionTypeExcludeCombination'
This happens because the serializer doesn't know what type to cast to since the types that throw the error can be of more than one type. I think that simplifies the XML but it makes the WSDL/.NET stuff more complicated. I'm probably not saying that perfectly accurately but that's the gist of it, at least as I understand it.
You can go into your reference.cs file and remove the serialization for those offending fields and try again. I've done this in the past with some success. If/when you update the API version with a new WSDL file you'll have to remember to do it again, though, so it's not a perfect solution. I've got a sample of what I removed from my reference.cs file to get one of the profile APIs below, hopefully it's helpful.
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.3056.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.sabre.com/eps/schemas")]
public partial class BusinessSystemIdentityInfoSynchronizationCriterionType {
private BusinessSystemIdentityInfoSynchronizationCriterionTypeExcludeCombination[] itemsField;
private ItemsChoiceType1[] itemsElementNameField;
//remarked this out 12/24/18 - these include/exclude combinations do not serialize correctly for some reason
/// <remarks/>
//[System.Xml.Serialization.XmlElementAttribute("ExcludeCombination", typeof(BusinessSystemIdentityInfoSynchronizationCriterionTypeExcludeCombination))]
//[System.Xml.Serialization.XmlElementAttribute("IncludeCombination", typeof(BusinessSystemIdentityInfoSynchronizationCriterionTypeIncludeCombination))]
//[System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemsElementName")]
//public BusinessSystemIdentityInfoSynchronizationCriterionTypeExcludeCombination[] Items {
// get {
// return this.itemsField;
// }
// set {
// this.itemsField = value;
// }
//}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("ItemsElementName")]
[System.Xml.Serialization.XmlIgnoreAttribute()]
public ItemsChoiceType1[] ItemsElementName {
get {
return this.itemsElementNameField;
}
set {
this.itemsElementNameField = value;
}
}
}

X-Tika-PDFocrStrategy is an invalid X-Tika-OCR header error

I am trying to use TikaJAXRS and add headers for setting PDFParser properties. Specifially the ocrStrategy property. However, when I add the header using X-Tika-PDFocrStrategy, I get an error stating that it is an invalid X-Tika-OCR header.
After looking into the source code, I believe the issue might be with the 'fillParseContext' method in the TikaResource.java file.
public static void fillParseContext(ParseContext parseContext, MultivaluedMap<String, String> httpHeaders,
Parser embeddedParser) {
TesseractOCRConfig ocrConfig = new TesseractOCRConfig();
PDFParserConfig pdfParserConfig = new PDFParserConfig();
for (String key : httpHeaders.keySet()) {
if (StringUtils.startsWith(key, X_TIKA_OCR_HEADER_PREFIX)) {
processHeaderConfig(httpHeaders, ocrConfig, key, X_TIKA_OCR_HEADER_PREFIX);
} else if (StringUtils.startsWith(key, X_TIKA_PDF_HEADER_PREFIX)) {
processHeaderConfig(httpHeaders, pdfParserConfig, key, X_TIKA_PDF_HEADER_PREFIX);
}
}
parseContext.set(TesseractOCRConfig.class, ocrConfig);
parseContext.set(PDFParserConfig.class, pdfParserConfig);
if (embeddedParser != null) {
parseContext.set(Parser.class, embeddedParser);
}
}
The if statement first looks for a key that starts with the OCR header prefix, and since the PDFParser's property name contains 'ocr', it is trying to find a property named 'ocrStrategy' in the OCRParser class, which doesn't exist.
Can anyone verify this, or tell me how I could set that property via the restful service?
Side note, I am using Tika as a service via a docker container and calling it from a python app.

SharePoint 2010: Error Mapping to Picture Hyperlink with SPMetal

Whenever I have a column of type hyperlink with the format set for pictures, I get an error whenever there is actually a value in that column.
The exception it throws is "Specified cast is not valid".
My thought is that the problem is either here (the FieldType being set to Url):
[Microsoft.SharePoint.Linq.ColumnAttribute(Name = "FOO", Storage = "FOO_", FieldType = "Url")]
public string FOO
{
get
{
return this._FOO;
}
set
{
if ((value != this._FOO))
{
this.OnPropertyChanging("FOO", this._FOO);
this._FOO = value;
this.OnPropertyChanged("FOO");
}
}
}
Or here (it being cast to a string):
private string _FOO;
But I'd have no idea what the proper values for either of those fields should be.
Any help would be greatly appreciated.
It works whenever this field does not have data in it and I JUST used SPMetal to generate the class, so I'll get the two most obvious questions out of the way.
Link to the answer:
https://mgreasly.wordpress.com/2012/06/25/spmetal-and-workflow-associations/
Turns out it is a known bug when mapping lists that have associated workflows.
SPMetal assigns it as a nullable integer when it's supposed to be an Object, hence the cast error.
Workaround: manually edit the mappings to make the type it returns an object or ignore the column by using a parameter map.

Linqpad - Outputting into anchor to use title

I have a db that stores exception messages.
I would like to create a query that gets these exceptions but instead of dumping huge amounts of text i would prefer it to be "on demand".
I figured putting the exception into an anchor tag like so and then reading the message when needed by mousing over it would work... apparently not.
var logsForErrors = (from error in Logs
select new {
error = LINQPad.Util.RawHtml("<a title='"+ error.Exception+"'></a>"),
errorDate = error.Date,
errorMessage = error.Message
}).Take(10);
logsForErrors.Dump();
This is throwing an exception (lol) - "Cannot parse custom HTML: "
Encoding the exception message
...RawHtml("<a title='"+ Uri.EscapeDataString(error.Exception)+"'></a>")
Message Could not translate expression 'RawHtml((("h__TransparentIdentifier0.error.Exception)) +
"'>"))' into SQL and could not treat it as a local expression.
will generate a new error
Any ideas? - I am open to alternative solutions to this also.
I just want a container for the message instead of it just dumping right into the output as it it so huge!.
Thanks,
Kohan
Have you tried using the "Results to DataGrids" mode in the recent betas? It might do just what you need without having to write anything else.
Edit: your error was probably due to emitting HTML without escaping the text. The easiest solution is to call Util.RawHtml with an XElement instead of a string. You could write an extension method that does what you want like this:
public static class Extensions
{
public static object Tooltipize (this string data)
{
if (string.IsNullOrEmpty (data) || data.Length < 20) return data;
return Util.RawHtml (new XElement ("span", new XAttribute ("title", data), data.Substring (0, 20)));
}
}
Put this into My Extensions and you can use it from any query.