IE7 not calling formatted action properly.

This is completely bizarre. I have a respond_to block that looks kinda like this:

    respond_to do |format|       format.html { render :template => 'home/index' }       format.jpg { render :template => 'admin/products/small.flexi' }       format.xml { render :xml => @product.to_xml }     end

Which works great in Firefox and Safari. In IE7, however, ultimate weirdness. if I click a link from another page to this action (no file format extension) it trigger the .jpg format code. If I refresh, it then trigger the .html code like I expect it to.

I've never had cross browser issues like this that manifest on the server side. Has anyone else ever seen this? Is this a bug IE7?

I'm on Rails 2.0.2, and if there is some bug fix in rails about this that is in 2.1 maybe its worth the time to upgrade.

Anyone with hints?

Alex Wayne wrote:

This is completely bizarre. I have a respond_to block that looks kinda like this:

    respond_to do |format|       format.html { render :template => 'home/index' }       format.jpg { render :template => 'admin/products/small.flexi' }       format.xml { render :xml => @product.to_xml }     end

Which works great in Firefox and Safari. In IE7, however, ultimate weirdness. if I click a link from another page to this action (no file format extension) it trigger the .jpg format code. If I refresh, it then trigger the .html code like I expect it to.

I've never had cross browser issues like this that manifest on the server side. Has anyone else ever seen this? Is this a bug IE7?

I'm on Rails 2.0.2, and if there is some bug fix in rails about this that is in 2.1 maybe its worth the time to upgrade.

Anyone with hints?

A little further investigation, leads to some differences in the accept header:

Firefox sends:   "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"

IE7 sends:   "HTTP_ACCEPT"=>"*/*"

Could this be the culprit? Perhaps I need to declare a default format somewhere?

Alex Wayne wrote:

A little further investigation, leads to some differences in the accept header:

Firefox sends:   "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"

IE7 sends:   "HTTP_ACCEPT"=>"*/*"

Could this be the culprit? Perhaps I need to declare a default format somewhere?

I think I figured this out. IE7 is a tricky bastard. Basically, it sends different accept headers when clicking on links, and direct address bar access, than it does when refreshing.

Firefox's accept header lists "text/html" first, and this tells rails to trigger the "format.html" part of the respond to block.

IE7, on the other hand, sends an HTTP_ACCEPT header like so when you click a link:

  "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/ag-plugin, */*"

So rails looks at my respond_to block, and looks at that header. it looks for a gif responder, an x-bitmap responder, and then a jpg responder, which I do have. Rails declares is a match and sends it out. Normally people don't generate images via a respond_to block, which is why this hasn't come up much. Sadly, my app does this, and its actually a pretty clean solution.

So thing that made this such a nightmare to track down was when I refreshed the HTTP_ACCEPT header turned into simply "*/*", allowed rails to pick the default, which was html.

The solution is a gloabl before filter, that after some trial and error, looks like this:

    def set_default_format       bad_accept_header = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/ag-plugin, */*"

      if request.headers['User-Agent'] =~ /MSIE/ && request.headers['HTTP_ACCEPT'] == bad_accept_header         request.format = Mime::Type.lookup_by_extension(:all)       end     end

This forces it to behave if that funky header gets shoved to rails. Hope this helps someone.

Once again, IE has caused me hours of pain, when all other browsers performed flawlessly. Grumble... humbug... grrr...

Alex Wayne wrote:

Alex Wayne wrote:

A little further investigation, leads to some differences in the accept header:

Firefox sends:   "HTTP_ACCEPT"=>"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"

IE7 sends:   "HTTP_ACCEPT"=>"*/*"

Could this be the culprit? Perhaps I need to declare a default format somewhere?

I think I figured this out. IE7 is a tricky bastard. Basically, it sends different accept headers when clicking on links, and direct address bar access, than it does when refreshing.

Some final documentation and revelation about this is on my blog

http://beautifulpixel.com/2008/7/20/ie7-header-issues

Hopefully it helps someone from this noodle scratching problem.

I'm having a similar problem in IE 7. I have a search form that submits to an action that can handle either AJAX or HTML requests. Here is my respond_to block

respond_to do |format|   format.js { render :partial => 'list_table' }   format.html { render :action => 'index' } end

For some reason, IE is triggering the .js format and I'm getting the file download dialog. I did some testing, and it looks like if I swap the order of the formats so that .html comes before .js, then IE renders correctly.

respond_to do |format|   format.html { render :action => 'index' }   format.js { render :partial => 'list_table' } end

Seems like whatever format comes first gets matched. Stupid IE.

After switching the order of the formats my AJAX calls still work, as well as my HTML calls. Very odd.

deadwards wrote:

Seems like whatever format comes first gets matched. Stupid IE.

Right.

The only accept header item sent by IE that matches any of those formats is */*, which means send me anything. So Rails picks the first one it finds.

So you can either put html first, like you did, or you can add the snippet in my linked blog post to force the html format unless a params[:format] is explicitly declared on the url.

You just saved me a boatload of work and frustration.

Thanks

Brian Ploetz wrote:

This seems to be promoting URLs that are not "cool" (Hypertext Style: Cool URIs don't change.) by requiring the format (.html, .xml, etc) as an extension. That kind of stinks......

Thats good news. Obviously, HTTP clients cant yet be trusted to provide proper headers. So relying on them is problematic. I personally like the typed urls because it makes it super easy to grab things in a variety of formats without any complicated header trickery. I can do it right in my browser.

Alex Wayne wrote:

Thats good news. Obviously, HTTP clients cant yet be trusted to provide proper headers. So relying on them is problematic. I personally like the typed urls because it makes it super easy to grab things in a variety of formats without any complicated header trickery. I can do it right in my browser.

Right. It just means that I have to go through all of my views and refactor my plain old link_to calls to look like:

link_to 'Foo', formatted_foo_url(@foo, "html")

Which is more than a pain in the arse....your filter works well until I can get around to doing this I suppose.

Cheers. BP

Brian Ploetz wrote:

your filter works well until I can get around to doing this I suppose.

Actually, your filter is problematic for AJAX actions which do a render :partial => 'blah'

I've tweaked it to this, which seems to do the trick:

  def set_default_format     if !request.xhr?       params[:format] ||= 'html'     end   end

This works well for my particular set up, as most of my AJAX actions render partials, so if you're doing something like format.js and using RJS, you might need to tweak further.