Monday, June 10, 2013

Adhering to the DRY Principal in Javascript/Knockout

One of the things that honestly "hurt my feelings" when developing an HTML5 replacement application awhile back - was that the ViewModel needed to be declared in multiple places. Once in the service and again in the client. Of course, all the demonstrations during tech-week seemed to gloss over this with very simplistic applications. Required reading - Pragmatic Principles
Now, there may be ample reason to want to do this -> what I'm enacting upon in the client may require a subset (possibly?) but I would contend that it should probably be a different service call. Don't transfer bytes that you don't need! So I created a static class helper to be used within a Razor template - and proceeded to forgot all about it. 
A colleague from another department heard about/asked me about it and I rediscovered it. Enjoy. As always YMMV. If you improve on it - share it. I'll laud you copiously.

The helper:
public static class HtmlHelper
    {
        private static string JavaScriptify(string s)
        {
            return string.Join(".", s.Split('.').Select(x => x[0].ToString().ToLower() + x.Substring(1, x.Length - 1)));
        }

        public static IHtmlString KnockoutFrom<T>(this HtmlHelper<T> html, T obj)
        {
            var serializer = new JsonSerializer
                                 {
                                     ContractResolver = new CamelCasePropertyNamesContractResolver()
                                 };

            var sb = new StringBuilder();
            sb.Append("(function() {");

            var json = JObject.FromObject(obj, serializer);

            sb.Append("var vm = ko.mapping.fromJS(" + json + ");");

            var type = obj.GetType();

            var ns = JavaScriptify(type.Namespace);
            sb.Append("namespace('" + ns + "');");
            sb.Append(ns + "." + JavaScriptify(type.Name) + " = vm;");

            sb.Append("})();");

            return new HtmlString(sb.ToString());
        }
    }


The template:
@Html.KnockoutFrom(Model)

Friday, May 17, 2013

WSDL service returning DataSet? Seriously?

Just got a 'last-minute' TODO - have to establish another interface for state agency. Like any good developer - I grab the WSDL and 'prop-up' a test service. Imagine my surprise when I see the defined method results as DataSet. Yup. Can be anything - based on nature of the "select" - egads. 

The ONLY reasonable  - and its by NO MEANS reasonable - "theory" that *might* explain this 'design' decision is that auto-generated proxies won't 'break'. (Yea. It's a lame excuse and kinda defeats the purpose of contract-first development) Besides, auto-generated proxies are for the faint-hearted (HTTP/XML for me).

How to generically 'mock' a dataset? Grab NBuilder from NuGet and add to your project. Then add a POCO representation of the fields you wish to return. Then call this:
private static DataSet CreateDataSet<T>(int numberOfRows = 1)
        {
            var datatable = new DataTable(typeof (T).Name);
            typeof (T).GetProperties().ToList().ForEach(
                x => datatable.Columns.Add(x.Name));
            Builder<T>.CreateListOfSize(numberOfRows).Build()
                                    .ToList().ForEach(
                                        x => datatable.LoadDataRow(x.GetType().GetProperties().Select(
                                            y => y.GetValue(x, null)).ToArray(), true));
            var dataset = new DataSet();
            dataset.Tables.Add(datatable);
            return dataset;
        }

soapUI tests against WSDL methods work - now 'back-to-work'!

Tuesday, May 14, 2013

More Hibernation Fun :: Dialect does not support variable limits.


Had a sad-panda moment when I went to Linq to NHibernate with the following (rather straight-forward) syntax.

...

 var e = r.Where(w => w.Name.Contains(searchBy)).Select(c => c).Take(5).ToList();  
...
I bombed out on a simple test - with the exception being "Dialect does not support variable limits." Rather broad base of Google hits on this one...

Seemed like something wrong with the underlying dialect - so I needed to override; something like this:
 public class FixedMsSqlDialect : NHibernate.Dialect.MsSql2005Dialect  
   {  
     public override bool SupportsVariableLimit  
     {  
       get  
       {  
         return true; //because SQL Server DOES support TOP selects  
       }  
     }  
   }  

...


What was unclear was "where" does that go? Quick breeze through source revealed that it was 'set' right after the IPersistenceConfigurer was instantiated - so static method to use for my fluent configuration.
... 


 private static IPersistenceConfigurer PersistenceConfigurer(string connection)  
     {  
       var provider = MsSqlConfiguration.MsSql2005.ConnectionString(connection);  
       provider.Dialect<FixedMsSqlDialect>();  
       return provider;  
     }  
...

Now based on connection string - I can inject the "home-grown" default behavior from my GetConfiguration method.

