Attempting to use OOPFactory to parse 271 benefits using EligibilityBenefitDocument - c#

I'm attempting to use OOPFactory to parse 271 files. (source code here: https://x12parser.codeplex.com/SourceControl/latest) The part I'm struggling with at the moment is getting benefits information. (I can get subscriber and source information just fine).
I've followed the instructions in this post:
(Anyone translate a X12 271 Healthcare response) I can get an EligibilityBenefitDocument with the Subscriber and Source information, but the benefit information on the document winds up being either null, empty, or some other unhelpful value.
I've gone through the raw 271 data and verified that the information I'm looking for is indeed in there. (for reference, I've run multiple files from multiple payers)
I've traced through the both X12SteamReader and the X12Parser while they ran, and verified that the data made it all the way through the parser. It looks like things are working well with the parser. I'm not totally sure on how the EligiblityBenefitDocument is supposed to be generated. It looks like it uses some sort of xslt translation that doesn't seem to be working well for my 271 files. I've applied this tweak to my xslt file (https://x12parser.codeplex.com/workitem/2765) - it cleans up some null values, but still doesn't parse correctly.
What should I be looking at next?
It's possible that I'm using an unsupported EDI format. I'm not sure how to tell if that's the case
I've been programming for a long time, but I've never used the XSLT features of .NET Does anyone have any good links on where to get started there?
A quick solution would be AWESOME if anyone has one.
Thx!
=========
Edit 1:
Here is my code that kicks things off:
Dim ediFileString = path_to_my_file
Dim fstream = New FileStream(ediFileString, FileMode.Open, FileAccess.Read)
Dim service = New EligibilityTransformationService()
Dim benefitDoc = service.Transform271ToBenefitResponse(fstream)
Dim responses = benefitDoc.EligibilityBenefitResponses
I'm calling it from VB.NET instead of C#, but given that it all compiles down to MSIL, and that Source, Receiver, and Subscriber properties are all working, I don't think that's a reason why BenefitInfos would fail.
=========
Edit 2: including more code in response to a request for more detail of what I'm trying to do
Dim ediFileString = path_to_my_file
Dim fstream = New FileStream(ediFileString, FileMode.Open, FileAccess.Read)
Dim service = New EligibilityTransformationService()
Dim benefitDoc = service.Transform271ToBenefitResponse(fstream)
Dim responses = benefitDoc.EligibilityBenefitResponses
Dim strClient = ""
For Each client In benefitDoc.EligibilityBenefitResponses
Try
strClient = "MemberID: " + tidyNull(client.Subscriber.MemberId) + " Transaction Control Number: " + tidyNull(client.TransactionControlNumber) + Constants.vbCrLf
Catch ex As Exception
End Try
Try
strClient += "Member Name: " + tidyNull(client.Subscriber.Name.FirstName) + " " + tidyNull(client.Subscriber.Name.MiddleName) + " " + tidyNull(client.Subscriber.Name.LastName) + Constants.vbCrLf
Catch ex As Exception
End Try
Try
strClient += "Payer Name: " + tidyNull(client.Source.Name.LastName) + Constants.vbCrLf
Catch ex As Exception
End Try
Try
strClient += "Date of Birth: " + tidyNull(client.Subscriber.SerializableDateOfBirth) + Constants.vbCrLf
Catch ex As Exception
End Try
Try
strClient += "Address: " + tidyNull(client.Subscriber.Address.Line1)
strClient += " " + tidyNull(client.Subscriber.Address.Line2) + " " + Constants.vbCrLf
strClient += "Address: " + tidyNull(client.Subscriber.Address.City) + ", " + tidyNull(client.Subscriber.Address.StateCode) + ", " + tidyNull(client.Subscriber.Address.PostalCode) + Constants.vbCrLf
Catch ex As Exception
End Try
Dim results As List(Of EligibilityBenefitInformation)
Try
results = client.BenefitInfos.FindAll(AddressOf searchPlanActive)
If results.Count > 0 Then
strClient += "Active Coverage!" + Constants.vbCrLf
End If
Catch ex As Exception
strClient += "Coverage Type: Couldn't be found"
End Try
For Each benefit In client.BenefitInfos
If benefit.Amount IsNot Nothing Then
strClient &= " Code: " & benefit.Amount
End If
strClient &= " Percentage: " & benefit.Percentage
Try
strClient &= " CoverageLevel: " & benefit.CoverageLevel.Description
Catch ex As Exception
End Try
Try
strClient &= " InPlanNetwork: " & benefit.InPlanNetwork.Description
Catch
End Try
Try
strClient &= " PlanCoverageDescription: " & benefit.PlanCoverageDescription
Catch ex As Exception
End Try
'strClient &= " Messages: " & benefit.Messages.FindLast()
Try
strClient &= " Amount: " & benefit.Amount.Value
Catch ex As Exception
End Try
'strClient &= " Amount: " & benefit.AdditionalInfos
strClient &= Constants.vbCrLf
Next
MsgBox(strClient)
Next
=======
EDIT 3:
I'm attempting to process a 5010 file; OOPFactory says "The built-in specs contain all 4010 standards and some 5010 specifications" https:// x12parser.codeplex.com/ (can't post another working link yet due to lack of reputation points)
=======
Edit 4:
The failure seems to be happening in EligibilityTransformationService.cs on line 35. The correct information is making it into the XML, but is not deserializing properly.
var response = EligibilityBenefitDocument.Deserialize(responseXml);
I'm investigating why that might be.
=====
Edit 5:
In EligiblityTransformationService.cs, starting on line 32, the XML is transformed and then deserialized. The data in question is last seen on line 35 in the responseXml variable, but it never makes it into the response object.
It looks like an issue with the XSLT file.
transform.Transform(XmlReader.Create(new StringReader(xml)), new XsltArgumentList(), outputStream);
outputStream.Position = 0;
string responseXml = new StreamReader(outputStream).ReadToEnd();
var response = EligibilityBenefitDocument.Deserialize(responseXml);

I actually use this same method for my own work at the office. The issues we always run into is the response we receive is either null or random values. What we had to do was continue searching patient information until we found as many possible results that would come back to us. So for example, if we wanted to look up policy date information, we use:
var service = new EligibilityTransformationService();
EligibilityBenefitDocument eligibilityBenefitDocument = service.Transform271ToBenefitResponse(response271Stream);
eligibilityBenefitDocument.EligibilityBenefitResponses = eligibilityBenefitDocument.EligibilityBenefitResponses;
foreach (EligibilityBenefitInformation benefitInfo in eligibilityBenefitDocument.EligibilityBenefitResponses[0].BenefitInfos)
{
if (benefitInfo.InfoType.Code == "V")
return Tuple.Create(false, "Medicare cannot process");
if (benefitInfo.InfoType.Code == "6")
return Tuple.Create(false, "Inactive Policy");
if (benefitInfo.InsuranceType.Code == "HN" || benefitInfo.InsuranceType.Code == "12")
{
try
{
return Tuple.Create(false, "MADV " + benefitInfo.Identifications[0].Id + " " + benefitInfo.RelatedEntities[0].Name.LastName);
}
catch
{
return Tuple.Create(false, "MADV");
}
}
}
We still work off and on with these responses to try and get them as accurate as possible, but unfortunately, it seems like the codes can change for different payers, and its a bit time consuming figuring out how each one works until you get their possible response variations.
EDIT:
If there are no benefitInfos in the response, it means that you are submitting the incorrect patient Information. I have the following check in my program:
if(eligiblityBenefitDocument.EligiblityBenefitResponses[0].BenefitInfos.Count() < 1)
return "Subscriber Info Invalid"

Related

Trying to get my SSIS to continue running if a file doesn't exist

So, I am running SSIS (through VS) and I have two segments that hang me up when my clients don't send in the exact files every day. I have a task that deletes old files, and then renames the current files to the filename with _OLD at the end of it.
The issue is: If the files that are in there aren't the exact same, it crashes, failing the entire thing.
An example:
A client sends in on Monday files: Names, Addresses, Grades, Schools
The same client, on Tuesday sends in: Names, Addresses, Schools
Since the Grades file doesn't exist, it still gets renamed to Grades_OLD but the SSIS fails.
The scripts are:
del Names_OLD.csv
bye
This will then go to the Rename Script:
ren Names.csv Names_OLD.csv
bye
and will then go on to Addresses, to do the same thing. It is super frustrating that these fail when a single file doesn't exist the next day, and there doesn't seem to be a need for it.
We have two scripts that generate the archive data to process:
public void Main()
{
Dts.Variables["ARCHIVEFILE"].Value = Path.GetFileNameWithoutExtension(Dts.Variables["FTPFILE"].Value.ToString()) + "_OLD" + Path.GetExtension(Dts.Variables["FTPFILE"].Value.ToString());
Dts.TaskResult = (int)ScriptResults.Success;
}
and
public void Main()
{
/*PSFTP_DEL_script.txt
del %1
bye
PSFTP_REN_script.txt
ren %1 %2
bye
*/
var lineOut = String.Empty;
var File1 = Dts.Variables["User::FTPWORKINGDIR"].Value.ToString() + "\\SSIS_PSFTP_DEL_script.txt";
var File2 = Dts.Variables["User::FTPWORKINGDIR"].Value.ToString() + "\\SSIS_PSFTP_REN_script.txt";
lineOut = "del " + Dts.Variables["User::ARCHIVEFILE"].Value.ToString() + Environment.NewLine + "bye";
System.IO.File.WriteAllText(File1, lineOut);
lineOut = "ren " + Dts.Variables["User::FTPFILE"].Value.ToString() + " " + Dts.Variables["User::ARCHIVEFILE"].Value.ToString() + Environment.NewLine + "bye";
System.IO.File.WriteAllText(File2, lineOut);
Dts.TaskResult = (int)ScriptResults.Success;
}
Researching it doesn't really give anything helpful, and kind of just leads me back to where I am right now.
Try using a foreach loop on files for each file that can be processed and put all the processing of the file inside it. And do not put any precendence constraints between the foreach loops.
This will process the files that are there an not fail when the others aren't there.
The foreach loop essentially works as a check if the file exists.
This assumes you do not need all the files to properly process them.
Why not checking if the file exists before writing the script:
if (System.IO.File.Exists(Dts.Variables["User::ARCHIVEFILE"].Value.ToString())){
lineOut = "del " + Dts.Variables["User::ARCHIVEFILE"].Value.ToString() + Environment.NewLine + "bye";
System.IO.File.WriteAllText(File1, lineOut);
}
if (Dts.Variables["User::FTPFILE"].Value.ToString())){
lineOut = "ren " + Dts.Variables["User::FTPFILE"].Value.ToString() + " " + Dts.Variables["User::ARCHIVEFILE"].Value.ToString() + Environment.NewLine + "bye";
System.IO.File.WriteAllText(File2, lineOut);
}

