This blog has moved, permanently, to http://software.safish.com.

Thursday, August 18, 2011

Cruise Control Powershell Script with spaces in path

 

I have a powershell script that is executed as a Cruise Control.NET task.  The problem is, the script sat in a length path with spaces in some of the folder names.  The “powershell” task itself doesn’t support spaces, so the solution to this is to use old-school 8 character directory names.

For example, if you script lies in the path “C:\Parent Folder\NotParent Folder”, set your task up as follows:

<powershell>
	<script>myscript.ps1</script>
	<executable>C:\windows\system32\WindowsPowerShell\v1.0\powershell.exe</executable>
	<scriptsDirectory>C:\Parent~1\NotPar~1</scriptsDirectory>
	<description>Build something.</description>
</powershell>

Friday, July 8, 2011

HTTP Header Errors with MVC3 Redirects

 

We noticed in our error logs that we were getting quite a few of these good old errors:

"Cannot redirect after HTTP headers have been sent."
This wasn’t affecting our system from a usability point of view, but it’s irritating nonetheless. Anyway, the cause of the error was the following code in the OnActionExecuting override of a custom ActionFilterAttribute:
HttpContext.Current.Response.Redirect(“our url”, true)

Looks fine, right?

The error here is that within action filter attributes, you don’t know what other code is being executed in the request pipeline – in our case we had a BaseController adding caching headers in the OnResultExecuting override. 

The correct way to do this is to set the result of the filterContext object – this gets dealt with immediately and the error goes away.  The correct code is:

filterContext.Result = new RedirectResult(“our url”);

Pretty trivial, I know, but I Googled this and found very little out there that actually describes this error and the solution.

Friday, May 6, 2011

MVC3 Deployment Nightmare

 

I had a freaking nightmare deploying an MVC3 app today.  Seems simple.  Database was up and running.  The code was deployed and had been tested on our local systems.  I deployed via our amazing SVN deployment process, and published on the live server.  Permissions applied automatically, all the files appeared – all was good in the world.  Until I loaded up the site in my browser and hit…

Infinite Redirects

Fan-freaking-tastic.  Double-check the Web.config.  Fine.  Double-check the IIS mappings.  Fine. This ruined my day.  To cut a long story short: this all boils down to conflicts between the versions of MVC3 binaries between RC1 and RC2.  If you search on the web you will find numerous references to issues with the get_viewBag() call, and to be honest, I didn’t have to time to fully understand WHY this is such a cockup.

Either way, the solution I finally came up with was to UNINSTALL MVC3 on the web server, manually add the .dll references to our project, and force "Copy Local".

http://www.tugberkugurlu.com/archive/deployment-of-asp-net-mvc-3-rc-2-application-on-a-shared-hosting-environment-without-begging-the-hosting-company

The DLLs that must be referenced:

  • Microsoft.Web.Infrastructure
  • System.Web.Razor
  • System.Web.WebPages
  • System.Web.WebPages.Razor
  • System.Web.Helpers
  • System.Web.WebPages.Deployment (If you are deploying MVC RC 2, this assembly is necessary to deploy)
  • System.Web.Mvc

Make sure these copy locally to your bin folder (Right click, Properties, Copy Local = true)

This sorted out that bug.  Enter the next issue: The type or namespace name 'WebMatrix' could not be found (are you missing a using directive or an assembly reference?).  WTF!?

Web Matrix Agony Part 1

MVC3 RC2 has a bug where some of the source files have "using WebMatrix" references in them. As such, even though you don't need them, your project will not run without a reference to WebMatrix, which is annoying.

The obvious solution is to add these as a reference, but I tried that and it fails because WebMatrix requires an initialisation call in the Global.asax. Bummer.  I redeployed, and my error message now changed to

You must call the "WebSecurity.InitializeDatabaseFile" or "WebSecurity.InitializeDatabaseConnection" method before you call any other method of the "WebSecurity" class.

EFF THIS.

Web Matrix Agony Part 2

To get around this, in your global.asax make sure you add the following code at the bottom of the file:

namespace WebMatrix.Data { internal class Ignore { } }
namespace WebMatrix.WebData { internal class Ignore { } }

Reference: http://stackoverflow.com/questions/4146545/razor-helper-in-mvc-3-rc

This works as the statements in the MVC3 source binaries are only using statements!  I added these lines to the end of my Global.asax with a big comment about how much I hate the world and how much those 2 lines of code REALLY NEED TO STAY; removed the WebMatrix references I had added earlier, published, and redeployed.

And everything started working.

Thursday, May 5, 2011

Odds and Ends

 

Symbolic links in Windows: http://technet.microsoft.com/en-us/library/cc753194(WS.10).aspx – this was weird.  I was moaning to Rohland about how I missed have symlinks from Linux, but I’d never bothered to research the alternative in Windows, assuming that Shortcuts were all we have.  It turns out, you CAN make sybmbolic links in Windows.

Sick of Windows 7 copying? http://www.codesector.com/teracopy.php – I love this tool.  It also queues copying requests so you don’t end up with a hard drive going back and forth like a scratch record.

Precompiling Razor views: http://odetocode.com/blogs/scott/archive/2011/02/16/notes-on-building-razor-views.aspx – this is awesome.  Set up your Debug version to not precompile views, and set up an automated build to precompile views in Release mode at a regular interval to catch any issues in your views caused by refactoring.

