Amazon.com Widgets All posts by williarob

WilliaBlog.Net

I dream in code

About the author

Robert Williams is an internet application developer for the Salem Web Network.
E-mail me Send mail
Code Project Associate Logo
Go Daddy Deal of the Week: 30% off your order at GoDaddy.com! Offer expires 11/6/12

Recent comments

Archive

Authors

Tags

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.


Blog Engine Save Button not working on large post

I recently wrote a really long (about 20,000 words) blog post. I had been saving it periodically as I typed, but it suddenly reached a point where the Save button just didn't work anymore. Bringing up Firebug I could see that the Ajax request was being sent and a 500 sytem Error was being returned by the server. When I tried to insert a breakpoint in the method it was never being hit.

This made me think that this size limitation was probably in ASP.Net, not in the BlogEngine.Net codebase, and sure enough that is what it is. jQuery doesn't limit the size, but ASP.NET does by default.  You can adjust it with this web.config setting:

 

<system.web.extensions>
 
<scripting>
     
<webServices>
       
<jsonSerializationmaxJsonLength="x">
       
</jsonSerialization>
     
</webServices>
 
</scripting>
</system.web.extensions>


Where x is the size limit in bytes.

If you insert this section into your web.config and start seeing errors, you will need to install ASP.NET AJAX. Visit www.asp.net/ajax for more details.

 


Categories: Ajax | JavaScript
Posted by Williarob on Wednesday, April 10, 2013 9:32 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Export options missing from Adobe Media Encoder

I installed the trial version of Adobe Media Encoder CS6 (Actually the whole CS6 Master Collection) just so that I could try exporting a video as a DPX image sequence. The installation took about 90 minutes. After opening Adobe Media Encoder and adding my source file I discovered that I couldn't export to any kind of image sequence:

Adobe Media Encoder Presets

Although they appear in the list of presets, they have no options beneath them and whichever one you select the Apply Preset button remains grayed out:

Adobe Media Encoder Presets Image Sequence greyed out

I watched a tutorial video on the Adobe Web site to make sure I wasn't missing something, but it made it very clear that it was as easy as selecting a preset, so why couldn't I select one of the image sequences? Google helped me find other people with the same problem, but no solutions. Eventually, however I did find the write combination of search terms and found a solution here.

Find the file named AddExporterList.txt located at

C:\Program Files\Adobe\Adobe Media Encoder CS6\txt

Save an original copy somewhere else. Copy/Paste or delete as necessary to make the new file look like this:

# MediaCore Plugins

# AME Plugins

AudioWriter
WinMediaWriter

# AME Plugin Formats

MPEG4

H.264 Blu-ray


Hit save and restart AME. Voila! It worked for me and hopefully it will work for you. My Export options are now greatly expanded:

The old AddExporterList.txt which was not working, looked like this:

# MediaCore Plugins

ExporterAIFF
ExporterAVI
ExporterBMP
ExporterCIT
CITExporter
ExporterDPX
ExporterGIF
ExporterGIFStill
ExporterJPEG
ExporterCoreAudio
ExporterNULL
ExporterP2
ExporterPNG
ExporterQuickTimeHost
ExporterTarga
ExporterTIFF
ExporterUncompressed
ExporterWave
ExporterWindowsMedia
ExporterXDCAMHD

# MediaCore Plugin Formats. Syntax: ExporterName.ZeroBasedIndexToBlacklist

ExporterMPEG4.1
ExporterMPEG4.2
ExporterMPEG4.3

# AME Plugins

AudioWriter
WinMediaWriter

# AME Plugin Formats

MPEG4
H.264 Blu-ray

Posted by Williarob on Friday, February 08, 2013 2:30 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Adding a Paypal Donate button to your Blogengine.Net blog or ASP.Net Page.

I recently had a request from a client to add a paypal donate button to their blog. So off I went to the Paypal site to get instructions for them on how to generate the button html for them to send to me.

  • Login to your paypal account (or create one).
  • Click on the Merchant Services tag.
  • Click on "Create Payment Buttons for your Website"
  • Choose "Donate" as the button type, and complete the form.
  • At the end of the process, you have the html you need to add the button to any site.

