Iframe Content Does Not Load When Iframe URL Matches URL of Parent Document – in IE and FF

by Oliver 29. September 2016 20:00

It's been a few years already, that on Camping.Info we decided to load the detail page (aka product page) of a campsite into an iframe that lies on top of the search page. This decision has three reasons that still hold true today: Opening the new content on top of the search page – which hosts a Google Map – we avoid additional map views (which would count against our quota or cost money when above the quota) because when the user closes the detail page, we simply remove the iframe from the page. Returning to the search page is faster for the user because all we have to do is remove the iframe from the page. Avoiding another page load for re-displaying the search page with the current filters to the user lessens server load, especially during high season, which actually might save us from running an extra server. Recently, we've finally come around to leveraging the HTML5 history API to adapt the URL of the currently visible page, aka the search page, to that of the campsite's detail page URL that a user chooses to open. It can't be that hard to do, right? During development, Chrome is my browser of choice for testing because my Firefox installation is locked down to avoid infections. In Chrome, the following worked like a charm: Open the Camping.Info search page, i.e. https://www.camping.info/campingplaetze. Click on any link that points to a campsite's detail page, e.g. https://www.camping.info/kroatien/istrien/camping-polari-84 Manipulate the browser history to imitate navigation to that URL. Add an iframe to the search page with that same URL and load the page into that iframe – which lies on top of the page now for the user to interact with. Be done with it. Unfortunately, testing the same approach in Firefox and Internet Explorer it turned out that both FF and IE would not load the page from the given URL into the iframe. Firefox and Internet Explorerbehave differently from Chrome At first, the behavior of Firefox and IE irritated and confused me. Only after some reflection on the scenario, it dawned to me that both browsers simply want to avoid an endless loop of loading a page with an iframe that loads the same page again, which contains an iframe that loads the same page again… So, Firefox and IE choose to not load the iframe contents at all. This is a fair decision, if you think about it for a minute. But what does Chrome do? Does it really allow you to crash it by loading a page with an iframe that loads the same page again? Well, no. Chrome simply decides to break out of the endless loop after the first iteration, instead of before it. Here's what a small test page looks like in all three browsers: The Obvious Fix Since loading a page into an iframe from a URL that is identical to the iframe's parent's URL won't work, we really have only one choice: load it from a different URL! In our case, an easy fix to achieve that is by appending a trailing slash to the URL we pass to the iframe, e.g. https://www.camping.info/kroatien/istrien/camping-polari-84/. This works because we have a URL redirect rule in place that will redirect such a request to https://www.camping.info/kroatien/istrien/camping-polari-84 which will then be loaded into the iframe successfully. Our browser's developer tools then tell us that the src attribute of the iframe does not change during that redirect so we've successfully tricked all browsers into loading the desired page into our iframe, while at the same time we can display the campsite's real detail page URL to the user. Happy coding!

Trimming Whitespace From Text Inputs In ASP.NET WebForms – The Easy Way

by Oliver 22. September 2016 01:02

When I validate forms, I usually don't want the user to allow to enter only whitespace in any of the text fields that I deem required. With a handful of them, checking for that condition can be annoying. Let me introduce you to… TrimTextBox! To centralize the concern to trim padding whitespace from text inputs, I simply derived from the built-in TextBox class and overrode a single property – Text: With this simple piece of code my backend validation logic can now focus on the business rules, e.g. a minimum length of one character, without having to worry about leading, trailing, or only whitespace in any input field. Don't Repeat Yourself – Keep it DRY Whenever I encounter a piece of code that repeats more than once, I try and refactor that code away to make it reusable and sometimes even to completely hide a certain aspect of it from the current context so that when reading a block of code I can decide whether I want to dive deeper into the nitty gritty details or just get an overview of the workflow I'm looking at. This saves my brain some precious resources ;-) I wonder what other use cases you can come up with where a specialized control can make your developer life simpler :-) Happy coding (subclassing)!

How to Convert an XSLX File to CSV with UTF-8 Encoding Using LibreOffice / OpenOffice

by Oliver 13. November 2015 21:54

Thanks to this stackoverflow answer I stumbled upon the comment by Aryeh Leib Taurog who shared his solution and a link to the OpenOffice documentation on the available options for the CSV filter. Here's how to convert the file input.xlsx to the UTF-8 encoded file input.csv in the current directory, with semicolons as field delimiter: soffice.exe --convert-to "csv:Text - txt - csv (StarCalc):59,,76,1" input.xlsx On my Windows system the soffice.exe is located under C:\Program Files\LibreOffice 5\program. Hre's the explanation of the cryptic filter arguments: csv – the extension of the output file Text - txt - csv (StarCalc) – the (ancient) name of the filter (kept for compatibility) 59,,76,1 – these are four arguments: the first parameter is the delimiter in the output file – 59 is the ASCII code for ';' the second parameter is the text delimiter – it's missing because I don't want to wrap text in quotes the third parameter is the file encoding – 76 is the internal OpenOffice code for UTF-8 (from the table on the documentation page) the fourth parameter defines the line number with which to start the export – here, we start with line 1 Thank you, open source community, and happy converting! PS: For non-windows users, Gnumeric with its command line tool ssconvert might be a good choice for this job, as well.