Passing long querystrings over urls shows page not found error(404)

I have a "error.aspx" page which is there to mail me if any exception is caught. When I open the page manually, mysite.com/error.aspx, the page opens fine but when it is redirected by a catch block with the exception.message and exception.stackTrace as querystrings, I get an error "page not found". Are the querystrings directing the browser to open a different url? It works fine when run on localhost, though.
public void send_error(Exception ex)
{
Response.Redirect("error.aspx?time=" + DateTime.Now.ToString() + "&ex=" + ex.Message + "&st=" + ex.StackTrace.Replace("\n", " "), false);
}
If you check this Article, you will see that the max query length of url string is 2048 symbols for Internet explorer. Probably the url is bigger and because of that you have this problem. One solution is to save the desire message in the session as string and after that retrieve it on other pages.
string errorMessage = DateTime.Now.ToString() + " " + ex.Message + " " + ex.StackTrace.Replace("\n", " ");
Session["__ErrMessage"] = errorMessage;
When you are in other pages you can access this string like this:
string errMessage = "";
if(Session["__ErrMessage"] != null)
errMessage = Session["ErrMessage"].ToString();

ASP.NET can't create Windows Event Log even as Administrator

I'm working on an ASP.NET web application in Visual Studio 2013 and as part of the main error routine, I want it to store the errors in a Windows Event Log. However, every time I run the code, the log never gets created even when I run Visual Studio as Administrator. Would turning off UAC fix this? Code is below. Any help is appreciated. Thanks.
public static void ErrorRoutine(Exception e, string obj, string method)
{
EventLog.Delete("LogName"); // uncomment this line to delete log
EventLog log = new EventLog();
log.Source = "SourceName";
log.Log = "LogName";
if (e.InnerException != null)
{
log.WriteEntry("Error in Models, object = " + obj + ", method = " + method + ", inner exception = " +
e.InnerException.Message, EventLogEntryType.Error);
throw e.InnerException;
}
else
{
log.WriteEntry("Error in Models, object = " + obj + ", method = " + method + ", message = " + e.Message,
EventLogEntryType.Error);
throw e;
}
}
Edit: I get that this is probably not best practice but this project is actually an assignment for college and this is the exact code we were told to write, as well as being told to run VS as Administrator. I just need to find a way to make work really.

