How to troubleshoot Oracle Data Provider for .NET aka ODP.NET

Unmanaged  Jerry and I’m lovin’ every minute of it!

We’ve been using the unmanaged Oracle Data Provider for .NET as part of a production software suite for quite some time. Ideally one would use the managed version, but for a variety of reasons including the fact that some functionality from the unmanaged version is not available in the managed version we continue to have to use the unmanaged version.

Oracle.DataAccess.dll is a managed assembly, but it calls out to the unmanaged provider code in OraOps12.dll using a specific search order that has nothing to do with how .NET loads assemblies.

The Oracle.DataAccess.dll checks the version of the unmanaged DLL it finds and if it does not match up exactly with the version it expects then it throws an exception like this…

The provider is not compatible with the version of Oracle client

One of the main issues with resolving this problem in ODP.NET installations prior to 18c is that the Oracle.DataAccess.dll is installed in the GAC by the provider installer. Also, if you had a previous version of ODP.NET installed then the installer will add policy files that redirect from the older version to the newer version. Policy files are just assemblies with configuration embedded in them. That configuration implements a binding redirect in the same fashion as you would if you were doing it through configuration.

There are numerous problems with a publisher trying to automatically redirect versions via policy files, but then you also have the issue of said assembly having to locate a set of unmanaged files that exactly match a particular version. In addition, if you deployed the Oracle.DataAccess.dll assembly in your application bin folder and some or all of your application uses late binding calls to load Oracle.DataAccess.dll that don’t specify a particular assembly version, then you’re going to end up even more confused since your application will not load the assembly from the GAC and will instead load the one from your local bin folder which may or may not be compatible with the provider that you have installed.

This last point became a problem for us with using NHibernate, because it does late binding in this fashion (to be fair due to the ODP.NET versioning issue there is really no other way for it to go and we’ll see how to fix this in a bit).

Troubleshooting

There are several things you can do to discover where your issues are happening.

Fusion Log Viewer

You should definitely use Fusion Log Viewer to see from where your application is attempting to load Oracle.DataAccess.dll and what version it is attempting to load. This is likely going to give you the primary reason you are getting the provider compatibility error. If your application looks finds a 12.1 DLL in the local bin and your provider is 12.2 you have your answer. Usually it’s as simple as that, but if you have installed multiple ODP.NET providers onto the same machine it could get more complicated as you are then possibly dealing with Policy files in the GAC redirecting from one version to another. In that case you will need to examine the gac using gacutil looking for assemblies named Policy.VERSION.Oracle.DataAccess.dll.

Compatibility and Binding Redirects

Despite this requirement that each version of Oracle.DataAccess.dll be matched to a particular unmanaged version of the provider, in the majority of cases you can still use a binding redirect to point your application to a newer (or older) version of the managed Oracle.DataAccess.dll client assembly even if the exact version is not installed. Most basic functionality is unchanged from one version to another so a binding redirect in your client application’s config file is all you need to solve the issue.

<dependentAssembly>
<assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89b483f429c47342"/>
<bindingRedirect oldVersion="4.112.1.0" newVersion="4.122.1.0" />
</dependentAssembly>

The other issue is with late binding and the GAC. Without specifying the fully qualified assembly name a late binding call will not load an assembly from the GAC. In some cases you may not want to ship the Oracle.DataAccess.dll with your application since it requires the customer to install ODP.NET anyway. In this case, if you have issues with late binding from third party apps such as NHibernate you can add a Qualify Assembly element to your application configuration that specifies the particular version you want to load and any unqualified calls will use the version you specify.

<qualifyAssembly partialName="Oracle.DataAccess"
             fullName="Oracle.DataAccess,
                            Version=4.122.1.0,
                           Culture=neutral,
                           PublicKeyToken=89b483f429c47342" />

Debugging VBScript / ASP pages in the year 2017, with Visual Studio 2015 (VS2015)

