Getting ADO.NET Data Service error details on client

When you are working with ADO.NET Data Services, errors are returned through the HTTP mechanism. Right now the most straightforward way of handling any errors on the client is by catching a WebException and using it.

Something that is a bit obscure is that even though an exception has been thrown, it's possible that a response is available - this is very often the case when the server was indeed contacted and a reply was sent.

The following short console project demonstrates how to handle an error on the client side. The server side uses a service operation, which I will go into more detail in a future post, along with a more in-depth explanation of how exceptions are handled on the server side.

First, let's start with the skeleton for the file.

using System;
using System.IO;
using System.Net;

using Microsoft.Data.Web;

namespace ConsoleApplication1
{
/* Everything else comes here */
}

Now, let's add a service. In place of 'object' we would normally include the real type for our data source, an EDM ObjectContext for example, but because we won't be reading any data, anything will do. We'll include a service operation that throws an exception.

    class ErrorService : WebDataService<object>
{
public static void InitializeService(IWebDataServiceConfiguration c)
{
c.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
}

        [System.ServiceModel.Web.WebGet]
public void Operation()
{
throw new Exception("Nooooooo!");
}
}

Next, let's write the main method of our program. It will get a service running, then make a request, and then wait for a key to be pressed so you can read the output. The interesting bit is in how it handles and prints out exception information for the request. I've linked to a couple of interesting classes in the code.

    class Program
{
static void Main(string[] args)
{

            Type serviceType = typeof(ErrorService);
Uri[] baseAddresses = new Uri[] { new Uri("
https://localhost:8090/ ") };
DataServiceHost host = new DataServiceHost(serviceType, baseAddresses);

Console.WriteLine("Starting host...");
host.Open();

            Console.WriteLine("Invoking service operation...");
WebRequest request = WebRequest.Create("
https://localhost:8090/Operation ");
try
{
WebResponse response = request.GetResponse();
Console.WriteLine("Response succeeded.");
}
catch (WebException exception)
{
Console.WriteLine("Exception caught.");
if (exception.Response != null)
{
Console.WriteLine("Status: " + exception.Status.ToString());
HttpWebResponse httpResponse = (HttpWebResponse)exception.Response;
Console.WriteLine("HTTP Response Status: " + httpResponse.StatusDescription);
using (StreamReader reader = new StreamReader(exception.Response.GetResponseStream()))
{
Console.WriteLine(reader.ReadToEnd());
}
}
}

            host.Close();

            Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}

To build this program, you'll need references to at least Microsoft.Data.Web, System.ServiceModel and System.ServiceModel.Web, in addition to the regular assemblies included in a new Console project. When you run it, you should see output similar to the following:

Starting host...
Invoking service operation...
Exception caught.
Status: ProtocolError
HTTP Response Status: Internal Server Error
Exception has been thrown by the target of an invocation.
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Data.Web.RequestUriProcessor.ProcessRequestUri(String requestUri, IWebDataService service)
at Microsoft.Data.Web.WebDataService`1.ProcessIncomingRequest()
Nooooooo!
at ConsoleApplication1.ErrorService.Operation()

Press any key to exit.

 

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm.