Showing posts with label Gotcha. Show all posts
Showing posts with label Gotcha. Show all posts

Saturday, July 27, 2013

Using Oracle in a standalone .NET application

Our goal is to set up standalone .NET application without dependency on installed Oracle client in our system. In other words, our application should contain all necessary dll's in the bin folder of our project .

We need following dll's from Oracle client :
  • oci.dll
  • OraOps11w.dll
  • oraocci11.dll
  • orannzsbb11.dll
  • oraociei11.dll
  • Oracle.DataAccess.dll
You can get them from installed version of your Oracle client. In my case it was 11.2 version of Oracle client.
You can put this assemblies in some folder in your solution, let's say this folder is named "Components".
Now you can refer Oracle.DataAccess in your solution projects whenever you need. So, Oracle.DataAccess will get to the bin folder of your project when you'll build it.

But we need other Oracle libs to be in the bin folder too! How to force this to happen?

You can achieve this using Pre-Build Events of your project. Go to Properties of your project, then select the Build Events tab and paste the following lines in Pre-build event box:

copy $(ProjectDir)\..\..\Components\oci.dll $(TargetDir)
copy $(ProjectDir)\..\..\Components\OraOps11w.dll $(TargetDir)
copy $(ProjectDir)\..\..\Components\oraocci11.dll $(TargetDir)
copy $(ProjectDir)\..\..\Components\orannzsbb11.dll $(TargetDir)
copy $(ProjectDir)\..\..\Components\oraociei11.dll $(TargetDir)

Maybe, you'll need to correct paths for your case, but you should get the idea: these Oracle libraries will be copied into the bin folder of your project before the each build.
So, after each build you will get standalone application(with all necessary Oracle client libs), that can run on any computer without the need to install Oracle on this computer.

Tuesday, March 12, 2013

Preloading assemblies from Application folder in C#

As you may know, AppDomain.CurrentDomain.GetAssemblies() returns list of assemblies that are loaded in current Application Domain. Even if your executing project has reference to some assembly there is no guarantee that this assembly has been already loaded. It will be loaded lazily on first use. But what if you need all assemblies now? For example, you want to search assemblies for classes that implement some interface or something else.

You can easily force loading assemblies into your Application Domain.

Let's create helper class to return list of all files in our Application folder(Bin folder in case of Web Application):
 public static class From  
 {  
   public static IEnumerable<FileInfo> AllFilesIn(string path, bool recursively = false)  
   {  
     return new DirectoryInfo(path)  
               .EnumerateFiles("*.*", recursively ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);  
   }  
   public static IEnumerable<FileInfo> AllFilesInApplicationFolder()  
   {  
     var uri = new Uri(Assembly.GetExecutingAssembly().CodeBase);  
     return AllFilesIn(Path.GetDirectoryName(uri.LocalPath));  
   }  
 }  

So, now you can preload assemblies as follows:
 From.AllFilesInApplicationFolder().Where(f => f.Extension == ".dll").ForEach(fi => Assembly.LoadFrom(fi.FullName));  

This solution is applicable both for Desktop and Web Applications.

Wednesday, December 26, 2012

Implement GetHashCode() to track changed objects in C#

Let's say we pull information about Movies from remote XML and save it in our database. Class that represent this objects can look like:
 public class Movie  
 {  
     public int Id { get; set; }  
     public string Name { get; set; }      
     public int? Duration { get; set; }  
     public int? Director { get; set; }      
     public int[] Actors { get; set; }      
     public int[] Genres { get; set; }      
     public int[] Countries { get; set; }      
     public string PosterUrl { get; set; }  
     public double? Rate { get; set; }  
     public int? Votes { get; set; }  
     public double? Imdb { get; set; }  
     public int? ImdbVotes { get; set; }  
     public string Site { get; set; }  
     public string Limits { get; set; }  
     public DateTime? Date { get; set; }  
     public string Description { get; set; }  
     public string Trailers { get; set; }  
     public string Company { get; set; }      
 }  

Write operations are expensive if there are a lot of objects to be saved, so for performance reasons we should NOT save new object in database, if there is old object in database that is the same. So we need to extract object from databse and determine if new object differ from the old one. If objects are the same we DO NOT update it.

But how to determine that objects are the same?

Objects are differ if their contents differ. In our case we can clarify this as follows: Objects are differ if their properties are differ.