They did all this and sent me the html which consists of a simple form. Initially, I simlpy created a new text widget and pasted it in. The button looked as it should but when I clicked on it I got a 404 error. I viewed the source for the page and saw that the Form tag had been stripped, probalby by the text editor. No problem, I went to the Site Master page, and pasted it directly into the theme template, exactly where it was needed. Published the change, still goes to a 404 page. Then I realize what the problem is. I'm nesting forms. Blogengine.Net, like many traditional ASP.Net based sites, relies on the page being wrapped in a <form runat="server"> tag, which allows for all the postback stuff to work.

A quick Google search for "BlogEngine PayPal Donate button" returned a handy little Extension. But on closer inspection I could see that while this would add a button inside a post, it could not be relied upon to add it to the frame of the page itself, so that it could appear at all times, regardless of which post or page you were viewing. Of course, if it could add it to a post it must have found a way around the nested form issue, so I took a look at the code and discovered that it was creating a simple link, that is an image, wrapped in an anchor tag that looked something like this:

<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=[email address here]&item_name=[Description, e.g. "Donation to MySite.com" (UrlEncoded)]&no_shipping=0&no_note=1&tax=0¤cy_code=USD&lc=US&bn=PP%2dD onationsBF&charset=UTF%2d8"><img src="Path/To/PaypalDonateButton.jpg" /></a>

So I filled in my information and I finally had a working paypal donate button. However, I didn't like the fact that my email address was now so firmly embedded on the page, I rather liked the anonymity that the original paypal code offered. Any spider could skim my email from the page and start adding to the thousands of spam emails I already receive every day. So I kept looking for other solutions. As usual, Stack Overflow had a better solution.

Instead of using the anchor tag which makes a Get request and exposes your email address, paste in the full code from paypal, then delete the form tags. Replace the image input with a server side image button or regular button and have it post back to paypal for example If the paypal code looks like this:

 

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="xxx">
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" 
alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>

 

You paste it all in where you want it then modify it like this:

 

<input name="cmd" type="hidden" value="_s-xclick" /> 
<input name="hosted_button_id" type="hidden" value="xxx" /> 			
<asp:ImageButton ID="btnDonate" 
AlternateText="PayPal - The safer, easier way to pay online!" runat="server" 
ImageUrl="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" 
 PostBackUrl="https://www.paypal.com/cgi-bin/webscr" OnClick="btnPayNow_Click"/>
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1" />

 

In your code behind, add an empty method to handle the OnClick specified above (btnPayNow_Click):

 

protected void btnPayNow_Click(object sender, EventArgs e)
{
        
}

 

That's it! Now you have a working Paypal donate button. If you want to test it out to see if it works, by all means click on the one you see on this page ;) Or, you can change the postback Url on your button to "https://www.sandbox.paypal.com/us/cgi-bin/webscr" which should allow you to test it without actually spending any money.


Categories: ASP.Net
Posted by Williarob on Friday, October 26, 2012 7:43 AM
Permalink | Comments (0) | Post RSSRSS comment feed

WINDOWS 7: Explorer Locks "thumbs.db" in most recently viewed folder

Problem

On windows 7, you navigate to a folder that contains images or video files that you have either added new content to or have simply never explored before, if you then back out of that folder and try to delete it, you are warned that "The action can't be completed because the file is open in Windows Explorer. Close the file and try again. Thumbs.db":

Clicking Try Again any number of times will not resolve the issue. All of the files within that folder (except Thumbs.db) do still get deleted.

Usually, if you navigate to another folder for which a new Thumbs.db file is generated, then often the original problem folder can be deleted (though the most recently explored one can not), but sometimes a reboot is required. Even switching to another PC and trying to delete the folder through the network doesn't work. This was not an issue with Windows Vista.

Solution