Visual Studio 2013 Update 4 Crashes On Startup – It Might Be GitExtensions' Fault

by Oliver 23. February 2015 22:49

Lately, I've been having a hard time with my Visual Studio installation because one day it just out of nowhere started crashing during startup. Starting VS with the /SafeMode flag avoided the crash but wasn't of much help to do major work since all my R# syntax highlighting and refactoring tools are not available in safe mode. First Try: Reset All Your Settings The first time I encountered the problem I found this answer on stackoverflow.com  helpful which suggests to: Reset all your Visual Studio settings by calling devenv /resetsettings from a command line prompt or after hitting the Windows key. Delete the folders %LocalAppData%\Microsoft\VisualStudio and %LocalAppData%\Microsoft\VSCommon Second Try: Uninstall GitExtensions Today, VS started crashing again and I was just happy with resetting all of my fine-tuned settings AGAIN. Luckily, a google search brought up this thread on the NCrunch forum and since I use NCrunch for test execution I went to have a look Here's what Simon had to say there: I'm thinking the problem was a GIT plugin installed by GitExtensions - I've read other reports about it causing problems, so I've removed it and things seem stable so far. To verify whether this was true in my case I just went ahead and uninstalled GitExtensions via the Control Panel – and Visual Studio would happily start again! What a relief. But I Still Want To Use GitExtensions… After uninstalling, go get the installer again (did you know there's a standalone version without msysgit and kdiff?) and during install unselect all the Visual Studio plugins like this: UPDATE: Keep Even GitExtensions' VS Plugin! A commenter to my answer to the VS crash problem on stackoverflow suggested that unchecking the option "Show current branch in Visual Studio" in GitExtensions under Tools –> Settings –> Appearance fixed the VS crashes for him: I used this hint to reactivate the GitExtensions VS plugin on my machine as well, because I use some of its features quite often. Now, you should be good to go! I'll try to get back to work now while my VS is running… Happy coding!

Setting up freeSSHd to Connect to its SFTP Server Using SSH Public Key Authentication

by Oliver 14. January 2015 22:59

