Removing Exif Data To Resolve IOS Issues

Related to my last post, I had a bug to fix. The images looked rotate 90 degrees locally, so I used Imagemagick’s convert command to rotate them 90 degrees. They looked right locally, and on the sight when viewed in chrome.

However, iOS was showing the images over-rotated by 90 degrees. It turns out after some digging that the pictures were taking on an iOS device and had saved Orientation data in the EXIF data of the image (metadata). The iOS browser was still honoring that metadata.

Because metadata also has date, time, and location info, a lot of people prefer not to publish EXIF data anyway. Photoshop offers options to remove this data when exporting. I believe GIMP may as well.

But I just wanted to make it part of my process. So I updated the Rakefile from the last post with the following command option from Imagemagick’s convert:

convert input.jpg -strip output.jpg

All is well now. Use your favorite EXIF viewer to confirm success.

Rake Tasks For NuGet

If you use NuGet, and only check-in your packages.config files to source control, then your source control repository will stay smaller, and checkout faster. Checking in binaries is usually a nice thing to avoid. However, you need new developers to be able to get those libraries locally easily, and to allow your build server (continuous integration or otherwise) to keep libraries up to date.

After all, that’s one of the advantages of NuGet, you only download a new library when you first need it for that solution, or when you change versions.

In order to solve this problem, I use a rake task, as we use rake for other setup tasks (creating or seeding databases, continuous integration, etc). Rake may sound like an odd choice for a .Net environment, but it’s very good for customing cmd line tasks, and all the .Net building and setup we have run into can be done from the command line. Anyway, assuming the directory structure below, I thought I’d share the Rake tasks…

MySampleProject
|-Rakefile
|-tools
 |-NuGet.exe
|-Source
 |-Packages
  |-NHibernate
  |-MassTransit
 |-SampleProject.Web
  |-packages.config
  |-SampleProject.Web.csproj
  |-other files, etc
 |-SampleProject.ServiceBus
  |-packages.config
  |-SampleProject.ServiceBus.csproj
  |-other files, etc

Relevant tasks in the Rakefile below. Note the ci task using nuget task before it builds.

def nuget_for_project(project_dir)  
  sh "tools\\NuGet.exe " + 
    "i Source\\#{project_dir}\\packages.config " + 
    "-o Source\\Packages"
end

namespace :nuget do  
  desc "nuget for servicebus"  
  task "ServiceBus" do	
    nuget_for_project "SampleProject.ServiceBus"  
  end    

  desc "nuget for web"  
  task "Web" do	
    nuget_for_project "SampleProject.Web"  
  end  
  
  desc "nuget for all"  
  task "all" => ["nuget:ServiceBus", "nuget:Web"]
end

desc "continuous integration task"
task "ci" => ["clean", "nuget:all", "build", "test"]

Source Control Considerations for ConnectionStrings in .Net

For .Net projects that have multiple developers, configuration differences can be a real problem. For this post, we’ll use the example of connection strings, but it could just as easily be a directory location, or some other difference. Let’s say that we have two developers, one is using SQL Server, while the other is using SQL Server Express. A minor difference in configuration. The first developer needs to list a DataSource of “.” or “localhost”, while the second developer’s DataSource is something like “.\SqlExpress” or “localhost\SqlExpress”.

Note, for the purposes of this discussion, I’ll refer to some git terminology, as it’s my preferred source control tool, but this could just as easily apply to TFS, subversion, mercurial, etc.

Some developers will put the most common version in their web.config, and the developers in the minority have to change their file without checking in, and regularly undo and redo that process in order to get latest if their are other web.config (or app.config) changes.

To avoid this, some teams don’t check in the web.config file. They check in something like web.config.sample which has the default settings, and you make a local copy called web.config that is not registered with source control. You can make any appropriate changes without causing conflicts. Anytime you get latest and see a web.config change, you’ll want to use your favorite merge tool to pull any necessary changes into your web.config. Less work than the previous version, but more manual merging.

I like to recommend a 3rd method, that uses a lesser known piece of web.config capability. Most config sections allow a configSoure attribute to specify an external config file.

So in the case of the connection string differences, the web.config would get checked into source control, and it’s connection string section would like like the following:

<connectionStrings configSource="connection.config"/>

And then the connection.config file is treated like the second method above. There is a connection.config.sample file in source control that shows all the connection strings you need to have with sample connection info. Like follows:

<?xml version="1.0" encoding="utf-8" ?>
<connectionStrings>
    <add name="SomeDB"
         connectionString="Data Source=.;Initial Catalog=SomeDB;Integrated Security=True;"
         providerName="System.Data.SqlClient" />
</connectionStrings>

Additionally, we have a rake task (could be msbuild, maven, .bat, etc) that helps you initialize the project upon first checkout. One of the things it does, is copy that file from connection.config.sample to connection.config. And our .gitignore file on the project, tells git to ignore connection.config. Now you only need to change your DataSource and are ready to go. And the web.config can change without the need to change your connection.config file. The only time that should change is when you add, remove, or rename a connection string.

This same idea can be used for Elmah config, SMTP config, etc. For example, in development, we have email go to file, and different developers use different directories to store the mail. This scheme handles it.

Lastly, this same scheme can largely handle the differences we have with staging and production environments. Since the differences in web.config from the development branch to the stage and production branch are minimal, merging is pretty painless. And those external config files are a one-time setup on the server.

Consider this pattern for your projects, and let me know what you think. Either in the comments below or at @thoolihan. And if you find any room for improvement or have other feedback, please pass it along.

Rake Breathing New Life to Building Old Projects

I’ve seen lots of examples of rake (the ruby make replacement) being used as a build tool in non-ruby projects. Many of these are still modern platforms, like .Net. For example, StructureMap builds with rake. But I’ve found that even on older platforms, the power of having a full programming language in your build tool is useful.

Recently, I was working through examples in Thinking in C++, and there is the need to build many small one file examples. I started writing a Makefile to simplify this, and decided to try rake instead.

The power of a programming language brings a lot to table when doing repetitive tasks. Check out the following Rakefile which generates a build, run, and clean method for each file listed in an array. And there are aggregate methods which will run or clean all.

exe_name = ["hello","c_in_cpp","file","vector"]

exe_name.each do |f|
  desc "clean #{f}"
  task "clean_#{f}".to_sym do
    sh "rm -rf #{f} #{f}.o"
  end

  desc "build #{f}"
  task "build_#{f}".to_sym => "clean_#{f}" do
    sh "g++ #{f}.cpp -o #{f}"
  end

  desc "run #{f}"
  task "run_#{f}".to_sym => "build_#{f}" do
    sh "./#{f} 2> error.log"
  end
end

desc "run all"
task :default => exe_name.collect{|f| "run_#{f}"}

desc "clean all"
task :clean => exe_name.collect{|f| "clean_#{f}"}

If any of the above is unclear, and you want to see the output, do the following: copy and paste that code into a file named “Rakefile”. Run “rake -T” to lists all available tasks. You won’t be able to actually run the tasks, unless you have the appropriate cpp files in the directory (ie “rake run_hello” requires hello.cpp).

If you want to learn a build tool, and know ruby, or want to learn ruby rather than some specialized build language with no other uses, give rake a shot.