Let's override GetHashCode() and Equals() methods to define how to check equality of 2 Movie objects:
 public class Movie  
 {  
    public int Id { get; set; }  
    public string Name { get; set; }  
    public int? Duration { get; set; }  
    public int? Director { get; set; }  
    public int[] Actors { get; set; }  
    public int[] Genres { get; set; }  
    public int[] Countries { get; set; }  
    public string PosterUrl { get; set; }  
    public double? Rate { get; set; }  
    public int? Votes { get; set; }  
    public double? Imdb { get; set; }  
    public int? ImdbVotes { get; set; }  
    public string Site { get; set; }  
    public string Limits { get; set; }  
    public DateTime? Date { get; set; }  
    public string Description { get; set; }  
    public string Trailers { get; set; }  
    public string Company { get; set; }  
    
    public override int GetHashCode()  
    {  
       return HashCodeGenerator.Generate(Id, Name, Duration, Director, Actors, Genres, Countries, PosterUrl, Rate, Votes, Imdb, ImdbVotes, Site, Limits, Date, Description, Trailers, Company);  
    }  
    public override bool Equals(object obj)  
    {  
       return this.GetHashCode() == obj.GetHashCode();  
    }        
  }  

As you can see, we use custom class HashCodeGenerator to generate hash code from specified property values that we need to track.

Implementation of this class:
  public static class HashCodeGenerator  
  {  
     public static int Generate(params object[] objects)  
     {  
       unchecked  
       {  
         var offset = 13;  
         var compositionOffset = 7;  
         foreach (object obj in objects)  
         {  
           if (obj==null)  
             continue;  
           if (obj is Array)  
           {  
             var array = obj as Array;  
             foreach (var item in array)  
             {  
               offset = (offset * compositionOffset) + item.GetHashCode();  
             }  
           }  
           else  
           {  
             offset = (offset * compositionOffset) + obj.GetHashCode();  
           }            
         }            
         return offset;  
       }  
     }      
   }  

Wednesday, November 7, 2012

Static polymorphism and dynamic keyword in C#

Static Polymorphism - is kind of polymorphism also known as function overloading(or operator overloading).

Static polymorphism means that functions can be applied to arguments of different types, different number and sequence of arguments.
The various types of parameters are specified at compile time, so the function can be bound to calls at compile time. This is called early binding.

Example of static polymorphism:
 class Program  
 {  
   class A { }   
   class B { }  
   private static void Foo(A a)   
   {   
     //something   
   }   
   private static void Foo(B b)   
   {   
     //something   
   }   
   static void Main(string[] args)  
   {   
     A a = new A();   
     Foo(a);   
     B b = new B();   
     Foo(b);   
   }  
 }  

In this example we exactly know the type of object(A or B) and corresponding Foo method that should be called.

Let's say we get object from the third-party method and we do not know exactly real type of the object(A or B). We can get this object and then cast reference to A(or to B) and call corresponding Foo method. Or we can use nifty dynamic keyword:
 public class ThirdPartyClass  
 {  
   public static IObject GetObject()  
   {  
     //something  
   }  
 }  
 class Program  
 {  
   class A { }   
   class B { }   
   private static void Foo(A a)   
   {   
     //something   
   }   
   private static void Foo(B b)   
   {   
     //something   
   }   
   static void Main(string[] args)   
   {   
     dynamic d = ThirdPartyClass.GetObject();  
     Foo(d);   
   }  
 }  

In this example, actual type of the variable d that’s declared dynamic is resolved at run time. If variable d is not of type A or B then exception will be thrown, because of trying to call method Foo with incompatible argument type.

Monday, October 22, 2012

Cookie value is nulled when using Response.Cookies

I have the following code to check if Cookie with name "city" already exists in Response.Cookies collection:
 if (HttpContext.Current.Response.Cookies["city"]!=null)   
   return HttpUtility.UrlDecode(HttpContext.Current.Response.Cookies["city"].Value);  

But to my big surprise this code is not working in that way that i expected. This code resets Cookie value to NULL when i am trying to check if Cookie value is not NULL.

Here the code that works fine for me:
 if (HttpContext.Current.Response.Cookies.AllKeys.Contains("city"))  
   return HttpUtility.UrlDecode(HttpContext.Current.Response.Cookies["city"].Value);  