It turns out that Windows 7 no longer relies on hidden Thumbs.db files to manage its thumbnails - that's now done with a central thumbnail cache - and it only generates these db files for backward compatability purposes. So, in my opinion, the best solution is to stop using Thumbs.db files entirely. Just to be clear, this does not mean that you will no longer see thumbnails of images and videos in windows explorer. Thumbnails will still be generated and your Windows Explorer experience as a user will be unchanged (except that you will be able to delete your folders more freely because these pesky thumbs.db files will no longer be an issue).

There are a number of ways to implement this fix and I believe they all require a reboot for the change to take effect. If you have a version Windows 7 that allows you to edit group policies (Windows 7 Professional, Ultimate or Enterprise) you can follow these steps to resolve the problem:

·    Click the Start orb

·    Enter gpedit.msc in the search box and hit Enter.

·    Expand User Configuration - Administrative Templates - Windows Components. 

·    Click on Windows Explorer.

·    Right-click the entry "Turn off the caching of thumbnails in hidden thumbs.db files" and choose Edit.

·    Enable the setting.

If you have Windows 7 Starter, Home Basic or Home Premium, or just want a quicker solution here's the .reg file equivalent of the group policy fix above.

(Paste the text below into Notepad, save it with a .reg extension, and then double-click the file.)


Windows Registry Editor Version 5.00

; Enables group policy: "Turn off the caching of thumbnails in hidden thumbs.db files"

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer]
"DisableThumbsDBOnNetworkFolders"=dword:00000001


Alternatively you could download a .reg file I made earlier, and simply double click on it:

ThumbsDbFix.reg (244.00 bytes)

Or:

Bring up a (administrator) CMD prompt and type (or paste):

  REG ADD "HKCU\Software\Policies\Microsoft\Windows\Explorer" /v "DisableThumbsDBOnNetworkFolders" /t REG_DWORD /d 1 /f

And you're done.


Tags:
Posted by Williarob on Wednesday, March 14, 2012 11:48 AM
Permalink | Comments (0) | Post RSSRSS comment feed

visualsvn server "'repositories' is not a valid short filename"

Problem

I had been trying to upgrade my standard edition Visual SVN Server for months now. Every time I received the email notification of a new version I would download the update, run it and the install would fail with the error "'repositories' is not a valid short filename". Google helped me find a handful of people seeing the same error, but no solutions. Ever hopeful that the next release would not have this issue, I tried again today with the latest version but the same thing happened. Then I had an idea:

Solution

Before you run the installer, open VisualSVN Server Manager and click the stop button. Then the install will complete without a hitch. Why the installer doesn't stop the service for you before it tries to install is something only the VisualSVN Team can answer.


