Archive

Archive for the ‘.net 2.0’ Category

Setting the ViewPort for iPhone/iTouch Ready Web Sites

January 13, 2009 Comments off

Scenario:

After rolling out two new web applications targeted for WindowsMobile and Blackberries, we had a request to test and support Apple iPhone/iTouch devices.  Not a big deal, or so I thought.

Unfortunately, Safari on these devices displayed properly, but every page required zooming and was almost impossible to read.  There had to be a way to get Safari to respect the set width of the page rather than scale it out.

Solution:

Michael: “are you setting the viewport?”

Thanks to Google and a bit of help from a friend (thanks Michael!), the mysterious solution was just a meta tag away.  The best place to start would be the “Safari Web Content Guide for iPhone OS”.  I had found bits of this document elsewhere, but the information about the Viewport tags are extremely helpful.

The default viewport width is 980px; however, you can hard code the width of your page.  I placed the following tag in the <head> section of my MasterPage for the mobile site.

<!– meta tag for iPhone/iTouch devices –>

<meta name=”viewport” content=”width=350px” />

That worked; however, the HTML elements (buttons, selects, etc) were still far too small.  It seems that “fit to device” is more explicitly expressed with the device-width value.

<!– meta tag for iPhone/iTouch devices –>

<meta name=”viewport” content=”width=device-width” />

device-width not only fit the text to the screen, but also properly scaled the elements as well.

Excellent. ๐Ÿ™‚

I need to fully read that Safari Web Content Guide to see if there are other wonky tags for iDevice goodness. ๐Ÿ˜‰

PersistanceConfiguration for Oracle/Fluent NHibernate

December 4, 2008 1 comment

On Tuesday, I mentioned that I created a custom PersistanceConfiguration (based on the template for MS SQL) to connect to Oracle.  I had a few individuals email me, so I went ahead and tossed the code out on Google Code for everyone.

Feel free to download the source here.

The class derives FluentNHibernate’s PersistanceConfiguration<T> and uses the Oracle.DataAccess (ODP) driver. 

To use it, run through just like the MS SQL version.  I did, however, add an OtherOptions property to pass caching, pooling, and other Oracle-specific parameters.  I could have put each to a separate property (and may in the future)—as soon as I can get F-NHibernate fully working. Heh.  Priorities, right?

// Add our Oracle configuration to the NHibernate Config.

var oracleConfiguration = OracleConfiguration.Oracle9

.ConnectionString

      .Server(“server”)

      .Port(1521)

      .Instance(“instance.here”)

      .Username(“user”)

      .Password(“p@$$w0rd”)

      .OtherOptions(“Statement Cache Size=50;”)

      .Create;

oracleConfiguration.ConfigureProperties(config);

config.AddMappingsFromAssembly(Assembly.Load(_mappingAssembly));

Fluent NHibernate With Oracle – An Answer…

December 3, 2008 1 comment

Yesterday, I posted up a real annoying issue with getting Fluent NHibernate working with Oracle.  After dinking most of the evening, I found (as with most things) that the issue had little to do with NHibernate and a great deal to do with my lack of understanding.

Ahh, the joys of learning.

So, here’s where I glitched.

1. The ClassMap needs more than to have public constructors—but must be public itself. 

public class StudentMap : ClassMap<Student>

{

       public StudentMap()

       {

              WithTable(“Students”);

 

              Id(x => x.Id, “pupil_number”)

                     .GeneratedBy.Native();

              Map(x => x.FirstName, “first_name”);

              Map(x => x.LastName, “surname”);

 

       }

}

Whoops.

2. The connection string is touchy.  My original connection string looked like:

@“User Id={0};

Password={1};

Pooling=True;

Enlist=False;

Statement Cache Size=50;

Min Pool Size=10;

Incr Pool Size=5;

Decr Pool Size=2;

Data Source= (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
(HOST={2})(PORT={3})))(CONNECT_DATA=(SERVICE_NAME={4}))”

Unfortunately, that doesn’t seem to work with the non-ODP driver (aka: the Microsoft driver).  Statement Cache Size and the Pooling Size are unknown parameters.  That’s TOTALLY understandable and is easy to fix.

For now, I can simplify this to:

@“User Id={0};

Password={1};

Pooling=True;

Data Source= (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
(HOST={2})(PORT={3})))(CONNECT_DATA=(SERVICE_NAME={4}))”