Monday, October 15, 2012

How to remove component in Castle Windsor 3.0?

Say we have registered component in Castle Windsor:
 Container.Register(Component.For<IRegistrator>().ImplementedBy<TestRegistratorWhichReturnsGoodResult>());  

Sometimes in Unit tests i need to remove registered component from Castle Windsor and to register new one. Prior to 3.0 version we can do this:
 Container.Kernel.RemoveComponent(typeof(TestRegistratorWhichReturnsGoodResult).FullName);  
 Container.Register(Component.For<IRegistrator>().ImplementedBy<TestRegistratorWhichReturnsBadResult>());  

Аfter version 3.0 breaking changes we can't do this, because there is no RemoveComponent method in version 3.0.
But we can use the following approach:
  class RegistrationHandlerSelector :IHandlerSelector  
       {  
         public static bool UseBadResultRegistrator { private get; set; }  
         public bool HasOpinionAbout(string key, Type service)  
         {  
           return service == typeof(IRegistrator);            
         }  
         public IHandler SelectHandler(string key, Type service, IHandler[] handlers)  
         {  
           return handlers.First(x => UseBadResultRegistrator ? x.ComponentModel.Implementation == typeof (TestRegistratorWhichReturnsBadResult ) :  
                                      x.ComponentModel.Implementation == typeof (TestRegistratorWhichReturnsGoodResult ));                      
         }  
       }  

 Container.Register(Component.For<IRegistrator>().ImplementedBy<TestRegistratorWhichReturnsGoodResult>());  
 Container.Register(Component.For<IRegistrator>().ImplementedBy<TestRegistratorWhichReturnsBadResult>());  
 Container.Kernel.AddHandlerSelector(new RegistrationHandlerSelector());  

Now we can use RegistrationHandlerSelector.UseBadResultRegistrator field to choose which component to use.

Friday, October 12, 2012

Transferring to error pages from Application_Error handler in MVC3

Our task is to implement transferring(not redirection) to correspond error page when error occurs in ASP.NET MVC3 application.

Good solution for redirection to error pages is to use <customErrors> section in web.config. But we need transferring for SEO purposes.

So it was obvious to use httpErrors section instead of customErrors section:
  <httpErrors errorMode="Custom" existingResponse =" Replace" >  
     < clear />  
     < error statusCode =" 403" path= "/Error/Forbidden " responseMode="ExecuteURL" />  
     < error statusCode =" 404" path= "/Error/NotFound " responseMode="ExecuteURL" />  
     < error statusCode =" 500" path= "/Error/InternalError " responseMode="ExecuteURL" />  
   </ httpErrors>  

It's good solution, but it works only when your application is under website root. If your application is under virtual directory transferring will be broken.

The only solution i found is to use Application_Error handler in Global.asax instead of config:
 protected void Application_Error(object sender, EventArgs e)  
     {        
       var exception = Server.GetLastError();  
       if (Context.Request.IsLocal)  
         return;  
       var actionName = "InternalError";  
       if (exception is HttpException)  
       {  
         var code = (exception as HttpException).GetHttpCode();  
         switch (code)  
         {  
           case 400:  
             actionName = "NotFound";  
             break;  
           case 403:  
             actionName = "Forbidden";  
             break;  
           case 404:  
             actionName = "NotFound";  
             break;  
         }  
       }        
       var path = string.Format( "~/Error/{0}/" , actionName);        
       Server.TransferRequest(path, false);        
     }  

Code is obvious and it works fine almost for all cases. ALMOST, but not for all.

I am sure you know popular ASP.NET exception "A potentially dangerous Request.Form value was detected from the client". This exception happens when you(or ASP.NET) try to extract QueryString values, but there is "potential dangerous" in values: html tags, for example.

So, exception happens, then our Application_Error handler fires. Then we use Server.TransferRequest which PRESERVE QueryString of current request despite on second "false" parameter. Now we have "potential dangerous" again in our QueryString during this transferring, which wll trigger Application_Error again, and so on.  What we get here is cyclical transferring that can kill Application Pool easily.

To force Server.TransferRequest NOT to save QueryString of current request you have to specify QueryString explicitly in your transferring URL. For example:
 var path = string.Format( "~/Error/{0}/?transfer=1" , actionName);