...
 public FluentHelper(string connectionKey, bool autoConfig = false)  
       : this(  
         () =>  
         Fluently.Configure()  
         .Database(GetConfigurationOption(connectionKey))  
         .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))  
           .ExposeConfiguration((c =>  
           {  
             if (autoConfig)  
             {  
               BuildSchema(c);  
             }  
           })).BuildSessionFactory())  
     {  
     }  
 private static IPersistenceConfigurer GetConfigurationOption(string connectionKey)  
     {  
       string connection = ConfigurationManager.ConnectionStrings[connectionKey].ConnectionString;  
       switch (ConfigurationManager.ConnectionStrings[connectionKey].ProviderName)  
       {  
 ....omitted for brevity  
           default:  
             return PersistenceConfigurer(connection);  
       }  
 }  

Hurray - Linq Take() actually works now.



Sunday, May 12, 2013

NHibernate 3.x changes


Working on a sample project for a perspective company - when enabled NuGet for FluentNHibernate, and saw a breaking change in the NhQueryable constructor. (I've been building from the source for awhile so this one passed me by, 2.x - 3.x introduced some breaking changes)

This breaks:
...
public ReadOnlyRepository(ISession session)
        {
            this.selection = new NhQueryable(session);
        }
....

This 'seemed' to work - at least the compiler didn't complain:
...

public ReadOnlyRepository(ISession session)
        {
            this.selection = new NhQueryable(session as ISessionImplementor);
        }
...

After a few unit-tests later I discover that the session passed in is NOT being preserved. Now what?

So I look at the IQueryOver interface - inside of Hibernate seems to add some Extension methods and a Linq-like interface; but I miss the more "natural" feel of regular Linq expressions. Granted, I won't have as much fine-control over the underlying query - but I'm not doing anything too crazy - yet.

I end-up changing the original interface/implementation from:
 public interface IReadOnlyRepository where TEntity : class  
  {  
      IQueryable Linq();  
  }  
...
#region IReadOnlyRepository Members

         public IQueryable Linq()
  {
   return this.selection.AsQueryable();
  }

#endregion
...

to the 3.x friendly:

public interface IReadOnlyRepository : IQueryable where TEntity : class
    {
        IQueryable AsQueryable(); 
    }
...

Note: The implementation then explicitly marshals the "queryable-ness" to my preserved session.

Also Note: the explicit usage of namespace System.Linq - otherwise it WILL conflict with Hibernate:

#region IReadOnlyRepository Members

        public System.Linq.IQueryProvider Provider
        {
            get { return session.Query().Provider; }
        }

        public System.Collections.Generic.IEnumerator GetEnumerator()
        {
            return session.Query().GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public System.Type ElementType
        {
            get { return session.Query().ElementType; }
        }

       public System.Linq.Expressions.Expression Expression
        {
            get { return session.Query().Expression; }
        }

        public IQueryable AsQueryable()
        {
            return session.Query();
        }
        #endregion

Turns out this tripped out quite a few, as I searched the web. Hope this helps someone transitioning from building from source to moving to NuGet.

Why did I ever switch to MSTEST?

Ran into a wicked problem with MSTEST today, resurrected an old project went to run the tests - and boom - nothing appeared to run - very similar to the "cylon" symptom I talked about in 2010. Eventually ran into this wonderment which gave me at least an indication of what was happening (and only 2 days after latest VS2012 update too...hmmm)



So I waded through the following links to try and discover what was happening...

Came across a number of Open, Closed and Unreproducable issues from Microsoft Connect. Then finally a Resharper related post seemed like it was worth trying out (super shoutout to JetBrains forums). 

So I ended up switching from MSTEST to NUNIT and all tests ran. (Big Surprise)
I am reminded of an old song going back to NUNIT...

So how to switch in between NUNIT/MSTEST quickly - use a build directive - NUNIT.
Add the following code to the the head of your test files (or possibly a partial class, or just a plain base-class that all test files inherit from). Then you are basically remapping the MSTEST attributes to the appropriate NUNIT ones. You are rocking with NUNIT - thank you Resharper & StackOverflow. 
(Note: There is no TestContext available in NUNIT so if you rely heavily on that you will have to do something else)


#if NUNIT
using TestClass = NUnit.Framework.TestFixtureAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
using TestInitialize = NUnit.Framework.SetUpAttribute;
using ClassCleanup = NUnit.Framework.TestFixtureTearDownAttribute;
using ClassInitialize = NUnit.Framework.TestFixtureSetUpAttribute;
#else
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif

StackOverflow

http://osherove.com/blog/2010/3/5/nunit-vs-mstest-nunit-wins-for-unit-testing.html