I’ll work out the ODP drivers as a next step..

That’s it!

With those two changes, my tests pass without any problems AND return the correct information from our database:

Passing Fluent NHibernate Test

Fluent NHibernate With Oracle – A Question…

December 2, 2008 3 comments

Answer found!  Read more here.

After success with standard NHibernate, I quickly became enraptured with the cleaner Fluent NHibernate API.  No more XML; however, I have had VERY limited (read: none) success getting this working against Oracle—especially against our crazy Oracle environment (of which I have no control and readonly access).

Here’s what I have:

A basic ClassMap of a Student object.

class StudentMap : ClassMap<Student>

{

       public StudentMap()

       {

              WithTable(“Students”);

 

              Id(x => x.Id, “pupil_number”)

                     .GeneratedBy.Native();

              Map(x => x.FirstName, “first_name”);

              Map(x => x.LastName, “surname”);

 

       }

}

A basic Student object.

public class Student

{

       private Student() { }

 

       public virtual int Id { get; set; }

       public virtual string FirstName { get; set; }

       public virtual string LastName { get; set; }

}

Note: My constructor is private because this SHOULD be a readonly object.  Setting it public doesn’t seem to matter either. ๐Ÿ˜ฆ

A basic data provider.

public class SISDataProvider

{

       public ISession Session;

 

       public SISDataProvider(ISession session)

       {

              Session = session;

       }

 

       public T GetById<T>(int id)

       {

              Session.Flush();

              return Session.Get<T>(id);

       }

}

No save functionality—again, we just have readonly access to this database.

A basic session manager.

public class SISSessionManager

{

       private readonly string _mappingAssembly;

       private readonly ISessionFactory _sessionFactory;

 

       public SISSessionManager()

       {

              _mappingAssembly = “SIS.Domain”;

              _sessionFactory = GetSessionFactory();

       }

 

       public ISession GetSession()

       {

              return _sessionFactory.OpenSession();

       }

 

       private ISessionFactory GetSessionFactory()

       {

              var config = new Configuration();

 

              var configuration = OracleConfiguration.Oracle9

                .ConnectionString

                    .Server(“server”)

                    .Port(1521)

                    .Instance(“instance.name”)

                    .Username(“user”)

                    .Password(“password”)

                    .Create

                .ConfigureProperties(config);

 

              configuration.AddMappingsFromAssembly(Assembly.Load(_mappingAssembly));

 

              return configuration.BuildSessionFactory();

       }

}

The OracleConfiguration is based on a FluentNhibernate.Cfg.PersistanceConfiguration that I created that calls the OracleClientDriver (not the ODP; that’s OracleDataClientDriver—I’m simply wanting to get the architecture working for now and I’ll dink with increasing performance with ODP as the next step).

Finally, the test.

public class creating_a_student

{

       private SISDataProvider _provider;

       private SISSessionManager _sessionFactory;

 

       public creating_a_student()

       {

              _sessionFactory = new SISSessionManager();

              _provider = new SISDataProvider(_sessionFactory.GetSession());

       }

 

       [Fact]

       public void with_a_valid_student_id_selects_the_correct_student()

       {

             var sut = _provider.GetById<Student>(12345);

             sut.Should_Not_Be_Null();

             sut.Id.Should_Be_Equal_To(12345);

       }

}

Unfortunately, all that and I get an error:

creating_a_student.with_a_valid_student_id_selects_the_correct_student : Failed

XunitException: NHibernate.MappingException : No persister for: SIS.Domain.Student

After some debugging, the Sis.Domain.Student is being added to the Mapping collection, but I’m not sure if that’s the problem or not.  A Google of “no persister” pulls up a few NHibernate hits for not having the XML files set to Embedded Resource, which isn’t my problem here—is it?  I thought Fluent NHibernate escaped XMLHell.

I’d appreciate any guidance on this—I’m stumped.

Using Oracle ODP with NHibernate From a C# Class Library

November 7, 2008 2 comments

I’m working through a few demos today and needed to connect to an Oracle 10g database using NHibernate.  NHibernate, out of the box, has a Dialect for 10g/11g using the Oracle9Dialect; however, relies on Microsoft’s OracleClient library.  I prefer Oracle’s own ODP and, thankfully, after a few configuration settings, NHibernate complies. ๐Ÿ™‚

On the library with your mappings and domain classes, be sure that the hibernate.cfg.xml is set to Build Action: “Content” and Copy to Output Directory: “Copy always” when included in a class library (so it’s available in the /bin directory for the other consuming projects).

<?xml version=1.0 encoding=utf-8 ?>

<hibernate-configuration xmlns=urn:nhibernate-configuration-2.2>

       <session-factory>

              <property name=connection.provider>

                     NHibernate.Connection.DriverConnectionProvider

              </property>

              <property name=dialect>

                     NHibernate.Dialect.Oracle9Dialect

              </property>

              <property name=connection.driver_class>

                     NHibernate.Driver.OracleDataClientDriver

              </property>

              <property name=connection.connection_string>

                     User Id=user;

                     Password=password;

                     Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=
                           (PROTOCOL=TCP)(HOST=server)(PORT=1521)))
                           (CONNECT_DATA=(SERVICE_NAME=service.site)));

                     Pooling=true;

                     Enlist=false;

                     Statement Cache Size=50;

                     Min Pool Size=10;

                     Incr Pool Size=5;

                     Decr Pool Size=2;

              </property>

              <property name=show_sql>

                     true

              </property>

              <mapping assembly=NHibernateDemo.Core/>

       </session-factory>

</hibernate-configuration>

The connection.driver_class property value of NHibernate.Driver.OracleDataClientDriver tells NHibernate to look for the ODP (thanks Tomer!).  After wards, add in Oracle.DataAcess into the references of the project.  Unfortunately, there’s one more step.

If you try to compile and run tests at this point, you’ll get an NHibernate.HibernateException:

NHibernate.HibernateException : The IDbCommand and IDbConnection implementation in the assembly 
Oracle.DataAccess could not be found. Ensure that the assembly Oracle.DataAccess is located 
in the application directory or in the Global Assembly Cache. If the assembly 
is in the GAC, use <qualifyAssembly/> element in the application configuration file to 
specify the full name of the assembly.

The qualifyAssembly key goes in the App.config/Web.config file; however, I cannot get this to work using an App.config within the library itself.  For example, you’d need this qualifyAssembly key in EVERY application (tests, etc) that called your NHibernate Oracle objects.  Not cool.

For me, I’m using v2.111.6.20 of the ODP.NET for 11g.  Since I can’t get this working inside the class library, I’ll create and place it in the App.config of my Unit test project (demos with unit tests == good, console applications == bad).

<runtime>

       <assemblyBinding xmlns=urn:schemas-microsoft-com:asm.v1>

              <qualifyAssembly partialName=Oracle.DataAccess

                     fullName=Oracle.DataAccess,

                            Version=2.111.6.20,

                           Culture=neutral,

                           PublicKeyToken=89b483f429c47342 />

       </assemblyBinding>

</runtime>

Save, compile, run tests…

Successful XUnit Tests with NHibernate and Oracle ODP

Success!

Getting Oracle.DataAccess “Working” on x64

November 6, 2008 1 comment

Note: Please read to the end of the article before starting—results may vary.

We recently moved one of our applications off an older server to a shiny, speedy new server. In that transition, however, the new server was loaded with 64–bit Windows Server 2003 R2.  That’s fine—run .NET in 64–bit mode and kick along—my libraries are already set to run under ‘Any CPU’.

Wrong. BadFormatExceptions from Oracle.DataAccess.

Unfortunately, even the 64–bit versions of the Oracle 11g ODP returns a x86 Oracle.DataAccess.dll.  For me, setting the project to ‘x86’ (under the CPU build type) didn’t resolve the issue—it still couldn’t load the Oracle library.  A bit of hunting turned up that the x86 version of .NET isn’t installed by default.

Cool—easy fix.

To enable 32–bit access on a 64–bit platform, a few command lines are required:

First, a quick script to enable support on the system:

cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 True

Second, actually install the 32–bit version of ASP.NET onto IIS:

%SYSTEMROOT%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -i

Finally, enable 32–bit ASP.NET inside the Web Server Extensions (IIS Management Console):

Enabling x86 .NET in IIS

Now, that works—but we have a 64–bit server downgrading everything to 32–bit.  Why can’t we find and get this crackin’ at 64–bit?  We just need a 64–bit version of Oracle.DataAccess, right? 

Right. ~~~ Like most thing, the challenge is in the details.

