Saturday, October 30, 2010

Custom iPhone 4 Mount For Car

Cutting to the chase. Here are the pics of my new custom iPhone mount!


Previously I had customized my car to mount my iPhone 3G using a Griffin iPhone 3G Windshield Mount.

A couple months later the iPhone4 came out and it does not work with the Griffin mount I was using. I took a gamble and order a Griffin WindowSeat AUX.

I got very lucky and was able to put the cradle from the new Griffin mount onto the existing arm from the 3G mount. It's an extremely tight fit but it works. It doesn't swivel as easily as I'd like but I'm very happy I didn't have to do anymore cutting.

The next customization I wanted to do was to add steering wheel controls for music. I found this Kensington LiquidAUX Bluetooth Car Kit and it was on sale so I got overly excited and bought 2!

After it arrived I was disappointed to find out that my Alpine CDA117 car stereo does not have a regular "line in" that would work with the Kensington Bluetooth kit. :(

In addition the AD2P audio takes over the wired line out so it was looking like I'd have to not use the Bluetooth kit or buy a new stereo. After some googling I found the solution to my problem. If you jailbreak your iPhone and install Bluetooth Profile Selector (BTPS) you can disable the AD2P out and the audio will play out the wired connection, BUT the wireless steering wheel controls still work!

The Kensington Bluetooth kit allows me to play/pause, and skip songs forward and backward and also has a button that will bring up Voice Control. Voice Control seems to work Ok for dialing numbers. So far I haven't found the trick to get it to play songs/artists while connected to the car stereo.

The final mod I did was to disable the "Accessory Connected" splash screen that replaces the iPod apps UI when connected to my head unit. There is another app on Cydia for jailbroken phones called No Accessory Splash. Install this and you can use the iPod app like normal in addition to having the head unit controls work.

The combination of a nice touch screen and steering wheel controls should make my commutes much more pleasant! Especially considering every other feature in my Mitsubishi Evo IX RS is manual (locks, windows, mirrors, seats, etc). For those curious the RS is a stripped down model primarily marketed to be raced. This saves weight and allows the car to be sold at a lower price.

Thursday, October 14, 2010

How Not to Implement Unsubscribe

UPDATE 10/14/2010 11:55 AM CST: SpeakerRate may not have done the unsubscribe correctly. But they know customer service. Thanks guys!
http://twitter.com/#!/speakerrate/status/27356776561

This is just plain unacceptable. I rated one speaker and used my email address to do so. I get a newsletter from SpeakerRate the next day which is fine because I planned to just click the Unsubscribe link at the bottom. Here's what I was presented with:



Do you really think I want to create an account?

Friday, October 8, 2010

Count the Number of Network Connections in Windows

If you need to count the number of network connections to a certain port start by entering this command into a command prompt:
netstat -a -n

Then find the IP:Port combo you want to count and modify the following command to get the count:
netstat -a -n | find /c "<ip:port>"

Example:
netstat -a -n | find /c "127.0.0.1:1935"




Thursday, October 7, 2010

Upgrade ASP.NET MVC 3 Preview to MVC Beta

I previously blogged about upgrading the TekPub ASP.NET 2 Starter Site from MVC2 to MVC3 Preview:
http://blog.cdeutsch.com/2010/08/upgrade-mvc2-to-mvc3.html

Today I upgrade that project to MVC3 Beta.

It was pretty easy. Biggest change was with Dependency Injection. IMvcServiceLocator no longer exits and has been replaced with IDependencyResolver.

My NinjectServiceLocator file has been replaced with NinjectResolver (thanks Jedidja from StackOverflow!) and looks like this:

namespace Mvc3Ninject.Utility
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using Ninject;

    [System.Diagnostics.DebuggerStepThrough]
    public class NinjectResolver : IDependencyResolver
    {
        private static IKernel kernel;

        public NinjectResolver()
        {
            kernel = new StandardKernel();
            RegisterServices(kernel);
        }

        public NinjectResolver(IKernel myKernel)
        {
            kernel = myKernel;
            RegisterServices(kernel);
        }

        public static void RegisterServices(IKernel kernel)
        {
            //kernel.Bind<IThingRepository>().To<SqlThingRepository>();
        }

        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }
    }

}

And then in the Global.asax.cs file I changed this line....

//// Tell ASP.NET MVC 3 to use our Ninject DI Container 
MvcServiceLocator.SetCurrent(new NinjectServiceLocator(_container));

...to...

//// Tell ASP.NET MVC 3 to use our Ninject DI Container 
DependencyResolver.SetResolver(new NinjectResolver(_container));

