Posts Tagged ‘csharp’

C# Tips – Type Conversion with “as” and “is”

Tuesday, July 21st, 2009

I had used C# for at least a year before I found out a couple of nice shorthand ways to convert types. These are the is and as expressions, and using them can help make your code more readable.

The is Expression

The is expression will return true if the provided expression is non-null and can be cast to the specific type.

private string GetDisplayField(object val)
{
	if (val is string)
	{
		string text = (string)val;
		return "Value was text: " + text;
	}
	else if (val is DateTime)
	{
		DateTime time = (DateTime)val;
		return "Value was date: " + time.ToShortDateString();
	}
 
	return "Could not match type";
}

The as Expression

The as expression will try to cast the object into the given type, and returns an object of that type if the cast was successful, or return null if unsuccessful.

This buys a little bit more functionality for you, as it assigns the variable with an already casted value if successful. It is functionally equivalent to: expression is type ? (type)expression : (type)null

private string GetDisplayField(object val)
{
	string text = val as string;
	DateTime? time = val as DateTime?;
 
	if (text != null)
	{
		return "Value was text: " + text;
	}
	if (time.HasValue)
	{
		return "Value was date: " + time.Value.ToShortDateString();
	}
 
	return "Could not match type";
}

Testing out the functions


Console.WriteLine(GetDisplayField(1));              // Output: "Could not match type"
Console.WriteLine(GetDisplayField("Hello"));        // Output: "Value was text: Hello"
Console.WriteLine(GetDisplayField(DateTime.Now));   // Output: "Value was date: 7/21/2009"

They are both readable ways to perform a type conversion – but pick one or the other! Using both of them is redundant.

Multipart Form Post in C#

Friday, May 8th, 2009

I recently had to access a web API through C Sharp that required a file upload. This is pretty easy if you have an HTML page with a form tag and you want a user to directly upload the file.

<form method="POST" action="http://localhost/" enctype="multipart/form-data">
	File : <input type="file" name="content" size="38" /><br />
	<input type="hidden" name="id" value='fileUpload' />
 </form>

However, this is not always a reasonable path to take. Sometimes you may be wanting to access a file that is already in a system and you don’t want a new upload. If you are accessing an external API, this is probably always the case. Unfortunately, building this post using C# is not quite as straightforward. I first tried using the WebClient UploadFile method, but it didn’t fit my needs because I wanted to upload form values (id, filename, other API specific parameters) in addition to just a file.

So, I needed to roll my own form post. Here is the Multipart Form RFC and the W3C Specification for multipart/form data. After reading these links and searching some forums, here is what I came up with.

Note: If anyone is interested in this code in Visual Basic, reader Mike Ferreira converted the code into VB.Net in a comment below.

public static class FormUpload
{
	private static readonly Encoding encoding = Encoding.UTF8;
	public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
	{
		string formDataBoundary = "-----------------------------28947758029299";
		string contentType = "multipart/form-data; boundary=" + formDataBoundary;
 
		byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);
 
		return PostForm(postUrl, userAgent, contentType, formData);
	}
	private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
	{
		HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;
 
		if (request == null)
		{
			throw new NullReferenceException("request is not a http request");
		}
 
		// Set up the request properties
		request.Method = "POST";
		request.ContentType = contentType;
		request.UserAgent = userAgent;
		request.CookieContainer = new CookieContainer();
		request.ContentLength = formData.Length;  // We need to count how many bytes we're sending. 
 
		using (Stream requestStream = request.GetRequestStream())
		{
			// Push it out there
			requestStream.Write(formData, 0, formData.Length);
			requestStream.Close();
		}
 
		return request.GetResponse() as HttpWebResponse;
	}
 
	private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
	{
		Stream formDataStream = new System.IO.MemoryStream();
 
		foreach (var param in postParameters)
		{
			if (param.Value is FileParameter)
			{
				FileParameter fileToUpload = (FileParameter)param.Value;
 
				// Add just the first part of this param, since we will write the file data directly to the Stream
				string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", 
					boundary, 
					param.Key, 
					fileToUpload.FileName ?? param.Key, 
					fileToUpload.ContentType ?? "application/octet-stream");
 
				formDataStream.Write(encoding.GetBytes(header), 0, header.Length);
 
				// Write the file data directly to the Stream, rather than serializing it to a string.
				formDataStream.Write(fileToUpload.File, 0, fileToUpload.File.Length);
			}
			else
			{
				string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", 
					boundary, 
					param.Key, 
					param.Value);
				formDataStream.Write(encoding.GetBytes(postData), 0, postData.Length);
			}
		}
 
		// Add the end of the request
		string footer = "\r\n--" + boundary + "--\r\n";
		formDataStream.Write(encoding.GetBytes(footer), 0, footer.Length);
 
		// Dump the Stream into a byte[]
		formDataStream.Position = 0;
		byte[] formData = new byte[formDataStream.Length];
		formDataStream.Read(formData, 0, formData.Length);
		formDataStream.Close();
 
		return formData;
	}
 
	public class FileParameter
	{
		public byte[] File { get; set; }
		public string FileName { get; set; }
		public string ContentType { get; set; }
		public FileParameter(byte[] file) : this(file, null) { }
		public FileParameter(byte[] file, string filename) : this(file, filename, null) { }
		public FileParameter(byte[] file, string filename, string contenttype) 
		{
			File = file;
			FileName = filename;
			ContentType = contenttype;
		}
	}
}