If you look at the GAC on a machine with ODP 64–bit installed (I’m using 11.1.0.6.21 for 11g), there isn’t a x64 image available.  To find the 64–bit edition, you need the 11g Release 1 Client (it’s release 1 today).  Unfortunately, it’s 11.1.0.6.0–-a different version. GAH.  Okay, go ahead and install!

It should install a x64 image library with the following properties:

Oracle Client 64-bit

Now, in the web.config for the application, we need to add an assembly redirection.

<dependentAssembly>

       <assemblyIdentity name=Oracle.DataAccess publicKeyToken=89b483f429c47342/>

       <bindingRedirect oldVersion=0.0.0.0-2.111.6.20 newVersion=2.111.6.0/>

</dependentAssembly>

Also, in the /bin directory of your project (or where ever your referenced libraries are), make sure that the 32–bit edition is not available so that the compiler will read from the GAC.

Start up the application and go.

Too easy, right?  Yeah, I’m afraid it is.  After all this work, performance under the 64–bit environment was atrocious.  A load test of about 1000 users (using the Visual Studio Web Test tools).

Here’s the graph (click for details—it’s big so the detail is available):

64-bit Performance Monitors <— 64–bit Output

The bouncing green line in the top graph is the JIT compiler recycling over and over while the red in the bottom is the CPU pegged… and not pegged after 1000 users, but after about 15 at :15 seconds into the run.  Ugh.  I finally cut it off at 7:15 as the system was getting unstable.

So, I removed the 64–bit calls, rolled back to calling 32–bit ODP, and ran the EXACT same load tests.

32-bit Performance <— 32–bit Output

In 32–bit mode, the CPU is running as expected (the spikes are the system generating 50–100 page PDF reports on the fly using DataDynamics ActiveReports) and we hit our full 1000+ concurrent users without any real issues or memory seepage.

As a quick test, I removed the references and the few lines that are accessing Oracle databases in the application and just used the 64–bit libraries for SQL Server 2005 and my own framework libraries—and performance screamed.  I’m pretty confident that this is within Oracle.DataAccess, but more investigation is required to nail down which objects/calls.  There may be more value of simply populating the few bits of data I’m pulling out of Oracle within our SQL environment and updating it daily—like psuedo, remove materialized views. ๐Ÿ™‚

So… while it’s good to know how to get the 64–bit libraries working, I’m VERY interested in why the performance was so poor.  I haven’t tossed ANTS at it yet in 64–bit mode, though that is the next test on a 64–bit development box that I’m building up.

Handling Sessions Objects with a Custom Session Manager

September 18, 2008 Comments off

I try not to abuse Session objects too much—keep them simple types, not too many, etc.  However, on a recent project where there was a few of us dinking with the code, it became an issue with how the keys were named, where they were created, etc. 

To correct the problem on future projects, I tossed together a little class in the mix to manage the “keys”.

public class SessionManager

{

protected HttpSessionState session;

 

       public SessionManager(HttpSessionState httpSessionState)

       {

              session = httpSessionState;

}

 

public SessionManager()

       {

              session = HttpContext.Current.Session;

}

 

       public void Dispose()

       {

              session.Clear();

              session.Abandon();

       }

 

       public bool IsFoo

       {

              get { return

session[“IsFoo”].ConvertTo<bool>(); }

set { session[“IsFoo”] = value; }

}

 

       public string FooId

       {

              get { return

session[“FooId”].ConvertTo<string>(); }

set { session[“FooId”] = value; }

}

}

The two constructors allow the consumer to either accept the default HttpContext.Current session object or provide their own.  From there, the “keys” are coded within this page rather than in every code block throughout the site. 

To use the SessionManager:

I inherit all of my pages from a default page (DefaultPage, for lack of a better name) and place the session manager as a public field.

DefaultPage.cs:

public class DefaultPage : Page

{

public SessionManager CurrentSession;

      

protected void Page_PreInit(object sender, EventArgs e)

       {

              CurrentSession = new SessionManager();

}

}

To use the CurrentSession field, simply reference it.  This makes reading/writing to session easy on the inheriting pages.

private List<Foo> GetFooList()

{

var foo = sessionManager.IsFoo

              ? Foo.GetFooById(sessionManager.FooId)

: new List<Foo> { Foo.GetEmptyFoo() };

return foo;

}

Still tweaking to do, but it works and seems clean enough.

Suggestions or better ideas? ๐Ÿ™‚