Yesterday I walked into an interesting problem. After I finished cleaning up an SVN debug folder, my MVC app stop working, specifically calls to JSON. That were working previously.
I thought it must have something to do with silverlight since it was there where I found the exception. I did a series of searches looking for an answer, but I didn't find one since I looking at the wrong thing.
The actual problem had to do with MVC. I was getting the following response:
This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.
I did a search on this error. Behold! The issue was a change in how JSON is handled in .NET MVC. Adding a simple line took care of the issue.
return Json(result, JsonRequestBehavior.AllowGet);
So I want to use the .Net DataContractJsonSerializer object. I check on msdn for what are the references that are needed:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.jso...
But it didn't work. I wasted about 20 minutes trying to troubleshoot what it was. I did a search on it, and I got the following answer:
using System.Runtime.Serialization;
using System.ServiceModel;
System.Runtime.Serialization.dll
System.ServiceModel.dll
System.ServiceModel.Web.dll
http://forums.silverlight.net/forums/p/14304/367154.aspx
Grrr. What is wrong with that .Net documentation? So I go back, and scroll to the comments:
Regarding the problem mentioned earlier, i want to say this article is right: this class resides in System.Runtime.Serialization dll for the .NET Framework 4. The problem lies in the assembly version: although the class is contained in the version 4.0.0.0 assembly, you won't find it in earlier versions. This class was migrated from System.ServiceModel.Web to System.Runtime.Serialization in .NET 4.
Thus, if you are using .NET 3.5 SP1 or earlier, you should look for this class in System.ServiceModel.Web dll.
Ah! So that was the problem! Maybe this is a false memory, but wasn't there an easy way to toggle between the different versions of a page on the msdn site? That was useful.
Learning testing from dynamic languages such as javascript and php, my experience with testing uploads or file creation was via actually creating a file during test, verifying its existence, and then erasing this file. When I tried this in C# using Moq, the tests wouldn't fail, but the file wasn't created.
I was missing something, so I found this excellent link on testing file uploads in asp.net http://www.hanselman.com/blog/ABackToBasicsCaseStudyImplementingHTTPFile...
After reading it over, I realized that:
1. The problem was that I was calling SaveAs() from HttpPostedFileBase class, not HttpPostedFile. As an abstract class, this method is not implemented. Moq must implement this method for one. Nice, nice Moq.
2. There is a nice couple of method called Verifiable() and Verify(), and they belong to the Mock object. My using it in the following manner
file1.Setup(f => f.SaveAs(It.IsAny())).Verifiable();
We can later called
file1.Verify();
And this will verify that the method got called. So there is no need for me to implement SaveAs() to test that it is being called.
Bonus aside:
Thinking back, it seems that I have learned many new concepts via scripting languages. I believe it is because the simpler language interface allows one to exercise the features more seemly by not having to think of elaborate setups.
Today I spent many hours troubleshooting the unable to cast Object type X to X . As I said in the previous blog entry, I am starting an asp.net mvc project because I want to TDD this project. So I finished translating the existing project from web forms to asp.net mvc, and now the only thing I have to confirm is that the unit test that I adapted for testing file uploads pass. (By the way, the wonderful page is found here: http://csainty.blogspot.com/2009/01/aspnet-mvc-unit-test-file-upload-wit...)
And it won't work.
I repeated the steps on how to create the mocks and how to test the entry, and it doesn't work. It give me this weird error
unable to cast Object type System.Web.Mvc.Content to System.Web.Mvc.Content
I rubbed my eyes a few times. It looks to me that it is the same. So I try it again. Same result. I recreated, step by step, the test. Same result. I researched a possible bug in NUnit. Nothing. Just in case, I repeated the test using Microsoft's test framework. Same error.
I research the specific bug connecting it to mvc. Nothing relevant. I try just the bug. This time I got a page that said that this error could be triggered by having some repeated URI references. This is potentially possible, so I decide to repeat the experiment in a new project. This time, it works using visual studio's framework. I try it again using Nunit, and it fails. I start to suspect that it is Nunit or that there is something in visual studio's framework that can make it pass. I try a third project, and this time visual studio's frameworks fails too.
So I research this error again. This time, I got this excellent link:
http://www.hanselman.com/blog/FusionLoaderContextsUnableToCastObjectOfTy...
Where Scott Hanselman explains how this error can happen from using two different DLLs. Let me quote(quote()) here:
Suzanne Cook puts it best, emphasis mine:
For example, path matters when determining whether a type is castable to another type. Even if the assemblies containing the types are identical, if they're loaded from different paths, they're considered different assemblies and therefore their types are different. This is one reason why using contexts other than the Load context is risky. You can get into situations where the same assembly is loaded multiple times in the same appdomain (once in the Load context, once in the LoadFrom context, and even several times in neither context), and their corresponding types won't be castable.
So I checked in my project, and yes, this was the problem. Those test passed right away.
I just started working on a new project. As you know, I got agile religion earlier this month, and I am a born-again coder, who wants to test his code as he goes. Also, after doing a few TDD projects, not doing it seems wrong, and it is just not as fun.
So I got a new .Net project, and this time I actually can do it right. I am going to do it right. I set up Moq and NUnit, and off I go to test land. Now All what I have to figure out is how to mock HttpRequest to test an upload method. I research the question. And in most cases, most of the solutions involved Asp.net mvc. I kept trying to find something specific to just plain asp.net, but the information that I got was either very old, or was a tangential mention that in an mvc page about how the solution could also work with regular asp.net pages.
So the pragmatic solution was to move the back end of the project to mvc. Fortunately for me the project only has a couple of pages of code, and translating the behavior from asp.net to mvc was quick. In fact, it seems that it takes a lot less work code to do the same work.
I am not saying that it is not possible to TDD regular asp.net. I am sure it is. But most of the information and resources exist for asp.net mvc, so, if it is possible, it makes a lot more sense to adopt it if one wants to TDD a asp.net project.
ln -s /path/to/directory ./linkname
A while ago I said that I may come back and enter detail instructions on how to install simple test on drupal 6 on Windows. I forgot about it, and, of course, I need that information now. So here it is, in its detailed glory, how to do this.
1. Download simple test from this link http://drupal.org/project/simpletest
2. Make sure that you have curl installed. Check whether curl has been installed by looking at your phpinfo() page, or running on the command line php -i . If you don't have it installed, install it. On windows, that means going to your php.ini, and uncommenting the line where it says php_curl.dll and potentially moving php_curl.dll to Windows/system32 More information on this link http://www.php.net/manual/en/curl.installation.php read the 28-Dec-2009 07:17 comment by wixelbomb for more details on it.
3. Run the patch on drupal 6 core. Oh, boy, was this fun 2 months ago.
First, information on applying the patch is given here http://drupal.org/patch/apply If you are using windows, that means that the utility that you need must be run in cygwin http://www.cygwin.com/ or you need http://unxutils.sourceforge.net/ . That is actually not that bad. More information specific to windows on http://drupal.org/node/60179
What ended up being hard to figure out where you should run the patch. The answer to this, for simpletest, is your root drupal directory. Since I don't like to type too much, I copied and pasted D6-core-simpletest.patch to root, and ran the following command in cygwin
patch -p0 < D6-core-simpletest.patch
That should be it. Then you can have fun testing.
I just had a great time not being able to log into mysql after I attempted to reinstall, due to some problems that I had with my environment. Oh, was that fun. Fortunately, I found this article with detailed information:
http://lstigile.wordpress.com/2009/06/15/mysql-windows-install-troublesh...
use the recursive option, -r.
grep -r tastypies .
I have also found people who do
find . | xarg grep tastypies
The man page
http://unixhelp.ed.ac.uk/CGI/man-cgi?grep
R is an open source implementation of S-Plus language. There is a nice RGUI for windows, and following the excellent tutorials can be cumbersome if you don't know how to establish what is the working directory and how to navigate around. So here is this mini tutorial of sorts.
After R installs, the default working directory is My Documents folder. To confirm this, type
getwd()
and you should see where you are. To move around, you use
setwd()
Two issues on using this function when you are working in windows. First, to move around, you will need backslashes for the path separator. This is confusing since when you enter getwd(), the path that you get has forward paths, for example,
c:/development/rscripts
Attempting to move around using forward slashes will get you errors. You got to use escaped backslashes. Example:
setwd("c:\\bin")
Second, it is not clear, but you can actually use setwd() as cd. So you can navigate up and down directories via statements like this:
setwd("..\\Desktop")
setwd("..\\..\\fantasy\\directory")