A while ago I've set up an SFTP server using the freeware freeSSHd which is relatively easy to get up and running. Initially, I created a user/password pair to log into the server. Using SSH Last week, we decided to switch to public/private SSH keys for authentication instead of the user/password pair. Among other things, this allows us to script access to our server while at the same time we can avoid keeping a clear text password in one of our scripts. Here's how we've set it up. Configuring freeSSHd for use with SSH I'll run you through the necessary steps: Open an instance of freeSSHd and go to the Users tab. Add or Change a login to use Public Key (SSH only) authorization and enable SFTP access: Navigate to the Authentication tab. There you'll find the path to the folder in which to deposit your public keys. If you plan to have more than a few, consider using a subfolder of the default one: Open the public key folder in Windows Explorer and create a new empty text file there by the name of the login you've set up in step 1. Make sure the file name is exactly the same as the name of the user and don't add any file extension to it. This is where we'll be pasting a new SSH public key to in a moment: Now we will generate an SSH key pair. Locate puttygen.exe on your PC. You can grab it from the PuTTY download page, but it also comes bundled with GitExtensions, or WinSCP, if you use one of these: [Side note: I use Everything to find such files. It's a great search tool that delivers instant results.] Start puttygen.exe and generate a pair of SSH keys by clicking Generate ❶: Next, copy the public key from the grey text box ❷ and paste it into the empty file you've created in step 3. In my case, this file is called "oliver". You can now save the private key ❸ to a file of your choice, optionally protected by a passphrase, to use it to connect to freeSSHd via SSH using your preferred tool. I've successfully used WinSCP for testing, as I've experienced several problems using PuTTY's psftp.exe command line tool. Roundup Setting up public key authentication in freeSSHd can be tricky. While researching the solution I've stumbled over this blog post addressing the same problem. Its author refers to this setup guide from IBM (pdf) as the source of help so it might be helpful to others out there, as well. I hope that my step-by-step guide has also helped you. Happy connecting!

Turn Off / Remove Ads in Skype's Chat Window On a Windows OS

by Oliver 19. August 2014 21:37

I've got quite annoyed by seeing the same ad in my Skype chat window and today I simply had enough of it. Going to Google lead me to this Youtube video which shows how to block ads in Skype by denying access to https://apps.skype.com/ in Internet Explorer. Here's a screen shot, just follow the steps below and you're done: Open Internet Options Switch to the Security tab Select Restricted Sites Click the Sites button Type https://apps.skype.com/ into the text box Click Add Click Close Click OK For those changes to take effect in Skype you need to leave your chat window e.g. by clicking on your profile in the upper left corner. Now, when you open a chat window no ads will show. There are other ways to stop Skype from showing ads, and here's a really thorough post on that topic. Happy Skype'ing!

Optimize Images for Your Website

by Oliver 17. June 2013 13:59

This is just a short post to draw your attention to a sweet tool I've just discovered: PNGGauntlet. It runs on Windows using the .NET 4 framework and is as easy to use as you could possibly wish. Also: it's completely free to use. Convert Your Existing PNGs For starters, we'll just convert some existing PNGs – can't really do any harm with that. In the Open File dialog, there's an option to filter for only .png files. You can choose many of them at once: If you provide an Output directory, the optimized files will be written to that destination. But: the tool also has the option to overwrite the original files, which is awesome if you use some kind of source control (and thus have a backup) and just want to get the job done. During my first run, using the 8 processing threads my CPU has to offer, … … I got savings from 3% to 27%: PNGGauntlet also tells me, that in total I saved 4,52 KB. If those were all images on your web site, that would be a not so bad improvement, especially when you get it investing about 2 min of your time and no extra expenses! Real Savings Running PNGGauntlet on the sprites that we use for Camping.Info, we were really surprised: out of 172 KB it saved us over 31%, a whole 54 KB! Now that's an improvement that on a slightly slower connection will already be noticeable. We'll definitely check the rest of our images for more savings. Convert Other Image Formats You can also choose to change your images format to PNG if you're in the mood. I tried converting all GIFs in the Orchard CMS Admin theme to PNGs and went from a total of 24 KB for 20 files to less than 17 KB with no loss of quality – an over 30% saving! Just beware that you'll need to change the file references in your project to pick up the new PNGs. Roundup Easy, fast and cheap (as in free) image optimization doesn't have to be magic anymore – today anyone can do it. Check out PNGGauntlet to try for yourself. There's really no excuse not to!

Orchard Harvest: Shapes Session

by Oliver 14. June 2013 18:09

These are session notes, so they might not adhere to the standards of a complete blog post, but there's a bunch of inspiring info that I had to get out of my head… Shapes – Overview What are they dynamic data model can be updated at runtime replaces static(ally typed) view models Creating Shapes Never instantiate Shape directly it won't trigger the related events in code, use an IShapeFactory dependency IShape Create(string shapeType) in Orchard views, use New   - New is just an IShapeFactory cast to dynamic   - New.Product -> IShapeFactory.Create("Product") Rendering Shapes use well-named file templates use shape methods any method in class inheriting from IDependency with the [Shape] attribute future: dynamic shapes to come, e.g. from DB (by Piotr Szmyd) refer to IDisplayHelperFactory and IDisplayHelper for more detailed info Advanced Uses of Shapes If you're just starting with Orchard Shapes, I recommend you to skip this section for now ;-) Creating Strongly Typed Shapes in your ContentDriver, when creating a Shape, you can do: 1: protected override DriverResult Display(EntryPart part, string displayType, dynamic shapeHelper) { 2: return ContentShape("Parts_Common_Body" /* Placement Key */, 3: () => shapeHelper.Parts_Common_Body(Html: someHtml)); 4: } becomes: 1: public class ConcreteType : Shape { 2: public string Html { get; set; } 3: } 4:  5: protected override DriverResult Display(EntryPart part, string displayType, dynamic shapeHelper) { 6: var shape = (ConcreteType) shapeHelper.Parts_Common_Body(typeof(ConcreteType)) 7: shape.Html = someHtml; 8: return ContentShape("Parts_Common_Body" /* Placement Key */, 9: () => shape); 10: } And then in your template, you can actually define your @model to be of type ConcreteType: 1: @model My.Namespace.ConcreteType 2:  3: @Display(Model.Html) Shape Events We have different extension points to hook into the shape rendering process: IShapeDisplayEvent intercept all shape Display events ShapeMetadata intercept a specific shape's Display events IShapeTableProvider configured at discovery time, for a specific type hook into events other than Display Order of invocation of the different event handlers: Displaying ShapeDisplayEvents ShapteTableProvider ShapeMetadata Display Set Metadata.ChildContent Shape is rendered if ChildContent not set (open e.g. for Caching) Wrappers are rendered in order, from Metadata.ChildContent, e.g. Document.cshtml Displayed ShapeDisplayEvents ShapteTableProvider ShapeMetadata Shape Morphing change the Metadata.Type of a Shape before rendering render the same Shape again using a different template see the MenuItem template for an example Shape Relocation The idea here is to add a Shape to a different part of the page than where your current ContentItem is rendering. In your view, just use: 1: @Display(Model.MyTitle) Now, in your placement.info file, write: 1: <Match ContentType="Page" DisplayType="Detail"> 2: <Place Parts_Title="MyTitle:5" /> 3: </Match> This will display your Title shape (possibly) a second time.

Sample SMTP Session with Auth Login

by Oliver 13. June 2013 15:27

This post is most of all a log drop of an SMTP session I had with our mail server over telnet. We use hMailServer for all of our own and hosted e-mail accounts. Today, I set up a new account to use for our SQL servers to report any problems. I couldn't get SQL Server's DatabaseMail to successfully send any e-mail so I went to find out what might be wrong by myself. Here's my first successful chat with our mail server using AUTH LOGIN, i.e. username and password authentication: 1: 220 mail.teamaton.com ESMTP                                   // started session with: telnet mail.teamaton.com 25 2: hello                                                         // my first try - not quite ;-) 3: 502 Use HELO/EHLO first. 4: HELO                                                          // ok, I got you 5: 501 HELO Invalid domain address. 6: HELO                                                          // say again? 7: 502 Use HELO/EHLO first. 8: EHLO                                              // send a host name of the computer you're on 9: 250-mail.teamaton.com 10: 250-SIZE 15000000 11: 250 AUTH LOGIN 12: MAIL FROM: <sql*******@teamaton.com>                          // the from address to use for the e-mail 13: 250 OK 14: RCPT TO: <oliver*******@******.com> // trying to set a recipient's address 15: 530 SMTP authentication is required. 16: AUTH LOGIN                                                    // initiating login 17: 334 VXNlcm5hbWU6                                              // the server is asking for my username in base64 encoding 18: c3FsLXNl***************vbi5jb20=                              // sending my username in base64 encoding 19: 334 UGFzc3dvcmQ6                                              // the server is asking for my password in base64 encoding 20: YkZwN***************A1dng=                                    // sending my password in base64 encoding 21: 535 Authentication failed. Restarting authentication process. // oops, I copied some invisible character from that encoding web page 22: auth login                                                    // try again 23: 502 Unimplemented command.                                    // case seems to matter 24: AUTH LOGIN 25: 334 VXNlcm5hbWU6 26: c3FsLXNl***************vbi5jb20= 27: 334 UGFzc3dvcmQ6 28: YkZwN***************A1dng= 29: 235 authenticated.                                            // finally! 30: DATA                                                          // set the body of the e-mail 31: 503 Must have sender and recipient first.                     // hm, I thought I set the sender already… 32: MAIL FROM: <sql*******@teamaton.com>                          // oh well, set it again 33: 503 Issue a reset if you want to start over                   // I didn't want to start over! 34: RCPT TO: <oliver*******@******.com>                           // set only the missing recipient, then 35: 250 OK 36: DATA                                                          // now, set the mail body 37: 354 OK, send. 38: Test mail here. 39:  40: .                                                             // mark the end of the mail body 41: 250 Queued (11.247 seconds) 42: 421 Connection timeout.                                       // that's what happened after a while when I left the shell open 43:  44: Connection to host lost. 45:  46: C:\Users\Oliver> Every line that starts with a status code was sent by the server, the rest of them is what I entered. Just for the record.

SQL Server Compact timed out waiting for a lock

by Oliver 28. January 2013 14:26

Today, I faced the exception mentioned in the post title: SQL Server Compact timed out waiting for a lock. The default lock time is 2000ms for devices and 5000ms for desktops. The default lock timeout can be increased in the connection string using the ssce: default lock timeout property. (Plus some session details). Circumstances The exception was thrown in my local dev environment while working on our Orchard CMS based portal software discoverize, calling any page in the portal. Obviously, something was wrong not with a single page but rather with a piece of infrastructure. Interestingly enough, only a few moments before trying to open the web site I had done some database manipulation using SqlCeCmd deleting some unneeded columns from one of our tables. It seems that after that the site broke. Solutions tried I tried to get hold of the DB like this: stop and start the web site in IIS (using appcmd stop site "discoverize" and appcmd stop site "discoverize") – no change take DB offline by renaming the file – waited a few moments, renamed it back – no change! Here I started wondering where the lock is saved – is it inside the DB? took the whole application pool offline and restarted it – bang! That helped. I now have my site back up and running and can continue develepment. Conclusion If you encounter the SQL CE timeout error during development inside a web application, restarting the app's app pool will probably get you back to work. Happy coding!

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for jQuery. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our daughter. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.