Why is my ServiceStack throwing an exception?
I built a simple Rest service using ServiceStack (which is brilliant) that returns a list of key value pairs.
My service looks like this:
public class ServiceListAll : RestServiceBase<ListAllResponse>
{
public override object OnGet(ListAllResponse request)
{
APIClient c = VenueServiceHelper.CheckAndGetClient(request.APIKey, VenueServiceHelper.Methods.ListDestinations);
if (c == null)
{
return null;
}
else
{
if ((RequestContext.AbsoluteUri.Contains("counties")))
{
return General.GetListOfCounties();
}
else if ((RequestContext.AbsoluteUri.Contains("destinations")))
{
return General.GetListOfDestinations();
}
else
{
return null;
}
}
}
}
my answer looks like this:
public class ListAllResponse
{
public string County { get; set; }
public string Destination { get; set; }
public string APIKey { get; set; }
}
and I matched the rest of the urls like this:
.Add<ListAllResponse>("/destinations")
.Add<ListAllResponse>("/counties")
when calling the service
http: // localhost: 5000 / counties /? apikey = xxx & format = xml
I am getting this exception (the breakpoint on the first line of the service is not hit):
NullReferenceException An object reference was not specified in an object instance. at ServiceStack.Text.XmlSerializer.SerializeToStream (Object obj, Stream stream) at ServiceStack.Common.Web.HttpResponseFilter. <GetStreamSerializer> b_3 (IRequestContext r, Object o, Stream s) in ServiceStack.Common.Web.HttpResponseFilter. <> c_DisplayClass1. <GetResponseSerializer> b__0 (IRequestContext httpReq, Object dto, IHttpResponse httpRes) in ServiceStack.WebHost.Endpoints.Extensions.HttpResponseExtensions.WriteToResponse (IHttpResponseExtensions.WriteToResponse (response IHttpResponerSeponer, object result, ResponseText)
The exception is thrown regardless of whether I include any parameters in the call or not. I also created a number of other services along the same lines in the same project that work fine. Can anyone point me in the right direction on what this means?
source to share
Your web service design is slightly reversed, your DTO request should RestServiceBase<TRequest>
not go your answer. And if you are creating a REST-ful service, I recommend the name (i.e. DTO request) of your service to be a noun for example. in this case, perhaps codes.
Also I recommend having and using the same syntax response for your service with a name following the convention '{RequestDto} Response', for example. CodesResponse.
Finally, we return an empty response instead of null, so clients need to process an empty result set rather than a null result.
This is how I would rewrite your service:
[RestService("/codes/{Type}")]
public class Codes {
public string APIKey { get; set; }
public string Type { get; set; }
}
public class CodesResponse {
public CodesResponse() {
Results = new List<string>();
}
public List<string> Results { get; set; }
}
public class CodesService : RestServiceBase<Codes>
{
public override object OnGet(Codes request)
{
APIClient c = VenueServiceHelper.CheckAndGetClient(request.APIKey,
VenueServiceHelper.Methods.ListDestinations);
var response = new CodesResponse();
if (c == null) return response;
if (request.Type == "counties")
response.Results = General.GetListOfCounties();
else if (request.Type == "destinations")
response.Results = General.GetListOfDestinations();
return response;
}
}
You can use the [RestService] attribute or the following route (which does the same):
Routes.Add<Codes>("/codes/{Type}");
This will allow you to call the service like this:
http://localhost:5000/codes/counties?apikey=xxx&format=xml
source to share