Opening a PDF with search parameters just opens the PDF

I was requested to add some searching functionality to an existing system for the collection of PDFs that we have. I know about searching PDFs and opening them with search parameters and in a test application I wrote, it works like a dream. When trying to convert it over to our existing application the PDF opens but without the search terms or the advanced find of Acrobat Reader popping up. Any help would be greatly appreciated!
Here is a snippet of the cs code :
case "PDF":
string searchTerms = SearchWordsTB.Text;
searchTerms = searchTerms.Replace(',', ' ');
launchStr = "OpenPDF('" + e.Row.Cells[9].Text.Replace("\\", "/") + "','" + HttpUtility.UrlEncode(e.Row.Cells[2].Text) + "','" + e.Row.Cells[0].Text + "','" + searchTerms + "')";
break;
We are creating the list of documents on the fly and PDF is one of the options. Assuming I am understanding this correctly, A DataGrid is created with all these clickable rows that will execute a Javascript function when clicked. The Javascript function OpenPDF is shown below:
function OpenPDF(url, filename, ID, searchTerms) {
if (searchTerms.length > 0) {
window.open('FileViewer.aspx?name=' + filename + '&ID=' + ID + '&url=' + url + '#search="' + searchTerms + '"', 'mywindow' + windowCnt, 'width=800,height=600,location=no,resizable=yes');
}
else {
window.open('FileViewer.aspx?name=' + filename + '&ID=' + ID + '&url=' + url, 'mywindow' + windowCnt, 'width=800,height=600,location=no,resizable=yes');
}
windowCnt++;
}
From following the debugging in the CS code, I know that I am properly stripping out the commas in the search terms so that shouldn't be the problem. What currently happens is the PDF file will open up just fine, but the search terms are not being used. I have tried following the debugger through the Javascript (which for me has always been spotty at best) but the breakpoint is never hit. It should also probably be noted that the Javascript function is kept in a separate Javascript File and is not inline in the aspx page. And yes, we are correctly referencing the Javascript file. I will be more than happy to update this post with any extra info that is requested. Thanks in advance for any help!
I was able to achieve the desired results by using the http encode on the launch string as shown below.
launchStr = "OpenFile('" + HttpUtility.UrlEncode(e.Row.Cells[9].Text.Replace("\\", "/") + "#search=\"" + searchTerms + "\"") + "','" + HttpUtility.UrlEncode(e.Row.Cells[2].Text) + "','" + e.Row.Cells[0].Text + "','" + e.Row.Cells[1].Text + "')";
I then used the function to just open the window with the PDF in it. The problem I had was that without the HTTP Encode, the URL was just cutting off the search parameters. I believe this is because the #search="blah" isn't normally recognized as part of a URL and was therefore truncated. If anyone has a better reason, I would love to hear it.