And that's that! Have fun coding!

Here's a complete working sample project based on my Code-First Entity Framework upgrade of the TekPub Starter Site.

Sunday, September 5, 2010

Save Web Page as PDF on iPad then Annotate

I was viewing the schedule for Twin Cities Code Camp on my iPad this morning and wanted to circle the talks I was interested in. I quickly realized I wasn't going to be able to do this without some help. After some research here's what I came up with.
  1. Configure your iPad to sync Bookmarks with one of your browsers (I picked Safari)


  2. Add this Bookmarklet for converting web pages to PDF from PDF Download to Safari (originally found this tip on "The Heat Web")

  3. Sync your iPad with iTunes to get the Bookmarklet onto your iPad.
  4. Install one of the iPad PDF Annotation apps. I picked Noterize by Robert Stretch. I also looked at iAnnotate which I'll try next if I don't like Noterize.
  5. Browse to the web page you want to annotate, open your Bookmarks, and select Save Page As PDF
  6. Unfortuantely I had to hit stop and then "refresh" in Safari to get PDF Download to work (your results may vary)
  7. PDF Download will eventually open the page as a PDF. (it can take a while)
  8. Copy the URL of the PDF.
  9. Open Noterize, go to the root of your Notes and click Import PDF/PPT. Select the Web Browser option and paste in the copied URL.
  10. The PDF is now available to annotate.
I also highly recommend using Dropbox so you can easily save your annotations and view them on your computer or in other apps that support Dropbox. You can use Dropbox to easily get PDFs into Noterize from your computer as well.

Noterize does not automatically save your PDF's to Dropbox. You'll need to Share the PDF within Noterize after it has been annotated and then upload to Dropbox.

I'd love to hear from you! Leave a comment or reply to @cdeutsch on Twitter if you find something useful.



Saturday, August 21, 2010

Code-First Entity Framework ISession for Tekpub MVC Starter Site

I've been using a lot of the ideas/code in Tekpub's MVC Starter Site for a personal project of mine. For better or worse the features of .NET 4.0 and MVC keep rapidly changing. I wanted to use both MVC 3 Preview 1 and Code-First Development with Entity Framework 4 so I've taken the time to upgrade the MVC Starter Site to support both of these features. You can download my working project here. See this post for more info on the headache to upgrade to MVC 3.

IMO it took way too much time to do this but a lot of it is probably due to my inexperience with MVC and in particular Dependency Injection.

Below is the class I added in order to use Code-First in the MVC Starter Site. The class inherits ISession. At first I tried to get access to the underlying ObjectContext so I could just use the already written EFSession class. I couldn't get this to work and then luckily I took a step back and realized I didn't need it to. I still haven't figure out how to do a working IReadOnlySession.cs but for my needs it won't be an issue at this time.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Data.Metadata.Edm;
using System.Data.Entity;

namespace Web.Infrastructure.Storage
{
    public class EFCFSession : ISession
    {
        DbContext _context;
        public EFCFSession(DbContext context)
        {
            _context = context;
        }

        
        public void CommitChanges() {
            _context.SaveChanges();
        }

        public void Delete<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T: class, new() {

            var query = All<T>().Where(expression);
            foreach (var item in query) {
                Delete(item);
            }
        }

        public void Delete<T>(T item) where T: class, new() {
            _context.Set<T>().Remove(item);
        }

        public void DeleteAll<T>() where T: class, new() {
            var query = All<T>();
            foreach (var item in query) {
                Delete(item);
            }
        }

        public void Dispose() {
            _context.Dispose();
        }

        public T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T: class, new() {
            return All<T>().FirstOrDefault(expression);
        }

        public IQueryable<T> All<T>() where T: class, new() {
            return _context.Set<T>().AsQueryable<T>();
        }

        public void Add<T>(T item) where T: class, new() {
            _context.Set<T>().Add(item);
        }
        public void Add<T>(IEnumerable<T> items) where T: class, new() {
            foreach (var item in items) {
                Add(item);
            }
        }
        public void Update<T>(T item) where T: class, new() {
            //nothing needed here
        }
    }
}

Another interesting thing I found when doing this is that I couldn't use the same DB for the ReportingDB DbContext and the SiteDB DbContext without Code-First wiping the other out. Not a huge deal at the moment but could become an issue down the road.

So far I'm loving the idea of using POCO model classes and can't wait to try combine them with the MVC 3 Model Validation improvements!



Sunday, August 15, 2010

Upgrade MVC2 to MVC3

Today I upgrade a fairly new MVC2 app to MVC3. My original MVC2 app was based off of The Tekpub ASP.NET MVC 2.0 Starter Site

The first step is to update your projects references. This blog post by Rick Schott worked great to handle that task.

After doing that I was faced with the error:
No parameterless constructor defined for this object.

My original global.asax.cs looked like this:
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Ninject.Web.Mvc;
using Ninject;
using Ninject.Modules;
using Site.Infrastructure.Logging;
using Web.Infrastructure.Authentication;
using Web.Infrastructure.Reporting;
using Web.Infrastructure.Storage;
using Web.Model;

namespace Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : NinjectHttpApplication
    {
        public static ISession Session
        {
            get
            {
                return _container.Get<ISession>();
            }
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("favicon.ico");
            routes.MapRoute(
                "Login", // Route name
                "login", // URL with parameters
                new { controller = "Session", action = "Create" } // Parameter defaults
            );
            routes.MapRoute(
                "Logout", // Route name
                "logout", // URL with parameters
                new { controller = "Session", action = "Delete" } // Parameter defaults
            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        protected override void OnApplicationStarted()
        {
            Logger.Info("App is starting");

            //Database.SetInitializer<SiteDB>(new AlwaysRecreateDatabase<SiteDB>());

            AreaRegistration.RegisterAllAreas();
            RegisterRoutes(RouteTable.Routes);

            //ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(Container));
        }

        protected void Application_End()
        {
            Logger.Info("App is shutting down");
        }

        protected void Application_Error()
        {
            Exception lastException = Server.GetLastError();
            Logger.Fatal(lastException);
        }

        /// <summary>
        /// IoC stuff below
        /// </summary>
        /// <returns></returns>
        protected override IKernel CreateKernel()
        {
            return Container;
        }

        internal class SiteModule : NinjectModule
        {
            public override void Load()
            {
                //a typical binding
                Bind<ILogger>().To<NLogLogger>().InSingletonScope();
                //Bind<INoSqlServer>().To<DB4OServer>().InSingletonScope();
                //Bind<ISession>().To<Db4oSession>().InRequestScope();

                //You can use the SimpleRepository to build out your database
                //it runs "Auto Migrations" - changing your schema on the fly for you
                //should you change your model. You can switch it out as you need.
                //http://subsonicproject.com/docs/Using_SimpleRepository
                Bind<ISession>().To<SiteEFSession>();
                Bind<IReporting>().To<ReportingSession>();
                Bind<IAuthenticationService>().To<UserAuthenticationService>();
            }
        }

        public ILogger Logger
        {
            get
            {
                return Container.Get<ILogger>();
            }
        }

        static IKernel _container;
        public static IKernel Container
        {
            get
            {
                if (_container == null)
                {
                    _container = new StandardKernel(new SiteModule());
                }
                return _container;
            }
        }
    }
}

I then tried to add the NinjectServiceLocator.cs class and update my global.asax.cs to use Ninject like this sample from Scott Gu.

It looked something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Ninject;
using Ninject.Modules;
using Site.Infrastructure.Logging;
using Web.Infrastructure.Authentication;
using Web.Infrastructure.Reporting;
using Web.Infrastructure.Storage;
using Web.Model;
using Mvc3Ninject.Utility;

namespace Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("favicon.ico");
            routes.MapRoute(
                "Login", // Route name
                "login", // URL with parameters
                new { controller = "Session", action = "Create" } // Parameter defaults
            );
            routes.MapRoute(
                "Logout", // Route name
                "logout", // URL with parameters
                new { controller = "Session", action = "Delete" } // Parameter defaults
            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        public static void RegisterServices(IKernel kernel)
        {
            //a typical binding
            kernel.Bind<ILogger>().To<NLogLogger>().InSingletonScope();
            //Bind<INoSqlServer>().To<DB4OServer>().InSingletonScope();
            //Bind<ISession>().To<Db4oSession>().InRequestScope();

            //You can use the SimpleRepository to build out your database
            //it runs "Auto Migrations" - changing your schema on the fly for you
            //should you change your model. You can switch it out as you need.
            //http://subsonicproject.com/docs/Using_SimpleRepository
            kernel.Bind<ISession>().To<SiteEFSession>();
            kernel.Bind<IReporting>().To<ReportingSession>();
            kernel.Bind<IAuthenticationService>().To<UserAuthenticationService>();
        }

        public void SetupDependencyInjection()
        {
            // Create Ninject DI Kernel 
            _container = new StandardKernel();

            //// Register services with our Ninject DI Container
            RegisterServices(_container);

            //// Tell ASP.NET MVC 3 to use our Ninject DI Container 
            MvcServiceLocator.SetCurrent(new NinjectServiceLocator(_container));
        }

        void Application_Start()
        {
            SetupDependencyInjection();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            Logger.Info("App is starting");
        }

        protected void Application_End()
        {
            Logger.Info("App is shutting down");
        }

        protected void Application_Error()
        {
            Exception lastException = Server.GetLastError();
            Logger.Fatal(lastException);
        }

        public ILogger Logger
        {
            get
            {
                return Container.Get<ILogger>();
            }
        }

        static IKernel _container;
        public static IKernel Container
        {
            get
            {
                return _container;
            }
        }
    }
}

