Need to write a byte array to a file? .NET’s got your back with File.WriteAllBytes.
Usage:
var bytes = GetSomeBytes(); File.WriteAllBytes(@"c:\temp\somefile.tmp", bytes);
Need to write a byte array to a file? .NET’s got your back with File.WriteAllBytes.
Usage:
var bytes = GetSomeBytes(); File.WriteAllBytes(@"c:\temp\somefile.tmp", bytes);
I was just working on a small project that was importing data into one system from another. The data in the source system was formatted using all-caps, but the data entry practice for the destination system was to enter values using mixed or title case.
No problem, right? Reformatting the string values seems like a reasonably simple task. Make the whole thing lowercase, then capitalize the first letter. Improve the solution by using regular expressions to capitalize letters that follow spaces and hyphens.
But hold on a sec! It turns out it’s even easier than that. The .NET Framework has a culture-based TextInfo class that has a ToTitleCase method. Nice–way to have exactly what I need, Microsoft!
var textInfo = CultureInfo.CurrentCulture.TextInfo; return textInfo.ToTitleCase(value);
ToTitleCase will format each word in a string to title case, with the first letter uppercase and subsequent letters lowercase. It respects whitespace as a word boundary as well as certain punctuation, such as commas, periods, question marks, and exclamation points. It’s not title case in the strictest sense since all words–including prepositions, articles, and conjunctions–will be capitalized, but it’s definitely good enough to satisfy my needs. The algorithm assumes words in all-caps are abbreviations or acronyms and ignores them, but you can get around that by using string‘s ToLower method.
Here are a few example uses:
Console.WriteLine(textInfo.ToTitleCase("hello, world!"));
Console.WriteLine(textInfo.ToTitleCase("this and that"));
Console.WriteLine(textInfo.ToTitleCase("words.with.periods"));
Console.WriteLine(textInfo.ToTitleCase("WORDS WITH ALL CAPS"));
Console.WriteLine(textInfo.ToTitleCase("WORDS WITH ALL CAPS (TOLOWER EDITION)".ToLower()));
// Output:
// Hello, World!
// This And That
// Words.With.Periods
// WORDS WITH ALL CAPS
// Words With All Caps (Tolower Edition)
Say you’re consuming a WCF service. You’ve added a service reference, and you’ve got a client proxy. It implements IDisposable. So, when it’s time to use it, you should just chuck it in a using statement and not worry about additional resource cleanup, right?
Not so fast. There can be problems with the using statement. The problem is prevalent enough to warrant an article on MSDN demonstrating the improper use of using to automatically clean up resources when using a typed client.
So what should you be using instead of using? One option, which is outlined in the aforementioned MSDN article, is to use a try/catch block. If an exception occurs while closing the client, the client’s Abort method should be called. MSDN’s guidance suggests reporting errors and calling Abort for expected exceptions and calling Abort then re-throwing unexpected exceptions. The article explains, “Typically there is no useful way to handle unexpected errors, so typically you should not catch them when calling a WCF client communication method.”
// MSDN recommendation for WCF client cleanup
try
{
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
There’s a lot of quick & dirty advice online that suggests using a try/finally block to first Close the client if it’s not in a faulted state, then Abort it if it’s not in a closed state. This is probably fine for small, simple applications, but hiding all exceptions can lead to maintenance woes later by reducing the visibility of underlying problems.
// effective but hides errors
try
{
if (client.State != CommunicationState.Faulted)
{
client.Close();
}
}
finally
{
if (client.State != CommunicationState.Closed)
{
client.Abort();
}
}
I like the suggestion laid out in this blog article. The author suggests re-implementing IDisposable in a partial class. The problem I have with this approach is that it may be confusing to other developers. When the client is used in the application, it will be wrapped in a using. There’s no good way for a developer to know whether that class has been properly re-implemented without doing further investigation. I think it’s easier for developers to have a hard rule: don’t use using with WCF clients.
So, instead of using a partial class, I’d suggest creating a wrapper that implements IDisposable. Developers using the client don’t need to worry about closing connections or error-handling; they can just throw a using around it an move on.
Here’s what that might look like. You could implement the service contract interface to ensure all methods are exposed, or have a generic method that accepts a lambda expression.
// An IDisposable client wrapper
public class Client : IDisposable
{
private WcfClient _client;
public Client()
{
_client = new WcfClient();
}
public void SomeMethod()
{
_client.SomeMethod();
}
void IDisposable.Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_client == null)
{
return;
}
try
{
if (_client.State != CommunicationState.Faulted)
{
_client.Close();
}
}
catch (CommunicationException e)
{
//...
_client.Abort();
}
catch (TimeoutException e)
{
//...
_client.Abort();
}
catch (Exception e)
{
//...
_client.Abort();
throw;
}
finally
{
if (_client.State != CommunicationState.Closed)
{
_client.Abort();
}
_client = null;
}
}
}
~Client()
{
Dispose(false);
}
}
Latitude and longitude are usually represented in one of two formats: signed decimal and degrees/minutes/seconds (DMS). Signed decimal values range from -90 to 90 for latitude and -180 to 180 for longitude. DMS values, on the other hand, are broken into four parts: degrees, minutes, and seconds–obviously–plus a compass direction.
Converting between the two formats is not terribly difficult if you keep the following formula in mind:
Decimal Degrees = Degrees + minutes/60 + seconds/3600
Computers are good at math and converting things, so let’s write a converter to do the work for us! First, we need to define some types to work with. We have two different formats, so it makes sense for us to have a DecimalLocation and a DmsLocation. We can also get some re-use out of a DmsPoint type, and we’ll need an enumeration for PointType to help with displaying N/S & E/W directional indicators. I threw in some overloads for ToString to help with displaying results, too. Also note that N/S/E/W are determined based on the sign of Degrees for DMS points.
class DecimalLocation
{
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
public override string ToString()
{
return string.Format("{0:f5}, {1:f5}",
Latitude, Longitude);
}
}
class DmsLocation
{
public DmsPoint Latitude { get; set; }
public DmsPoint Longitude { get; set; }
public override string ToString()
{
return string.Format("{0}, {1}",
Latitude, Longitude);
}
}
class DmsPoint
{
public int Degrees { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }
public PointType Type { get; set; }
public override string ToString()
{
return string.Format("{0} {1} {2} {3}",
Math.Abs(Degrees),
Minutes,
Seconds,
Type == PointType.Lat
? Degrees < 0 ? "S" : "N"
: Degrees < 0 ? "W" : "E");
}
}
enum PointType
{
Lat,
Lon
}
Now that we’ve got our data types out of the way, we can work on the conversion. Our conversion formula shows how to calculate decimal degrees from DMS, so let’s do that first. It’s really straightforward–we just plug the formula into a function and call it for both latitude and longitude.
DecimalLocation Convert(DmsLocation dmsLocation)
{
if (dmsLocation == null)
{
return null;
}
return new DecimalLocation
{
Latitude = CalculateDecimal(dmsLocation.Latitude),
Longitude = CalculateDecimal(dmsLocation.Longitude)
};
}
decimal CalculateDecimal(DmsPoint point)
{
if (point == null)
{
return default(decimal);
}
return point.Degrees + (decimal)point.Minutes/60 + (decimal)point.Seconds/3600;
}
Going the other direction is a little more complicated. Ultimately, we’re just working backwards. Peel off the degrees, then calculate minutes, and seconds are left.
DmsLocation Convert(DecimalLocation decimalLocation)
{
if (decimalLocation == null)
{
return null;
}
return new DmsLocation
{
Latitude = new DmsPoint
{
Degrees = ExtractDegrees(decimalLocation.Latitude),
Minutes = ExtractMinutes(decimalLocation.Latitude),
Seconds = ExtractSeconds(decimalLocation.Latitude),
Type = PointType.Lat
},
Longitude = new DmsPoint
{
Degrees = ExtractDegrees(decimalLocation.Longitude),
Minutes = ExtractMinutes(decimalLocation.Longitude),
Seconds = ExtractSeconds(decimalLocation.Longitude),
Type = PointType.Lon
}
};
}
int ExtractDegrees(decimal value)
{
return (int)value;
}
int ExtractMinutes(decimal value)
{
value = Math.Abs(value);
return (int)((value - ExtractDegrees(value)) * 60);
}
int ExtractSeconds(decimal value)
{
value = Math.Abs(value);
decimal minutes = (value - ExtractDegrees(value)) * 60;
return (int)Math.Round((minutes - ExtractMinutes(value)) * 60);
}
That’s it–we’ve got some lightweight methods to go between the two formats. Let’s whip up a quick test to verify the conversions:
void Main()
{
DecimalLocation decimalLocation;
DmsLocation dmsLocation;
decimalLocation = new DecimalLocation
{
Latitude = 38.898611m,
Longitude = -77.037778m
};
dmsLocation = Convert(decimalLocation);
Console.WriteLine("{0} -> {1}", decimalLocation, dmsLocation);
dmsLocation = new DmsLocation
{
Latitude = new DmsPoint
{
Degrees = 38,
Minutes = 53,
Seconds = 55,
Type = PointType.Lat
},
Longitude = new DmsPoint
{
Degrees = -77,
Minutes = 2,
Seconds = 16,
Type = PointType.Lon
}
};
decimalLocation = Convert(dmsLocation);
Console.WriteLine("{0} -> {1}", dmsLocation, decimalLocation);
}
// output:
// 38.89861, -77.03778 -> 38 53 55 N, 77 2 16 W
// 38 53 55 N, 77 2 16 W -> 38.89861, -76.96222
The converted values are off slightly, presumably due to some loss of precision, but the values produced are in the same general vicinity. (See here, here, and here.)
Full example:
void Main()
{
DecimalLocation decimalLocation;
DmsLocation dmsLocation;
decimalLocation = new DecimalLocation
{
Latitude = 38.898611m,
Longitude = -77.037778m
};
dmsLocation = Convert(decimalLocation);
Console.WriteLine("{0} -> {1}", decimalLocation, dmsLocation);
dmsLocation = new DmsLocation
{
Latitude = new DmsPoint
{
Degrees = 38,
Minutes = 53,
Seconds = 55,
Type = PointType.Lat
},
Longitude = new DmsPoint
{
Degrees = -77,
Minutes = 2,
Seconds = 16,
Type = PointType.Lon
}
};
decimalLocation = Convert(dmsLocation);
Console.WriteLine("{0} -> {1}", dmsLocation, decimalLocation);
}
class DecimalLocation
{
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
public override string ToString()
{
return string.Format("{0:f5}, {1:f5}",
Latitude, Longitude);
}
}
class DmsLocation
{
public DmsPoint Latitude { get; set; }
public DmsPoint Longitude { get; set; }
public override string ToString()
{
return string.Format("{0}, {1}",
Latitude, Longitude);
}
}
class DmsPoint
{
public int Degrees { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }
public PointType Type { get; set; }
public override string ToString()
{
return string.Format("{0} {1} {2} {3}",
Math.Abs(Degrees),
Minutes,
Seconds,
Type == PointType.Lat
? Degrees < 0 ? "S" : "N"
: Degrees < 0 ? "W" : "E");
}
}
enum PointType
{
Lat,
Lon
}
DecimalLocation Convert(DmsLocation dmsLocation)
{
if (dmsLocation == null)
{
return null;
}
return new DecimalLocation
{
Latitude = CalculateDecimal(dmsLocation.Latitude),
Longitude = CalculateDecimal(dmsLocation.Longitude)
};
}
DmsLocation Convert(DecimalLocation decimalLocation)
{
if (decimalLocation == null)
{
return null;
}
return new DmsLocation
{
Latitude = new DmsPoint
{
Degrees = ExtractDegrees(decimalLocation.Latitude),
Minutes = ExtractMinutes(decimalLocation.Latitude),
Seconds = ExtractSeconds(decimalLocation.Latitude),
Type = PointType.Lat
},
Longitude = new DmsPoint
{
Degrees = ExtractDegrees(decimalLocation.Longitude),
Minutes = ExtractMinutes(decimalLocation.Longitude),
Seconds = ExtractSeconds(decimalLocation.Longitude),
Type = PointType.Lon
}
};
}
decimal CalculateDecimal(DmsPoint point)
{
if (point == null)
{
return default(decimal);
}
return point.Degrees + (decimal)point.Minutes/60 + (decimal)point.Seconds/3600;
}
int ExtractDegrees(decimal value)
{
return (int)value;
}
int ExtractMinutes(decimal value)
{
value = Math.Abs(value);
return (int)((value - ExtractDegrees(value)) * 60);
}
int ExtractSeconds(decimal value)
{
value = Math.Abs(value);
decimal minutes = (value - ExtractDegrees(value)) * 60;
return (int)Math.Round((minutes - ExtractMinutes(value)) * 60);
}
Last time in my Knockout series of posts, I explored how to retrieve and bind data from an ASP.NET page method. That’s only half the battle, though. How can you take data captured and do interesting things with it? I’ve got an idea! How about passing it to an ASP.NET page method!
I’m going to use my example from last time with a few modifications. I added some entry controls to capture the user’s status, and I modified the GetStatus page method to return the user’s last status. The last status values will be displayed as read-only and will only be visible when a value exists. Here’s the ASPX and code-behind. Note that ASPX contains a button bound to a method in the view model that’s not yet implemented, and the code-behind has a UpdateStatus method.
default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/jquery-2.0.2.min.js"></script>
<script src="Scripts/knockout-2.2.1.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
wasHappy: ko.observable(),
lastStatusText: ko.observable(),
isCurrentlyHappy: ko.observable(),
currentStatusText: ko.observable(),
updateStatus: updateStatus,
};
ko.applyBindings(viewModel);
getLastStatus();
function updateStatus() {
// todo: post data to page method
}
function getLastStatus() {
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
var data = result.d;
if (data == null) {
$("#lastTime").hide();
return;
}
$("#lastTime").show();
viewModel.wasHappy(data.HappyFlag);
viewModel.lastStatusText(data.Text);
}
});
}
});
</script>
</head>
<body>
<div>
<strong>How are you feeling?</strong><br/>
Are you happy? <input data-bind="checked: isCurrentlyHappy" type="checkbox"/><br/>
Tell me about it: <input data-bind="value: currentStatusText"/><br/>
<button data-bind="click: updateStatus">Update Status</button>
</div>
<div id="lastTime">
<strong>How you felt last time:</strong><br/>
Were you happy? <input data-bind="checked: wasHappy" type="checkbox" disabled="true"/><br/>
What you told me about it: <span data-bind="text: lastStatusText"></span>
</div>
</body>
</html>
default.aspx.cs:
using System;
using System.Web.Services;
namespace adamprescott.net.Knockout
{
public class Status
{
public bool HappyFlag { get; set; }
public string Text { get; set; }
}
public partial class Default : System.Web.UI.Page
{
private static Status lastStatus = null;
[WebMethod]
public static Status GetStatus()
{
return lastStatus;
}
[WebMethod]
public static void UpdateStatus(Status status)
{
lastStatus = status;
}
}
}
When the button is pressed, we need to collect values and put them into an object to be passed to our page method. That’s easy–just grab values from the view model:
var data = {};
data.HappyFlag = viewModel.isCurrentlyHappy();
data.Text = viewModel.currentStatusText();
Now that we’ve got our values, we just need to pass them to our page method. Once again, it’s jQuery to the rescue!
$.ajax({
type: "POST",
url: "Default.aspx/UpdateStatus",
data: JSON.stringify({ 'status': data }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
// todo: anything?
}
});
Bam! We just passed data to the page method in the code-behind. Tutorial accomplished. However, I need to go a little further. Now that I just updated the status, I want my UI to update its view to show the latest status. So, when my call to UpdateStatus finishes successfully, I just need to make another call to GetStatus. Super easy!
Here’s the final ASPX.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/jquery-2.0.2.min.js"></script>
<script src="Scripts/knockout-2.2.1.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
wasHappy: ko.observable(),
lastStatusText: ko.observable(),
isCurrentlyHappy: ko.observable(),
currentStatusText: ko.observable(),
updateStatus: updateStatus,
};
ko.applyBindings(viewModel);
getLastStatus();
function updateStatus() {
// todo: post data to page method
return;
var data = {};
data.HappyFlag = viewModel.isCurrentlyHappy();
data.Text = viewModel.currentStatusText();
$.ajax({
type: "POST",
url: "Default.aspx/UpdateStatus",
data: JSON.stringify({ 'status': data }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
getLastStatus();
}
});
}
function getLastStatus() {
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
var data = result.d;
if (data == null) {
$("#lastTime").hide();
return;
}
$("#lastTime").show();
viewModel.wasHappy(data.HappyFlag);
viewModel.lastStatusText(data.Text);
}
});
}
});
</script>
</head>
<body>
<div>
<strong>How are you feeling?</strong><br/>
Are you happy? <input data-bind="checked: isCurrentlyHappy" type="checkbox"/><br/>
Tell me about it: <input data-bind="value: currentStatusText"/><br/>
<button data-bind="click: updateStatus">Update Status</button>
</div>
<div id="lastTime">
<strong>How you felt last time:</strong><br/>
Were you happy? <input data-bind="checked: wasHappy" type="checkbox" disabled="true"/><br/>
What you told me about it: <span data-bind="text: lastStatusText"></span>
</div>
</body>
</html>
Last week, I wrote a brief post about how easy it is to do databinding with Knockout. The article presents a barebones example, but it fails to address an important issue: how to get data into the view model.
I live in a .NET world, and I’m usually working with small ASP.NET application. I’ve found that page methods are an easy and convenient way to get to the data I need. They’re easily accessible via jQuery, too. So let’s see how we can get data from an ASP.NET page method using jQuery and pass it along to our Knockout view model.
First, let’s get to know our page method. I created a simple Status class that will be returned from a page method, GetStatus. Here’s the entire code-behind for my page:
using System;
using System.Web.Services;
namespace adamprescott.net.Knockout
{
public class Status
{
public bool HappyFlag { get; set; }
public string Text { get; set; }
}
public partial class Default : System.Web.UI.Page
{
[WebMethod]
public static Status GetStatus()
{
return new Status { HappyFlag = true, Text = "This just a default" };
}
}
}
We know what data we’re getting, so we can go ahead and create our view model and UI. Here’s what that looks like:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/jquery-2.0.2.min.js"></script>
<script src="Scripts/knockout-2.2.1.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
isHappy: ko.observable(),
statusText: ko.observable(),
};
ko.applyBindings(viewModel);
// todo: get data from page method
});
</script>
</head>
<body>
<input data-bind="value: statusText" /><br/>
Happy? <input data-bind="checked: isHappy" type="checkbox" />
</body>
</html>
All that’s left is for us to do is call the page method and update the values in our view model. And, as I said before, jQuery makes it a snap!
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
var data = result.d;
viewModel.isHappy(data.HappyFlag);
viewModel.statusText(data.Text);
}
});
With that, we’re done. When the page loads, the view model is created and bound to the UI controls. We then make an asynchronous call to the page method using jQuery and update the values in our view model.
Here’s the complete ASPX file:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="adamprescott.net.Knockout.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="Scripts/jquery-2.0.2.min.js"></script>
<script src="Scripts/knockout-2.2.1.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
isHappy: ko.observable(),
statusText: ko.observable(),
};
ko.applyBindings(viewModel);
$.ajax({
type: "POST",
url: "Default.aspx/GetStatus",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
var data = result.d;
viewModel.isHappy(data.HappyFlag);
viewModel.statusText(data.Text);
}
});
});
</script>
</head>
<body>
<input data-bind="value: statusText" /><br/>
Happy? <input data-bind="checked: isHappy" type="checkbox" />
</body>
</html>
LINQ to XML is the greatest thing for working with XML. If you’re doing just about anything XML in .NET, you should probably be using it. One of the points I missed in the passed was the difference between LINQ to XML’s Elements and Descendants methods. Both methods are used to retrieve sub-elements, but the distinction is that Elements will only search direct child nodes whereas Descendants will search recursively.
Consider the following XML:
<root>
<house>
<address>123 Number Lane</address>
</house>
<business>
<address>100 Fun Drive</address>
</business>
</root>
If I want to retrieve a list of all addresses, I can use Descendants.
var addresses = xml.Descendants("address");
// Result:
// <address>123 Number Lane</address>
// <address>100 Fun Drive</address>
I can’t do this with Elements.
var addresses = xml.Elements("address");
// Result:
// (Nothing!)
If I want to accomplish this with Elements, I need to first get all children from the root and then retrieve their addresses.
// You should probably just use Descendants()...
addresses = xml.Root
.Elements()
.SelectMany(x => x.Elements("address"));
// Result:
// <address>123 Number Lane</address>
// <address>100 Fun Drive</address>
Elements is good for getting values from a specific path, though. For example, if you want to retrieve only the house addresses, you could do the following:
addresses = xml.Root
.Elements("house")
.SelectMany(x => x.Elements("address"));
// Result:
// <address>123 Number Lane</address>
Note, however, that the same* task can be accomplished using Descendants, too!
addresses = xml.Root
.Descendants("house")
.SelectMany(x => x.Descendants("address"));
// Result:
// <address>123 Number Lane</address>
*Of course, this “same” functionality is entirely dependent on the structure of the XML and what you’re trying to accomplish. If there were child elements beneath “house” that had child addresses, Descendants would snag those, which may or may not be desirable depending on your needs.
So, in summary, use Elements when you want to search and retrieve only from immediate child elements (perhaps it should have been named “Children!”), and use Descendants when you want to search and retrieve from all descendant elements. I generally stick to Descendants because I can “jump” directly to the node(s) that I’m looking for without having to step though the path. If I only care about a specific path, I can specify it with Descendants the same as I would with Elements. I only use Elements if I needed to find elements at a specific level or want to ignore matching sub-elements.
I first heard about ASP.NET Web API several months ago in MSDN magazine. My primary role is architecting cross-product solutions between my company’s customers and other software vendors, so I was instantly interested. The “wow” part for me was that the consumer can specify whether they’d like to communicate using JSON or XML, and Web API does the rest. The MVC-like structure promises improved unit-testability, and I’m excited to simplify access to our data for third parties on all platforms by leveraging HTTP.
And so, I created my first “Hello, world”-style application. In terms of creating the Web API service, I just followed MSDN’s Your First ASP.NET Web API tutorial. It’s very easy to follow, and I recommend starting there.
To get you somewhat up to speed, here’s a so-summarized-that-it’s-probably-not-even-useful summary of the tutorial. A functional web API is created by defining a control that derives from ApiController.
namespace HelloWebAPI.Controllers
{
using HelloWebAPI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
public class ProductsController : ApiController
{
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
public Product GetProductById(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return product;
}
public IEnumerable<Product> GetProductsByCategory(string category)
{
return products.Where(
(p) => string.Equals(p.Category, category,
StringComparison.OrdinalIgnoreCase));
}
}
}
Routing will map the controller methods to URIs as follows:
| Controller Method | URI |
|---|---|
| GetAllProducts | /api/products |
| GetProductById | /api/products/id |
| GetProductsByCategory | /api/products/?category=category |
Finally, the API can be accessed using JavaScript/jQuery like so:
<script type="text/javascript">
$(document).ready(function () {
// Send an AJAX request
$.getJSON("api/products/",
function (data) {
// On success, 'data' contains a list of products.
$.each(data, function (key, val) {
// Format the text to display.
var str = val.Name + ': $' + val.Price;
// Add a list item for the product.
$('<li/>', { text: str })
.appendTo($('#products'));
});
});
});
function find() {
var id = $('#prodId').val();
$.getJSON("api/products/" + id,
function (data) {
var str = data.Name + ': $' + data.Price;
$('#product').text(str);
})
.fail(
function (jqXHR, textStatus, err) {
$('#product').text('Error: ' + err);
});
}
</script>
The tutorial is great, but the controller methods only accept integers and strings. I need to accept and process complex types in order to do most tasks, like record searching and updating. It took me a little bit of Googling and trial & error to figure out, but I was able to modify the tutorial example to accept a complex object with minimal changes.
The first thing I needed was a complex type. I created an empty class named GetDto. I then added the new parameter to the GetProductById method in the controller. The final step was adding the HttpPost attribute to the method. (A POST request must be used since complex objects must be read from the request body, and GET requests do not have a body.) That’s it for the controller changes. In order to test, I added a name field to my DTO and appended it to the response.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http;
using HelloWebApi.Models;
namespace HelloWebApi.Controllers
{
public class GetDto
{
public string name { get; set; }
}
public class ProductsController : ApiController
{
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
public IEnumerable<Product> GetAllProducts()
{
return products;
}
[HttpPost]
public Product GetProductById(int id, GetDto dto)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
product.Name += dto.name;
return product;
}
public IEnumerable<Product> GetProductsByCategory(string category)
{
return products.Where(
(p) => string.Equals(p.Category, category,
StringComparison.OrdinalIgnoreCase));
}
}
}
The modifications to the calling jQuery code were less intuitive because the tutorial used the getJSON method. I had to rewrite that code to use the ajax method, so the request would be sent as a POST with my complex object sent as the request body. Here’s what I came up with:
<script type="text/javascript">
$(document).ready(function () {
// Send an AJAX request
$.getJSON("api/products/",
function (data) {
// On success, 'data' contains a list of products.
$.each(data, function (key, val) {
// Format the text to display.
var str = val.Name + ': $' + val.Price;
// Add a list item for the product.
$('<li/>', { text: str })
.appendTo($('#products'));
});
});
});
function find() {
var id = $('#prodId').val();
$.ajax({
url: "api/products/" + id,
type: "POST",
data: JSON.stringify({ name: id }),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
var str = data.Name + ': $' + data.Price;
$('#product').text(str);
}
});
}
</script>
jQuery is nice and all, but most of the work I do is C#. So my final goal for this first look was to invoke the API from C#. I created a simple WPF test app and used another MSDN tutorial, Calling a Web API From a WPF Application. This tutorial was also quite good, so I won’t get into too much detail. Here’s the end result that allows me to access my service from within my WPF application. Easy-peasy.
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Windows;
using HelloWebApi.Models;
namespace HelloWebApiTestClient
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void OnTestClick(object sender, RoutedEventArgs e)
{
HttpClient client = new HttpClient();
ProductsCollection _products = new ProductsCollection();
client.BaseAddress = new Uri("http://localhost:14095");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
btnGetProducts.IsEnabled = false;
var response = await client.GetAsync("api/products");
response.EnsureSuccessStatusCode(); // Throw on error code.
var products = await response.Content.ReadAsAsync<IEnumerable<Product>>();
_products.CopyFrom(products);
}
catch (Newtonsoft.Json.JsonException jEx)
{
// This exception indicates a problem deserializing the request body.
MessageBox.Show(jEx.Message);
}
catch (HttpRequestException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
btnGetProducts.IsEnabled = true;
}
}
}
}
I’m pretty happy with what I’ve seen so far. I watched a webcast on how easy it is to secure Web API using a variety of methods. So that’s what’s next for me. Yay for new stuff!
The other day, I was consulted by a colleague on a regular expression. For those of you that know me, this is one of my favorite consultations, so I was thrilled to help him. He was doing a simple parse-and-reformat. It warmed my insides to know that he identified this as a perfect regular expression scenario and implemented it that way. It was a functional solution, but I felt that it could be simplified and more maintainable.
I’ll venture to say that the most straightforward way to do a regular expression parse-and-reformat for a developer that’s not familiar with regular expressions (You call yourself a developer..!?) is by creating a Match object and reformatting it.
var date = "4/18/2013";
var regex = new Regex(@"^(\d+)/(\d+)/(\d+)$");
var match = regex.Match(date);
var result = string.Format("{0}-{1}-{2}",
match.Groups[3],
match.Groups[2],
match.Groups[1]);
Console.WriteLine(result);
You can accomplish the same task without creating a Match object by using the Replace method. There is a version that accepts a MatchEvaluator–which can be a lambda expression–so you can basically take the previous solution and plug it in.
var date = "4/18/2013";
var regex = new Regex(@"^(\d+)/(\d+)/(\d+)$");
var result = regex.Replace(date,
m => string.Format("{0}-{1}-{2}",
m.Groups[3],
m.Groups[2],
m.Groups[1]));
Console.WriteLine(result);
That’s a little bit better, but it’s still a little verbose. There’s another overload of the Replace method that accepts a replacement string. This allows you to skip the Match object altogether, and it results in a nice, tidy solution.
var date = "4/18/2013";
var regex = new Regex(@"^(\d+)/(\d+)/(\d+)$");
var result = regex.Replace(date, "${3}-${1}-${2}");
Console.WriteLine(result);
I have two problems with all three of these solutions, though. First, they use hard-coded indexes to access the capture groups. If another developer comes along and modifies the regular expression by adding another capture group, it could unintentionally affect the reformatting logic. The second issue I have is that it’s hard to understand the intent of the code. I have to read and process the regular expression and its capture groups in order to determine what the code is trying to do. These two issues add up to poor maintainability.
Don’t worry, though. Regular expressions have a built-in mechanism for naming capture groups. By modifying the regular expression, you can now reference the capture groups by name instead of index. It makes the regular expression itself a little noisier, but the rest of the code becomes much more readable and maintainable. Way better!
var date = "4/18/2013";
var regex = new Regex(
@"^(?<day>\d+)/(?<month>\d+)/(?<year>\d+)$");
var match = regex.Match(date);
var result = string.Format("{0}-{1}-{2}",
match.Groups["year"],
match.Groups["month"],
match.Groups["day"]);
Console.WriteLine(result);
var date = "4/18/2013";
var regex = new Regex(
@"^(?<day>\d+)/(?<month>\d+)/(?<year>\d+)$");
var result = regex.Replace(date,
m => string.Format("{0}-{1}-{2}",
m.Groups["year"],
m.Groups["month"],
m.Groups["day"]));
Console.WriteLine(result);
var date = "4/18/2013";
var regex = new Regex(
@"^(?<day>\d+)/(?<month>\d+)/(?<year>\d+)$");
var result = regex.Replace(date, "${year}-${month}-${day}");
Console.WriteLine(result);
There have been many times when I’ve thrown together a small utility app intended for situational use in specific scenarios. These scenarios are usually of a one-and-done nature, where they need to be done once and that’s it. It doesn’t make sense to have an installer that deploys the app to a permanent location in Program Files. What I really want is to have an EXE that I can copy to the desktop on a remote machine, use it, and junk it. There’s a wrinkle, though: the apps usually have some external dependencies, so it’s typically an EXE plus a handful of DLLs.
It’s not a huge problem, I just keep the EXE and its dependencies in a ZIP archive or folder. When I need the app, I copy the archive/folder. This works fine, but it’s not as simple as I’d like. It’s also error-prone, since another user may not realize that the accompanying assemblies are required dependencies. It’d be nice to roll the EXE and its dependencies into a single assembly, and that’s exactly what ILMerge does!
ILMerge is a Microsoft Research project that allows you to merge multiple .NET assemblies into a single assembly. It’s a command-line tool, but you can also use it programmatically.
Here’s the basic command-line usage:
ILMerge.exe /out:Target.dll PrimaryAssembly.dll ExternalAssembly1.dll ExternalAssembly2.dll etc.
I used ILMerge to consolidate a WCF client proxies library with several data contract assemblies. It worked great! Now, instead of telling service consumers to copy the client proxies assembly plus a short list of contract assemblies, I can tell them to grab the one consolidated assembly to get everything they need. Writing an app to consume my services is done with one new reference–to the consolidated assembly–and less than 10 lines of code. A previously complicated process is now remarkably simple!
Unfortunately, it sounds like ILMerge doesn’t work for WPF assemblies, but the ILMerge website offers the following alternative:
If you cannot use ILMerge because you are trying to merge WPF assemblies, then here is a great way for you to get the same effect, courtesy of Jeffrey Richter: embed the dlls you want to merge as resources and load them on demand! In many ways, this is a better technique than using ILMerge, so I strongly urge you to check it out, even if ILMerge is working for your scenario.
ILMerge can be downloaded from the Microsoft Download Center here. It’s also available through NuGet. I haven’t tried that out yet, but I’m intrigued. I’ll probably try using NuGet to include it with each project I intend on using it with to ensure availability in builds and workspaces.