PNGOUT: http://advsys.net/ken/utils.htm – this is a FREE tool that reduces the size of PNG files by 5 – 30%.  Running this on all images for presentations, blog posts and web sites is a pretty good idea!

Dapper: http://code.google.com/p/dapper-dot-net/ – this looks SO useful for smaller projects.  It’s being used on stackoverflow.com though – maybe not such small projects too!

IIS Compression: Excellent post by Rick Strahl with regards to setting up compression in IIS7: http://www.west-wind.com/weblog/posts/2011/May/05/Builtin-GZipDeflate-Compression-on-IIS-7x

Thursday, January 27, 2011

WCF Quick and Dirty

I added some WCF services to an existing project today, and I found I had completely forgotten the easy way of setting this stuff up.  So, here goes.  Note that you will usually split your host and consumer between separate projects – this is just an outline of the basics when working with Visual Studio 2010 and isn’t really concerned with actual implementation.

Create the DataContract Classes

These are the classes that will be serialized and submitted by WCF.  For example, if you are creating a service to add two numbers, you would have a class like so:

[DataContract] 
public class ExampleDataContract 
{ 
 [DataMember] 
 public int Num1 { get; set; } 

 [DataMember] 
 public int Num2 { get; set; } 
} 

Create the Service

Now that we have the data contract, we can create the actual service. 

  1. Navigate to the location in your solution where the service will sit, and add a new item (a WCF Data Service).
  2. The service is now created.  The interface should be decorated with a ServiceContract attribute.
  3. Any methods added to the interface will need to be decorated with an OperationContract attribute.
  4. In terms of the contract implementation, you will need to decorate your class with a ServiceBehavior attribute.  For example:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, AddressFilterMode = AddressFilterMode.Any)] 

Configure the Service

You can manually configure your service in your App.config file, but there is actually a GUI that makes this a lot easier.  All you need to do is righ-click your config file and there will be an option to Edit WCF Configuration – click this to launch the editor.

Note that if your project is not a WCF project, this may not be available in the context menu.  There’s an easy work-around for this though:

    1. Select Tools->WCF Configuration Editor from the Visual Studio menu, and click WCF Configuration Editor
    2. Close the WCF Configuration Editor

Now when you right-click the App.config the Edit WCF Configuration option should be available.

Usually there shouldn’t be too much to change here unless you’re manually creating your endpoints/services.  If you’re just wanting the basic endpoints, you can give the endpoints names (e.g. AddNumbersHttp for the wsHttpBinding) and continue.

We now have enough set up to host and test the service.

Test the Service

Visual Studio 2010 makes testing WCF apps really simple.  If you’re working with a WCF project, when you run the project Visual Studio will fire up the WCF test client by itself.

If you’re developing a web project, this won’t work, so you will need to fire up the client manually by opening a Visual Studio Command Prompt and typing the following:

wcftestclient http://yoursite/Services/YourService.svc.

If you get errors here, you may need to configure your web site.  There are two possible issues:

  1. IIS has not been configured to handle the .svc extension.  This is easily fixed by running the registration tool that comes with .NET – run ServiceModelReg.exe -i from the "%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation" directory
  2. If you are getting an error that the service cannot be activated because it does not support ASP.NET compatibility you can either configure your application for compatibility mode, or mark your service implementation with the following attribute:
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

Create the Client

You can now create the client that will consume the services created above. 

  1. Right-click your project’s References, and click Add Service Reference
  2. If you want to use a service within another project in your solution, you can click the Discover button and select Services in Solution
  3. Select the service, and enter a namespace that will be used within the client project to refer to the service
  4. You can now use the service like any other C# class, for example:
    MyServiceNamespace.MyServiceClient client = new MyServiceNamespace.MyServiceClient();
    client.AddNumbers(1, 2);
    client.Close();
    

Resources

  1. http://msdn.microsoft.com/en-us/netframework/dd939784
  2. http://channel9.msdn.com/shows/Endpoint/Endpoint-Screencasts-Creating-Your-First-WCF-Service/

Wednesday, November 17, 2010

Determining the target .NET Framework version of a .NET assembly

To determine which version of the .NET framework an assembly supports, you can use ILDASM.

Open up a visual studio command prompt, and type the following:

ildasm.exe C:\Yourdll.dll /metadata[=MDHEADER] /text /noil

You’ll get a large amount of indecipherable data, but right at the top, you’ll see something to the effect of

// Metadata section: 0x424a5342, version: 1.1, extra: 0, version len: 12, version: v4.0.30319

where the highlighted piece gives you the supported version.

Alternatively, you can just open ildasm (just type ildasm at the command prompt), and open up the dll – you can see the metadata version right at the top by double-clicking “MANIFEST”:

Mainfest

Useful!

Tuesday, November 16, 2010

Moq BadImageFormatException with NUnit

I ran into an issue today running a unit test where I kept getting a System.BadImageFormatException on the test dll. I incorrectly assumed this was NUnit - after digging around a bit I worked out it was actuall Moq that was the source of the problem.

The return value of the object being verified existed in an assembly that was not being referenced by my test project, and Moq was falling over. Adding the reference sorted out the problem.

The exact error I encountered was:

Test.MyLongNamespace.MyTestmethod: System.BadImageFormatException : [C:\Users\matt salmon\AppData\Local\Temp\nunit20\ShadowCopyCache\9748_634255057586445703\Tests_64256578\assembly\dl3\5181e02b\57ddb865_7585cb01\MyAssembly.DLL] The signature is incorrect.