Visually Located

XAML and GIS

Using the WebAPI to send errors for your apps

If your app does anything at all complex, it’s going to crash. You’re going to miss checking something for null. You’re going to use a resource that doesn’t exist. Your app is going to crash. Luckily there are some ways to make sure you know what’s happening. Little Watson by Andy Pennell shows us a great way to send application errors but requires the user to email them to you. Bjorn Kuiper extended Little Watson by removing the need to email the report and instead send it to a PHP endpoint. This is a great solution provided your server is setup to run PHP . If you don’twant to use PHP, don’t want to install PHP or if you are using a hosting service that does not run PHP then you’re out of luck.

Instead of convincing your web provider to install PHP you could create a WCF service, but that seems like a lot of overhead. You could also create an ASP.NET web page and put the error details into a query parameter, but that seems hokie. Luckily the Web API has been introduced. The Web API makes this easy to implement, easy to deploy, and easy to use. Web API allows you to send an object of information in a well known format. Overall, the Web API is just awesome.

The first step is to start with the minimal Web API project. Open the Global.asax file and add the following line inside the Application_Start method

RouteTable.Routes.MapHttpRoute("ErrorRoute", "{controller}/{id}", new { id = RouteParameter.Optional });

Right click on the on controllers folder and create a new ApiController.

image

Following Bjorn’s example, we need an ExceptionContainer class that will hold our exception information. I’ve added an additional property for the application name. This is handy if you have more than one app.

public class ExceptionContainer
{
    ///  <summary>  
    /// Gets or sets the message.  
    /// </summary>  
    public string Message { get; set; }
 
    ///  <summary>  
    /// Gets or sets the stacktrace.  
    /// </summary>  
    public string StackTrace { get; set; }
 
    /// <summary>
    /// The application the error was found.
    /// </summary>
    public string ApplicationName { get; set; }
}

Inside the controller we need one method that we can send exception info to. The Web API allows you to take advantage of the HTTP verbs and structure your API in terms of them. For this error reporting, the most logical verb is POST. We’re not trying to GET, update (PUT) or DELETE anything. Create a new Post method that returns an HttpResponseMessage and takes an ExceptionContainer as a parameter. In the method we’ll send an email.

public HttpResponseMessage Post(ExceptionContainer exception)
{
    if (exception == null) return new HttpResponseMessage(HttpStatusCode.PaymentRequired);
 
    var message = new System.Net.Mail.MailMessage
        {
            From = new System.Net.Mail.MailAddress("phoneApps@yourdomain.com"),
            Subject = "Error report: " + exception.ApplicationName,
            Body = exception.Message + Environment.NewLine + exception.StackTrace
        };
    message.To.Add("you@domain.com");
 
    System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient("localhost", 25);
    // send credentials if your SMTP server requires them
    //client.Credentials = new NetworkCredential("user", "password");
    client.Send(message);
 
    return new HttpResponseMessage(HttpStatusCode.Created);
}

Deploy this up to your site and you’re ready to start sending application errors from your app.  Inside your app you simply need to package up the error and send to your server.

public void SendException(string uri, ExceptionContainer exception)
{
    try
    {
        JsonSerializerSettings settings = new JsonSerializerSettings();
        settings.NullValueHandling = NullValueHandling.Ignore;
        string postStr = JsonConvert.SerializeObject(exception, settings).Replace("\"", "'");
 
        WebClient client = new WebClient();
        client.Headers[HttpRequestHeader.ContentType] = "application/json";
        client.UploadStringAsync(new Uri(uri), postStr);
    }
    catch { }
}

Remember that you should ask the user if you can send error reports, or give them the option to turn it on or off.