How to get the current project name in C# code?

I want to send an email to myself when an exception is thrown. Using StackFrame object, I am able to get File Name, Class Name and even class method that throw the Exception, but I also need to know the project name as many of my ASP.NET project has the same file name, class name and method.
This is my code:
public static string JndGetEmailTextForDebuggingExceptionError(this Exception Ex)
{
StackFrame sf = Ex.JndGetStackFrame();
string OutputHTML = "<i><b><u>For Developer Use Only: </u></b></i>" + "<br>" +
"<br>" +
"Project Name: " + HttpContext.Current.ApplicationInstance.GetType().Assembly.GetName().Name + "<br>" + //Under discussion
"File Name: " + sf.GetFileName() + "<br>" +
"Class Name: " + sf.GetMethod().DeclaringType + "<br>" +
"Method Name: " + sf.GetMethod() + "<br>" +
"Line Number: " + sf.GetFileLineNumber() + "<br>" +
"Line Column: " + sf.GetFileColumnNumber() + "<br>" +
"Error Message: " + Ex.Message + "<br>" +
"Inner Message : " + Ex.InnerException.Message + "<br>";
return OutputHTML;
}
Thanks ALL.
You can use Assembly.GetCallingAssembly if you have your logging code in a separate library assembly, and call directly from your ASP.NET assembly to your library, and you mark the method so that it won't be inlined:
[MethodImpl(MethodImplOptions.NoInlining)]
public static string JndGetEmailTextForDebuggingExceptionError(this Exception Ex)
{
StackFrame sf = Ex.JndGetStackFrame();
string OutputHTML = "<i><b><u>For Developer Use Only: </u></b></i>" + "<br>" +
"<br>" +
"Project Name: " + Assembly.GetCallingAssembly().GetName().Name + "<br>" +
"File Name: " + sf.GetFileName() + "<br>" +
"Class Name: " + sf.GetMethod().DeclaringType + "<br>" +
"Method Name: " + sf.GetMethod() + "<br>" +
"Line Number: " + sf.GetFileLineNumber() + "<br>" +
"Line Column: " + sf.GetFileColumnNumber() + "<br>" +
"Error Message: " + Ex.Message + "<br>" +
"Inner Message : " + Ex.InnerException.Message + "<br>";
return OutputHTML;
}
On any entry points in your library that can end up wanting to log the project name, you'd have to record the calling assembly and mark it NoInlining, then pass that around internally.
If you're using .NET 4.5, there's an alternative way to do this: CallerFilePath. It has the same restrictions on entry points, and it returns the source path on your machine instead of the assembly name (which is probably less useful), but it's easier to know that it'll work (because it compiles it, just like optional parameters are compiled in), and it allows inlining:
public static string JndGetEmailTextForDebuggingExceptionError
(this Exception Ex, [CallerFilePath] string filePath = "")
{
StackFrame sf = Ex.JndGetStackFrame();
string OutputHTML = "<i><b><u>For Developer Use Only: </u></b></i>" + "<br><br>" +
"Source File Path: " + filePath + "<br>" +
...
For anyone looking for an ASP.NET Core compatible solution, the following should work;
System.Reflection.Assembly.GetEntryAssembly().GetName().Name
.NET Core API Reference
This ought to be enough
string projectName = Assembly.GetCallingAssembly().GetName().Name;
Edit* If you are running this from another assembly then you should use GetCallingAssembly instead.
You can use
HttpContext.Current.ApplicationInstance.GetType().Assembly.GetName().Name
If this returns App_global.asax...., change it to
HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Name
If you aren't running in an HTTP request, you will need some way to get ahold of the HttpContext.
This will return different results if you're in a Web Site project (as opposed to Web Application).
You can also use HttpRuntime.AppDomainAppPath to get the physical path on disk to the deployed site; this will work everywhere.
Reflection is the best way to find out product name,company name version like information.
public static string ProductName
{
get
{
AssemblyProductAttribute myProduct =(AssemblyProductAttribute)AssemblyProductAttribute.GetCustomAttribute(Assembly.GetExecutingAssembly(),
typeof(AssemblyProductAttribute));
return myProduct.Product;
}
}
And Another way like get direct project name
string projectName=System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location).ToString();
Just adding my answer here.
For those who work with multiple Dlls in their projects, the correct answer is:
string projectName = Assembly.GetExecutingAssembly().FullName.Split(',')[0];

Categories