Categories: SVN
Posted by Williarob on Monday, March 12, 2012 12:45 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Generic AddOrUpdate Extension for IDictionary (C#)

I recently came across a situation where the properties of a class were adding the value to an internal dictionary of key value pairs which made it easy to loop through and return a JSON string. This worked great until we later ran into a situation where we needed to update a property after it had already been set, which of course generated a "System.ArgumentException: An item with the same key has already been added". While it is easy enough to add a check to see if the dictionary already contains the key you are attempting to add, doing this for every property would be way too much code repetition so an Extension Method seemed appropriate.

Add the following extenstion method to a static class in your solution, then add that namespace to the list of namespaces you are "using" at the top of any class that might need it, and your Dictionary will have a .AddOrUpdate(key, value) method:

        public static IDictionary<TKey,TValue> AddOrUpdate<TKey,TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
        {
            if(dictionary.ContainsKey(key))
            {
                dictionary[key] = value;
            }
            else
            {
                dictionary.Add(key, value);
            }

            return dictionary;
        }

 


Categories: C#
Posted by Williarob on Tuesday, August 30, 2011 8:54 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Printable HBO Game of Thrones Viewer's Guide

Like many people, after thoroughly enjoying the first season of Game of Thrones on HBO, my wife and I started reading the books. Even with the show fresh in our minds, we found ourselves getting confused Jory/Jorah, Tyrion/Tywin so we went online looking for a nice cheat sheet. If you haven't already been there, take a look at the official HBO viewer's guide. It's presented beautifully, and easy to follow. As a web developer, I can appreciate the hard work that went into this great site.

However, thinking that we didn't want to keep going online to check every time we needed to, we thought it would be great to print it all out. What a mistake that was. All formatting is gone, and this is the result:

With the layout all messed up, the printed pages are useless!

So, with a little help from FireBug for Firefox and Adobe Photoshop, I have created a nice printable version of the site:

Download it here in Adobe PDF Format:

HBO Game of Thrones Guide to Houses.pdf (2.27 mb)


Posted by Williarob on Monday, July 25, 2011 2:10 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Moving Files in Visual Studio and SVN

I'm writing this down because (1) I've had to figure it out a few times already and don't want to figure it out again, and (2) it may save you some snortin' and cussin' if you run across it yourself. It is astonishingly annoying.

If you have an MVC 3 project in Visual Studio 2010 and while refactoring you move a file - for example you move a view model to the shared area, you may suddenly encounter a compile error in some random temporary file like the one below:

The type or namespace name 'xxx' does not exist in the namespace 'xxx' (are you missing an assembly reference?)    c:\Users\[user name]\AppData\Local\Temp\Temporary ASP.NET Files\temp\eab6c63b\948de17e\App_Web_hadnllup.0.cs

Cleaning the solution and/or deleting the temporary files will not resolve the problem. This can happen whether you simply drag and drop the file to the new location, then change the namespace yourself, or if you right click on the file and choose Refactor > Move and have Visual Studio move the file and update the namespaces for you. The latter process (in theory) will update all references to the file within your project automatically, while with the former, you would typically try to compile the project and then fix all the broken items that now appear in the Error list as a result of the namespace change. However, unless you do a global find and replace, you will probably still end up getting the cryptic error above because chances are that the @model declaration in one or more of your Views is still pointing to the old namespace for that viewmodel file. Update the view(s) and the error will go away and all will be fine.

Now, if you use SVN, things are a little more complicated: If you move the file using either of the techniques described above, what will happen is SVN will delete the original file and create a new one for the new location, which is fine, unless you were hoping to preserve the full subversion history of that file. If you want to preserve the file history in SVN and move the file, this is how you do it: in Windows Explorer, right-click and drag the file from its old location to its new location, then select "SVN move versioned item" from the context menu. This will not only move the actual file itself, but it will also make sure that all the file history stays with it after you check in your changes. Back in Visual Studio, use the Solution Explorer in VS2010 to "exclude from project" the (now-missing) copy of the file in its old location, and then "include in project" the file in its new location. You may need to refresh the view in solution explorer and/or make sure you are viewing all the files by clicking the "Show all Files" icon at the top (next to the refresh icon) in order to see these files.

After you update the namespace to reflect the new location, I recommend using a global find and replace before you try to compile to save yourself a lot of trouble.

To summarize, if you find yourself getting obsolete, broken references in auto-generated files that you can't permanently delete, look in your Views folder for the bad references.


Posted by Williarob on Wednesday, May 25, 2011 7:33 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Firefox 4 doesn't save tabs

Problem: I've downloaded Firefox 4 and now I am no longer able to save my tabs. How can I fix that?

Solution: By default this function has been disabled. To enable it, do the following:

1. In the address line, type in "about:config" (without quotation marks). Click on "I'll be careful, I promise!"

2. In the filter field, type in browser.showQuitWarning. This should filter out all other options

3. Double click on the option that is left in the list. The value should switch from "false" to "true".

4. Close about:config tab and it should work


Posted by Williarob on Friday, May 06, 2011 1:53 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Using System.Threading.Tasks and BlockingCollections to FTP multiple Files at the same time

I recently needed to write an application that would loop through a queue of files and FTP them to our Content Delivery Network for streaming. Users upload files, and our administrators can mark some of them as urgent. Urgent ones need to jump to the front of the queue, otherwise everything should be orderd by broadcast date. My initial code was basically a loop that looked something like this:

While (GetFtpQueue().Count > 0)
{
    // Gather all the info from the db,  Ftp the file, then clean up (move the source file, update the db, etc.

}

It worked beautifully while we were just uploading small audio files, but as soon asl we started adding a lot of video files to the queue it became so slow that it might take 2 hours or more to upload a single video file. So, we experimented with Filezilla to see how many concurrent uploads we could add before the overall speed of each upload started to drop. We found that at our location, 4 simultaneous FTP uploads seemed to hit the sweet spot: instead of uploading 1 file at 500 kb/s we could upload all four and each one would still be at that speed, quadrupling our throughput.

I read up on using the new Threading classes in .Net 4.0, and began refactoring my FTP application. I decided to use the Task Factory to manage the threads, in conjunction with a BlockingCollection to create a classic Producer/Consumer pattern. My first attempt looked a lot like this:

int maxThreads = 4;
var filesToFtp = new BlockingCollection<FtpItem>(maxThreads);
var processedFiles = new BlockingCollection<FtpItem>();

// Stage #1: Producer
var initFtp = Task.Factory.StartNew(() =>
{
    try
    {
        While (GetFtpQueue().Count > 0)
        {
            // Gather all the info from the db and use it to create FtpItem objects
            // Add them to list of filesToFtp, which only allows maxThreads in at a time (this allows us to have an urgent item jump to the top while current items are still FTPing)
            filesToFtp.Add(new FtpItem { ... };
        }
    }
    finally { filesToFtp .CompleteAdding(); }
});

// Stage #2 Consumer of initFtpTask and Producer for Cleanup Task
var process = Task.Factory.StartNew(() =>

{
    try
    {
        foreach(var file in filesToFtp.GetConsumingEnumerable()
        {
            // Ftp the file
            // Add to list of processedFiles
            processedFiles.Add(file);
        }
    }
    finally { processedFiles.CompleteAdding(); }
});

// Stage #3
var cleanup = Task.Factory.StartNew(() =>
{
    foreach(var file in processedFiles.GetConsumingEnumerable()
    {
        // Clean up (move the source file, update the db, etc.
    }
});

Task.WaitAll(initFtp, process, cleanup);

Initially, this looked quite promising. I wrote a bare bones version of it like the one above that just did thread.sleep to simulate work and iterated through a list of ints. I was ablt to verify that each "stage" was running on it's own thread, that it never allowed more than 4 items through at a time, that I could add items to the front of the queue and get them processed next, and that it never tried to 'cleanup' a file until that file had passed through both stage 1 and stage 2. However, I did notice that the elapsed time was the same as when I ran a similar unit test in a simple while loop. It might be obvious to you why this is, but at the time I put it down to a limitation of the unit test and pushed my new code to production. The first thing I noticed was that it wasn't any faster. Not even slightly. It took me hours of staring at the code to finally figure out why my multi threaded code was not running any faster, but the answer is simple: I only created one consumer of filesToFtp. I had incorrectly assumed that because I was creating up to 4 ftpItems at a time, and the ftp process was running on it's own thread, that it would consume as many as it could, but the reality is that in the code above, while each of the three stages are running on their own thread, the whole process was still happening in series, since stage 1 doesn't create 4 items at once, it creates them one after the other, stage 2 does begin working before stage 1 is complete (as soon as there is an item to consume), but then it will be busy Ftping that first item until that item is fully uploaded, only then will it grab the next file.

To resolve this problem, I simply wrapped stage 2 in a for loop, and created a IList of Tasks to wait on:

int maxThreads = 4;
var filesToFtp = new BlockingCollection<FtpItem>(maxThreads);
var processedFiles = new BlockingCollection<FtpItem>();
IList<Task> tasks = new List<Task>();

// Stage #1: Producer
tasks.Add(Task.Factory.StartNew(() =>
{
    try
    {
        While (GetFtpQueue().Count > 0)
        {
            // Gather all the info from the db and use it to create FtpItem objects
            // Add them to list of filesToFtp, which only allows maxThreads in at a time (this allows us to have an urgent item jump to the top while current items are still FTPing)
            filesToFtp.Add(new FtpItem { ... };
        }
    }
    finally { filesToFtp .CompleteAdding(); }
}));

// Start multiple instances of the ftp process
for (int i = 0; i < maxThreads; i++)
{
    // Stage #2 Consumer of initFtpTask and Producer for Cleanup Task
    tasks.Add(Task.Factory.StartNew(() =>
    {
	try
	{
		foreach(var file in filesToFtp.GetConsumingEnumerable()
		{
			// Ftp the file
			// Add to list of processedFiles
			processedFiles.Add(file);
		}
	}
	finally { processedFiles.CompleteAdding(); }
	}));
}

// Stage #3
tasks.Add(Task.Factory.StartNew(() =>
{
	foreach(var file in processedFiles.GetConsumingEnumerable()
	{
		// Clean up (move the source file, update the db, etc.
	}
}));

Task.WaitAll(tasks.ToArray());

I reran the unit test and it was faster! Very nearly 4 times faster in fact. Wahoo! I updated the code, published my changes and sat back. Sure enough, the Ftp process finally started to make up some ground. In the mean time, I went back to my unit test and began tweaking. The first thing I noticed was that sometimes I would get a "System.InvalidOperationException: The BlockingCollection<T> has been marked as complete with regards to additions." Luckily, this didn't take a lot of head scratching to figure out: the first thread to reach the 'finally' clause of  stage 2 closed the processedFiles collection, leaving the other three threads hanging. A final refactoring resolved the issue:

int maxThreads = 4;
var filesToFtp = new BlockingCollection<FtpItem>(maxThreads);
var processedFiles = new BlockingCollection<FtpItem>();
IList<Task> tasks = new List<Task>();

// maintain a seperate list of wait handles for the FTP Tasks, 
// since we need to know when they all complete in order to close the processedFiles blocking collection
IList<Task> ftpProcessTasks = new List<Task>();

// Stage #1: Producer
tasks.Add(Task.Factory.StartNew(() =>
{
	try
	{
		While (GetFtpQueue().Count > 0)
		{
			// Gather all the info from the db and use it to create FtpItem objects
			// Add them to list of filesToFtp, which only allows maxThreads in at a time (this allows us to have an urgent item jump to the top while current items are still FTPing)
			filesToFtp.Add(new FtpItem { ... };
		}
	}
	finally { filesToFtp .CompleteAdding(); }
}));

// Start multiple instances of the ftp process
for (int i = 0; i < maxThreads; i++)
{
	// Stage #2 Consumer of initFtpTask and Producer for Cleanup Task
	ftpProcessTasks.Add(Task.Factory.StartNew(() =>
	{
		try
		{
			foreach(var file in filesToFtp.GetConsumingEnumerable()
			{
				// Ftp the file
				// Add to list of processedFiles
				processedFiles.Add(file);
			}
		}
	}));
}

// Stage #3
tasks.Add(Task.Factory.StartNew(() =>
{
	foreach(var file in processedFiles.GetConsumingEnumerable()
	{
		// Clean up (move the source file, update the db, etc.
	}
}));


// When all the FTP Threads complete
Task.WaitAll(ftpProcessTasks.ToArray());

// Notify the stage #3 cleanup task that there is no need to wait, there will be no more processedFiles.
processedFiles.CompleteAdding();

// Make sure all the other tasks are complete too.
Task.WaitAll(tasks.ToArray());

Download a working example (Just enter your FTP Server details prior to running):

ProducerConsumer.zip (11.18 mb)


Posted by Williarob on Monday, April 18, 2011 11:47 AM
Permalink | Comments (0) | Post RSSRSS comment feed