Ah, another year and I still need to debug VBScript code in ASP pages. I had hoped to forget how to do this and I did, but then I needed to do it again so I had to go “remember” / Google how to do it again. I’m kind of amazed that I can debug this stuff in VS2015 and of course I’m putting this all on here so that when I forget again I won’t have to search very far to find the information.

I was doing this on Windows 2008 with the full version of IIS, so YMMV with other versions of Windows. This also assumes you are an Administrator on the box. In my case this was a DEV/QA VM I was using so my account had administrative privileges.

First make sure you have ASP installed on your box by going into Roles under Server Manager and adding the ASP Role Service under Application Development.

Once this is done you might need to reset IIS and also reload the IIS Manager snap-in if you already had it open. I noticed the ASP option for the website did not appear until I reloaded the snap-in.

Navigate to your website in IIS Manager and in the center pane look for ASP under the IIS heading. Double click on that option to open the feature menu.

Expand the Debugging Properties section by clicking on the + next to it.

From there you will likely want to flip the option for “Enable Server-side Debugging” to True at the least. I flipped “Enable Client-side debugging” to true as well as I could not recall if some VBScript was used in that fashion in my ancient app.

Once that is all done you are ready to rock and roll with VS2015. For an ASP site what you will want to do is open up a new instance of VS2015. Then you will use the File – Open – Web Site option which takes you to a view of your local IIS. Your ASP site or app will need to be installed in there. Find your site/app and open it up and it will load up the structure of your site in the Solution Explorer.

At this point you should run your site in the browser so that IIS starts up. Use Debug – Attach To Process and choose the W3WP process (different process on certain versions of Windows) making sure that you are debugging using “Script Code” otherwise you will get nothing.

Set some breakpoints in your code and you should see results!

XSLT to display an XML document as HTML

I had a quick and dirty project to take some XML that was stored in our database and display it on a web page in an existing site. Normally I’d have a fairly large amount of client side tooling to perform this job, but the site was entirely based in WebForms and I really did not want to add new dependencies to the project. It became clear that the quick and dirty version of this involved using the Xml web control and binding the XML and XSL to the control. There are a bunch of articles on MSDN that purport to show you how to do this that end up being tedious.

The reality is that you can add this to your ASPX page.

<asp:Xml ID="XmlDisplay" runat="server" />

Then something like this to your codebehind

XmlDisplay.DocumentContent = MyXmlDocOrElement.ToString(); 
XmlDisplay.TransformSource = HttpContext.Current.Server.MapPath(@"../PathToMyXslt/MyXslt.xsl"); 
XmlDisplay.DataBind();

And you’ve got your XML on your page.

Then the only thing that is left is the XSLT to make your XML look pretty on the page. I actually had very little XSLT experience and took a few wrong turns trying to cook something up that would do this that involved using recursion and printing out all the values using individual XSL tags that I generated. This ended up being stupidly complex, but despite my ignorance I had a sense that I was doing something wrong so I took a step back and a co-worker and I talked for a bit and he mentioned that he thought XSLT just sort of did what I was trying to do with code. Well, turns out he was right. Now, to be fair, the XML I needed to display has no attributes, so this is really just printing out element names and values, but with a little work you could also find attributes fairly easily.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
	<xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes" />
	<xsl:template match="/">
		<div class="root">
			<xsl:for-each select="//*">
				<div>
					<xsl:choose>
						<xsl:when test="not(text())">
							<div class="col-name{count(ancestor::*)} col-empty-value" title="{name()}">
								<xsl:value-of select="name()"/>
							</div>
						</xsl:when>
						<xsl:otherwise>
							<div class="col-name{count(ancestor::*)}" title="{name()}">
								<xsl:value-of select="name()"/>
							</div>
							<div class="col-value{count(ancestor::*)}" title="{text()}">
								<xsl:value-of select="text()"/>
							</div>
						</xsl:otherwise>
					</xsl:choose>
				</div>
			</xsl:for-each>
		</div>
	</xsl:template>
</xsl:stylesheet>

This XSL will take any XML that is formatted as only elements and element values and print it out as a series of DIVs.