Here is the code to call the MultipartFormDataPost function with multiple parameters, including a file.

 
// Read file data
FileStream fs = new FileStream("c:\\people.doc", FileMode.Open, FileAccess.Read);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
fs.Close();
 
// Generate post objects
Dictionary<string, object> postParameters = new Dictionary<string, object>();
postParameters.Add("filename", "People.doc");
postParameters.Add("fileformat", "doc");
postParameters.Add("file", new FormUpload.FileParameter(data, "People.doc", "application/msword"));
 
// Create request and receive response
string postURL = "http://localhost";
string userAgent = "Someone";
HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters);
 
// Process response
StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
string fullResponse = responseReader.ReadToEnd();
webResponse.Close();
Response.Write(fullResponse);

Hopefully this code can help someone, figuring out exactly where to place the boundary and newlines in between form key-value pairs caused a little bit of grief during development. This is some functionality that would be really nice inside of the language library, but it seems like in most languages this is something you end up coding yourself.

C# Tips – Null Coalescing ??

Tuesday, May 5th, 2009

I have always enjoyed using the logical OR operator in JavaScript (||) as an oppurtunity to check for a null-like value, specifically to provide default parameters for functions or to check for existence of a property on a collection. I think they are a great way to make code more concise, and if used well, more readable.

These two functions do the same thing, but the first is shorter and more readable to people who may have to go back and modify it later.

function contentDocument(frame) {
    // If the frame.contentDocument either doesn't exist or is a null 
    // value, it will skip to the next value down the line 
    return frame.contentDocument || 
        frame.contentWindow.document || 
        frame.document;
}
 
function contentDocumentVerbose(frame) {
    // This works, but is possibly too verbose for such a simple task
    if (frame.contentDocument) {
        return frame.contentDocument;
    }
    else if (frame.contentWindow) {
        return frame.contentWindow.document;
    }
    else if (frame.document) {
        return frame.document;
    }
}

I was happy to see that C# has a similar feature, the Null Coalescing Operator.

This is nice for the same reasons, and is more readable than the normal ternary operator when simply checking null. Of course, if I am not checking for a null value, but a more complex boolean expression, I will usually use the ternary operator or an if-else block it is more than just a variable assignment or return statement. Anytime I use any extra syntactical feature, it is my hope to make the code more readable.

Anyway, here is an example of the ‘??’ (coalescing) operator contrasted with the ‘?:’ (ternary) operator.

string APP_DEFAULT = "application/octet-stream";
 
private string GetContentType(string contentType)
{
    // Nice and readable.  The '??' operator can be very useful.
    string FUNCTION_DEFAULT = null;
 
    return contentType ?? FUNCTION_DEFAULT ?? APP_DEFAULT;
}
 
private string GetContentTypeTernary(string contentType) 
{
    // This is NOT readable.  Please do not use nested ternary
    // operators... They take too much energy to figure out.
    string FUNCTION_DEFAULT = "text/plain";
 
    return (contentType != null) ? contentType :
        ((FUNCTION_DEFAULT != null) ? FUNCTION_DEFAULT : APP_DEFAULT);
}