This caused the following error to constantly trigger the debugger although the site seems to still be working:
Error activating IControllerFactory
No matching bindings are available, and the type is not self-bindable.

I then added the following line to the RegisterServices function based on this Stackoverflow tip:
kernel.Bind<IControllerFactory>().To<Ninject.Web.Mvc.NinjectControllerFactory>();

This caused the following error:
Method Ninject.Syntax.IBindingToSyntax`1[System.Web.Mvc.IControllerFactory].To: type argument 'Ninject.Web.Mvc.NinjectControllerFactory' violates the constraint of type parameter 'TImplementation'.

I then tried using DefaultControllerFactory instead of the line above and finally success!
kernel.Bind<IControllerFactory>().To<DefaultControllerFactory>();

This is my final working global.asax.cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Ninject;
using Ninject.Modules;
using Site.Infrastructure.Logging;
using Web.Infrastructure.Authentication;
using Web.Infrastructure.Reporting;
using Web.Infrastructure.Storage;
using Web.Model;
using Mvc3Ninject.Utility;

namespace Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("favicon.ico");
            routes.MapRoute(
                "Login", // Route name
                "login", // URL with parameters
                new { controller = "Session", action = "Create" } // Parameter defaults
            );
            routes.MapRoute(
                "Logout", // Route name
                "logout", // URL with parameters
                new { controller = "Session", action = "Delete" } // Parameter defaults
            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

        public static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IControllerFactory>().To<DefaultControllerFactory>();

            //a typical binding
            kernel.Bind<ILogger>().To<NLogLogger>().InSingletonScope();
            //Bind<INoSqlServer>().To<DB4OServer>().InSingletonScope();
            //Bind<ISession>().To<Db4oSession>().InRequestScope();

            //You can use the SimpleRepository to build out your database
            //it runs "Auto Migrations" - changing your schema on the fly for you
            //should you change your model. You can switch it out as you need.
            //http://subsonicproject.com/docs/Using_SimpleRepository
            kernel.Bind<ISession>().To<SiteEFSession>();
            kernel.Bind<IReporting>().To<ReportingSession>();
            kernel.Bind<IAuthenticationService>().To<UserAuthenticationService>();
        }

        public void SetupDependencyInjection()
        {
            // Create Ninject DI Kernel 
            _container = new StandardKernel();

            //// Register services with our Ninject DI Container
            RegisterServices(_container);

            //// Tell ASP.NET MVC 3 to use our Ninject DI Container 
            MvcServiceLocator.SetCurrent(new NinjectServiceLocator(_container));
        }

        void Application_Start()
        {
            SetupDependencyInjection();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);

            Logger.Info("App is starting");
        }

        protected void Application_End()
        {
            Logger.Info("App is shutting down");
        }

        protected void Application_Error()
        {
            Exception lastException = Server.GetLastError();
            Logger.Fatal(lastException);
        }

        public ILogger Logger
        {
            get
            {
                return Container.Get<ILogger>();
            }
        }

        static IKernel _container;
        public static IKernel Container
        {
            get
            {
                return _container;
            }
        }
    }
}

Alternatively in going through this headache I found downloading the source for both Ninject and Ninject.Web.Mvc and updating it to use .NET Framework 4.0 and Mvc 3 fixed most of the errors above and allows you to NOT change the global.asax.cs at all. You can just use it as it was originally.

To get Ninject.Web.Mvc updated you must:
  • Change the Target Framework to .NET 4.0.
  • Update the reference to System.Web.Mvc to use 3.0.0.0 instead of 2.0.0.0
  • Remove the following references:
    • System.Web.Routing
    • System.Web.Abstractions
In closing, I really wish the MVC team would include a default Dependency Injection with MVC. I've lost way too many hours at this point trying to get DI working between all the different options and all the outdated tutorials. If I'm struggling with it I have to imagine there are many others out there as well. This is making it harder for people to adopt MVC and should be eliminated by the MVC team picking a default to include when installing MVC and generating the default global.asax.