The meat of making this a decent looking display is the ability to apply dynamic CSS class names to the HTML elements you render from the XSLT as you go down the tree of XML. As the XSLT iterates over the various elements using xsl:for-each you can use count(ancestor::*) to apply a numeric value to your class name indicating the depth.

You could also probably cook up a table structure using this same method.

ASP.NET MVC strongly typed model binding to a collection with zero values.

I wasn’t quite clear how to do this and I’m not sure my solution is the best approach, but it certainly falls within the realm of normal functionality included in ASP.NET MVC.

The page I wanted to have was a partial view that listed out comments associated with a particular model object. So, if someone posted a comment on a particular Project object then I wanted to pass the object type and value to the partial view and have it render all the comments associated with that that object’s value.

So One Project has Many Comments.

The Comment partial view was to show the list of comments and then if the user was logged in it would also display a comment box for them to submit a new comment.

I wanted to bind the comment box fields to the model so that my DataAnnotations would show up properly. The only problem is that if you have a collection bound to your view it isn’t particularly straightforward binding only one set of values to your input fields. It’s quite easy to iterate over fields in your collection and use strongly typed helper methods to render each item, but if you only want one set of fields it becomes onerous.

Here is the solution I came up with (which is probably obvious to some, but for some reason I couldn’t find this when searching).

@model IEnumerable<Comment>

@if (Model != null)
    {
        foreach (var item in Model)
        {
            <div>Posted On: @item.DateCreated</div>
            <div>Last Updated On: @item.DateModified</div>
            <div>Subject: @item.Title</div>
            <div>Comment: @item.CommentText</div>     
            <div>Posted By: @item.UserInfo.UserName</div>
            <div>------</div>
        }
    }
        
    Html.RenderPartial("CommentSubmit", (IEnumerable<Model.Comment>)ViewBag.Comments, new ViewDataDictionary() { new KeyValuePair<string, object>("objid", objectid), new KeyValuePair<string, object>("objtype", objecttype) });

This is the main page, where the collection is rendered out and then at the bottom we call the helper method Html.RenderPartial, which in this case is actually pretty helpful in that you can pass

WTF is a VB.NET Module?

We still have an old VBScript app at my work and in an effort to eliminate it and replace it with something .NET we’ve started porting it to VB.NET. I won’t go into why it isn’t being completely rewritten.

Anyway, the app has a host of include files and when I started looking to move this functionality over I found that VB.NET can instantiate what are called Modules. For C# types like myself a Module is basically a static class that exists at the namespace level. It’s kinda awesome and also kinda crazy, because once you declare a function or subroutine in a module it is directly callable from anywhere in that namespace. Meaning, unless you duplicate the function/subroutine name you can just call that function/subroutine without any qualifier.

Public Module myModule
    Sub DoSomeStuff()
        Dim userName As String = InputBox("What is your name?")
        MsgBox("User name is" & userName)
    End Sub 
    ' Insert variable, property, procedure, and event declarations. 
End Module

Public Class myClass
    Public Function Start
        DoSomeStuff()
    End Function
End Class

I plan to continue to avoid VB.NET as much as possible, as I have for the last ten years since I gave up VB programming, because I find it syntactically verbose compared to C#, but this is still interesting and a nice holdover to allow one to essentially cut and paste a VBScript include into a file in VB.NET and have it work (given certain syntactic differences).

This is also a nice VBScript to VB.NET conversion page.

Update 1/29/2015: Also just to note that Visual Studio 2008 and earlier have tooling that will convert VB code into VB.NET. Later versions do not have this.

Windows Live Writer and Proxies

I started using Windows Live Writer for another blog mostly for the picture uploading and editing which is pretty nice. That said I had some issues behind a proxy which I only found when I enabled verbose logging. The major problem being that essentially the only error it gives in the GUI is “bad password.” Then I found out how to get it to use Windows Authentication behind a proxy and all was well. Essentially adding these lines to the exe.config file after the configuration element starts enables default authentication.

