Saturday, 3 December 2011

NAnt FTP Task

An NAnt task to allow file uploads using FTP allowing FTP+SSL to used.

<target name="ftp">
<ftp
server="ftp.yeticide.co.uk"
username="username"
password="password"
basedir="path-to-folder"
usessl="true">
<fileset>
<include name="NAnt.Task.Ftp/bin/**/*.dll"/>
</fileset>
</ftp>
</target>


using System.IO;
using System.Net;
using System.Text;
using NAnt.Core;
using NAnt.Core.Attributes;
using NAnt.Core.Types;

namespace NAnt.Task.Ftp
{
[TaskName("ftp")]
public class FtpTask : NAnt.Core.Task
{
[TaskAttribute("server")]
public string Server { get; set; }

[TaskAttribute("username")]
public string Username { get; set; }

[TaskAttribute("password")]
public string Password { get; set; }

[TaskAttribute("port")]
public int Port { get; set; }

[TaskAttribute("basedir")]
public string BaseDirectory { get; set; }

[TaskAttribute("usessl")]
public bool UseSSL { get; set; }

[BuildElement("fileset", Required = true)]
public virtual FileSet FileSet { get; set; }

public FtpTask()
{
Port = 21;
}

protected override void ExecuteTask()
{
if (FileSet != null)
{
foreach (var file in FileSet.FileNames)
{
if (File.Exists(file))
{
Log(Level.Info, file);
var ftpRequest = CreateUploadRequest(new FileInfo(file).Name);
// Copy the contents of the file to the request stream.
var sourceStream = new StreamReader(file);
byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
ftpRequest.ContentLength = fileContents.Length;

var requestStream = ftpRequest.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();

var response = (FtpWebResponse) ftpRequest.GetResponse();
Log(Level.Info, "Upload Complete: {0}", response.StatusDescription);
}
else
{
Log(Level.Error, "File doesn't exists: {0}", file);
}
}
}
}

protected FtpWebRequest CreateUploadRequest(string fileName)
{
var ftpServer = string.Format("ftp://{0}:{1}/{2}/{3}", Server, Port, BaseDirectory, fileName);

Log(Level.Info, "Preparing Upload: {0} => {1}", fileName, ftpServer);
var ftpRequest = (FtpWebRequest)WebRequest.Create(ftpServer);

if (!string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password))
{
ftpRequest.Credentials = new NetworkCredential(Username, Password);
}

if (UseSSL)
{
Log(Level.Info, "Using ssl");
ftpRequest.EnableSsl = true;
}

ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;

return ftpRequest;
}
}
}

Monday, 30 May 2011

Gnome 3 - Stupid Power Options Fix

Upgraded to Fedora 15 and Gnome 3 everything is working well and the new interface is looking slick. The gnome guys have done a very good job and am very impressed. However I have come across on thing that, for a while, really pissed me off. They removed the ability to easily change the power options when you close the lid on your laptop. The default option is to suspend the computer. This isn't a problem for a lot of people, even if there is a bug on the dell M1330 laptop which causes a crash when starting from a suspended state. I digress, a lot of work has done into this and has already been discussed in detail.

http://blogs.gnome.org/hughsie/2011/02/02/is-gnome-3-going-to-melt-your-laptop/
http://afaikblog.wordpress.com/2011/02/03/on-laptop-lids-and-power-settings/
http://live.gnome.org/Design/SystemSettings/Power

However all the discussion did not cover my use case, which occurs on a daily basis:

  1. Play audio book.

  2. Run command to shutdown laptop after half an hour.

  3. close laptop lid turn off lights and go to sleep.


You can resolve this using the solution, provided by timlau, to use gsetting to manually set the power setting (He post links to a script to automatically set this using a zenity dialog).


gsettings set org.gnome.settings-daemon.plugins.power lid-close-ac-action “blank”
gsettings set org.gnome.settings-daemon.plugins.power lid-close-battery-action “blank”


End Rant.

Tuesday, 17 May 2011

Adventures Into Web Farm Framework 2.0

I have been using the Web Farm Framework 2.0 to handle the load balancing and provision of the applications. Our web farm consists of four servers, 1 load balancer, 2 web servers and 1 database server. The installation was simple enough using the Web Platform Installer.




The web platform installer was used to install the Web Farm Framework 2.0 onto the load balancer. The guide "Setting up a Server Farm with the Web Farm Framework 2.0 for IIS 7" provides an easy walk through for getting your web farm setup. However once it has been setup there are a number of steps that still had to be configured to ensure the web farm worked correctly.



Before completing the following steps I ran into a an issue where the server would appear available for load balancing in the "Servers" view, but would be unavailable in the "Monitoring and Management" view. To resolve try the following steps.


1. Health Test Url


Make sure that the health test url has been set. The application request routing uses this to test whether a server should be used for load balancing.




2. Default App Pool Settings



Edit the advanced settings of the DefaultAppPool on the controlling server and set the recyling value for "Regular Time Interval (minutes)" to zero.




3. Set Primary and Secondary Servers to Response to Ping


Update the firewall settings on the Primary and Secondary servers to respond to ping.




These are thing steps that I followed to get it to work correctly, they might vary for you depending on your setup.

Thursday, 10 March 2011

IIS7 & IIS Express 401 Access is denied due to invalid credentials Issue

I have been working on a large web application using MVC3, NHibernate using IIS Express to debug and IIS7 to stage. I'm using the membership services provided by ASP.NET to handle user authentication and provide security to the system. However I kept running across an issue, when accessing remotely, that was preventing me from logging in. Whenever I tried to view a page as a non logged in user I was returned a 404 Unauthorized error.



After searching around for a solution to why this was not displaying the correct page, even if it was redirecting to the login page I decided to try to set the error displaying to return more information. After adding <httpErrors errorMode="Details" /> to try and get a detail output from IIS the page started to work as expected.




With this option enabled the login page was now correctly displayed. This can be set without having to edit the web.config on IIS7 by editing the "Error Pages" features settings for your site in IIS. Set the Error Response to "Detailed errors"