user2237815
user2237815

Reputation: 43

ServiceStack: Errors not serialized to responsestatus

Iam new to service stack and have been strugling for hours, trying to make servicestak work for me. For now the major show stopper is that i cann't make the exception part work. I registered all plugins by the book and services work for both REST, Soap, CSV, XML and JSV. The project contains 4 basic test methods for crud operations on a customer object. When an error is thrown i do not get the expected error: ResponseStatus is not set and a generel error is generated. Can some one please help me find out why?

https://dl.dropbox.com/u/101619220/TestingServiceStack.zip

EDIT: Thanks for comment :)

I created a simple AppHost file:

namespace TestingServiceStack { public class AppHost : AppHostBase { public AppHost() : base("StarterTemplate ASP.NET Host", typeof(CustomersService).Assembly) { }

    public override void Configure(Container container)
    {
        Plugins.Add(new ValidationFeature());
        Plugins.Add(new RequestLogsFeature());

        SetConfig(new EndpointHostConfig
            {
                DebugMode = true, //Enable StackTraces in development
            });

        LogManager.LogFactory = new Log4NetFactory(true);

        JsConfig.EmitCamelCaseNames = true;
        JsConfig.DateHandler = JsonDateHandler.ISO8601;

        Routes.Add<GetCustomers>("/customers", "GET")
              .Add<GetCustomers>("/customers/{Id}", "GET")
              .Add<AddCustomer>("/customers", "POST")
              .Add<UpdateCustomer>("/customers/{Id}", "PUT")
              .Add<DeleteCustomer>("/customers/{Id}", "DELETE");
    }

    public static void Start()
    {
        new AppHost().Init();
    }
}

}

And a service:

namespace TestingServiceStack { public class CustomersService : Service { #region Logging

    private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    #endregion

    public object Any(GetCustomers request)
    {
        GetCustomersResponse response = null;
        try
        {
            if (request.Id != "0")
                throw HttpError.NotFound("Id {0} throws error".Fmt(request.Id));

            response = new GetCustomersResponse {Id = request.Id ?? "notset", Name = "GetCustomers"};
        }
        catch (Exception ex)
        {
            Log.Error(base.RequestContext.Get<IHttpRequest>(), ex);
            throw;
        }

        return response;
    }

    public object Any(AddCustomer request)
    {
        return new AddCustomerResponse {Id = request.Id, Name = "AddCustomer"};
    }

    public object Any(UpdateCustomer request)
    {
        return new UpdateCustomerResponse {Id = request.Id, Name = request.Name};
    }

    public object Any(DeleteCustomer request)
    {
        return new DeleteCustomerResponse {Id = request.Id, Name = "DeleteCustomer"};
    }
}

}

And the exchanged objects are:

using System.Runtime.Serialization; using ServiceStack.ServiceInterface.ServiceModel;

namespace TestingServiceStack { [DataContract] public class GetCustomers { [DataMember] public string Id { get; set; } }

[DataContract]
public class UpdateCustomer
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

[DataContract]
public class AddCustomer
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Name { get; set; }
}

[DataContract]
public class DeleteCustomer
{
    [DataMember]
    public string Id { get; set; }
}

[DataContract]
public class GetCustomersResponse : IHasResponseStatus
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

[DataContract]
public class UpdateCustomerResponse : IHasResponseStatus
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

[DataContract]
public class AddCustomerResponse : IHasResponseStatus
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

[DataContract]
public class DeleteCustomerResponse : IHasResponseStatus
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

}

I use SoapUi to call the method GetCustomers that throws an error if id equals 0, and i would expect the ResponseStatus to be set, but it isn't. When calling from SoapUi i get the following error:

I have no clue how to get reponsestatus set proberly, any hints are appreciated.

Upvotes: 2

Views: 1345

Answers (3)

Peter Mounce
Peter Mounce

Reputation: 4225

We had an issue where ResponseStatus wasn't being populated - we'd decorated the Response DTO with DataContract/DataMember, but not the ResponseStatus property. Once we added that decoration, all was joyful.

Upvotes: 1

paaschpa
paaschpa

Reputation: 4816

I registered all plugins by the book and services work for both REST, Soap, CSV, XML and JSV To echo @mythz it's much easier to answer direct questions with clearly stated problems with examples of errors or exceptions. My issue with statements/generalizations like above is that I don't know what 'by the book' means nor do I know your concept of working is (could be build succeeds, metadata page is displayed, etc)

ResponseStatus is not set and a generel error is generated.

In your CustomersService class it looks you are throwing an error (HttpError) and catching/logging it. The code will then proceed to return a null response. ServiceStack has native support for throwing of exceptions. If you add a throw into your catch (assuming you want to keep the catch for logging purposes) you should get a populated ResponseStatus.

        GetCustomersResponse response = null;
        try
        {
            if (request.Id != "0")
                throw HttpError.NotFound("Id {0} throws error".Fmt(request.Id));

            response = new GetCustomersResponse {Id = request.Id ?? "notset", Name = "GetCustomers"};
        }
        catch (Exception ex)
        {
            Log.Error(base.RequestContext.Get<IHttpRequest>(), ex);
            throw; //Let ServiceStack do its thing.
        }

        return response;

SoapUI

This change may fix the issue with soapUI but I'm unclear as what 'general error' you are receiving. I'm guessing the issue could be due to 'deserializing' a null response.

Upvotes: 2

mythz
mythz

Reputation: 143284

ServiceStack doesn't support troubleshooting with 3rd party SOAP libraries or client proxies.

See WebServicesTests.cs for examples of exceptions in integration tests. For SOAP you also want to read up on ServiceStack's SOAP Support and its limitations

Upvotes: 1

Related Questions