<system.net>
<defaultProxy enabled=”true” useDefaultCredentials=”true”>    </defaultProxy>
</system.net>

WPF Compiling for 64 Bit – undefined clr namespace

I was building a rough WPF application on my 64 bit Windows 7 box and it uses the 64 bit Oracle client so I set my solution to compile as 64 bit. When adding references to even local assemblies in my XAML I kept getting this undefined clr namespace error.

I searched around for a bit and found a few links that didn’t help. Most of them dealt with people referring to namespaces that were in non-local assemblies, but what I wanted to use was a local class. I had a simple namespace reference like this…

xmlns:local="clr-namespace:TPPMonitor"

and it wouldn’t work. At least, it wouldn’t work in the designer. Everything compiled fine.

Finally I read down a bit on this thread and found the solution to this issue.

It seems as if VS2010 can’t use reflection to query 64 bit assemblies in the designer. Switching to x86 in my solution settings enabled me to use the designer properly (which I kind of wanted to do because it was easier to setup a DataGrid using the designer than by hand).

Stackoverflow Exception using HTML.RenderPartial ASP.NET MVC

Lesson learned. Don’t name your partial views the same as your normal views.

Login.cshtml under Views/Shared
Login.cshtml under Views/Login tries to call Html.RenderPartial(“Login”)

Stackoverflow Exception because the rendering engine ends up searching the Views/Shared after everything else and ends up recursively calling Views/Login/Login.cshtml.

Renaming the shared View to _Login.cshtml obviously fixed the issue.

Partial Views explained:
http://bradwilson.typepad.com/blog/2008/08/partial-renderi.html

jQuery Append, markitup and textarea annoyances.

I’m using markitup for a textbox editor. I’m also using jQuery UI for dragging and dropping.

I wanted to drag and drop images onto the textbox that is being formatted by markitup and have the image url show up in the box. I started out using append to do this and it seemed to be working fine with code like this.

$("#texteditor").droppable({
  drop: function( event, ui ) {
    $(this).append("[img]" + ui.draggable.children()[0].src + "[/img]");
  }
}).attr("contentEditable", true);

I added the markitup functionality and all seemed well, but then I noticed a problem in Firefox. When I first loaded the page I could drag images onto the box and all was fine, but if I typed some text into the box and then tried to drag an image nothing seemed to happen. There was no update to the text in the box. I tried this in IE and everything still worked. I went back to Firefox and started Firebug and surprisingly the DOM was being updated when I dragged the text over to the box, but for some reason it just was not showing up on the screen and when I tried to post the text back to the server it didn’t pick up the updates either.

After looking at the various options here I ended up changing things up in the code so it looks like this now.

$("#texteditor").droppable({
  drop: function( event, ui ) {
    $(this).val($(this).val() + "[img]" + ui.draggable.children()[0].src + "[/img]");
  }
}).attr("contentEditable", true);

Everything seems to work in IE and Firefox with this update. I’m really not sure what caused my problem here, but my knowledge of the DOM and jQuery is not such that I will pursue it beyond this.

Logging a message to a file for debugging purposes using C#.

There are any number of times where I find myself puzzled over a problem that exists on a remote server and cannot be reproduced on my local development box. There are different ways to solve this, but sometimes it’s just helpful to have a way to log messages to a file. This last incident involved OpenLDAP and it returning different types from a search of attributes depending on which box I was running it on.

Blatantly stolen from here.

using System.IO;
        
public string GetTempPath()
{
    string path = System.Environment.GetEnvironmentVariable("TEMP");
    if (!path.EndsWith("\\")) path += "\\";
    return path;
}

public void LogMessageToFile(string msg)
{
    System.IO.StreamWriter sw = System.IO.File.AppendText(
        GetTempPath() + "My Log File.txt");
    try
    {
        string logLine = System.String.Format(
            "{0:G}: {1}.", System.DateTime.Now, msg);
        sw.WriteLine(logLine);
    }
    finally
    {
        sw.Close();
    }
}