Question

I have created a web service with ServiceStack which returns List<SyncUserDTO>. It has more properties, but I simplified it to one field, Timestamp.

[DataContract]
public class SyncUserDTO
{
    public SyncUserDTO()
    {
        Timestamp = new TimestampDTO();
    }

    [DataMember(Order = 1)]
    public TimestampDTO Timestamp { get; set; }
}

[DataContract]
public class TimestampDTO
{
    [DataMember]
    public bool DataValid { get; set; }
    [DataMember]
    public DateTime? Value { get; set; }
}

The service seems to work perfectly (with other tests), but when I create a client console application and Add Service Reference, the SyncUserDTO does not have the constructor, meaning this doesn't work:

static void SendUsersServiceReference()
{
    var users = new List<SyncUserDTO>();
    for (var i = 0; i < 5; i++) 
    {
        var user = new SyncUserDTO();

        user.Timestamp.Value = DateTime.Now;  // NullReferenceException, 
        user.Timestamp.DataValid = true;      //   as Timestamp is null
    }
}

When pressing F12 on SyncUserDTO, I can't seem to find any Constructor method in Reference.cs, explaining why the above doesn't work.

But why is the constructor not created in my proxy classes in the client application?

I need to do the "construction" myself in the client, and then it works:

       var user = new SyncUserDTO() { Timestamp = new TimestampDTO() };

Of cause, I don't want the people who consumes my service to have to create this themselves. They should really note care about the underlying TimestampDTO. The constructor should do this.

Btw, I searched Google and SO for terms like "Constructor not created in proxy class with Add Service Reference" with and without "ServiceStack", no results to aid me in this quest...

Pps. Demis (ServiceStack), if you're reading this, yes SOAP is on the way out, REST is the new black - but I want to support both, which it seems like ServiceStack does, which is really great. I love ServiceStack :D

Was it helpful?

Solution 2

This is my solution (for now):

I created a new service method in my service, where the client gets a new UserDTO complete with all fields. This way, the constructor is run on the server. I bet I have quite a performance hit this way, but it doesn't matter that much (now...).

Service DTO's:

[DataContract]
public class ReturnNewEmptyUser : IReturn<ReturnNewEmptyUserResponse> {}
[DataContract]
public class ReturnNewEmptyUserResponse
{
    [DataMember]
    public SyncUserDTO User { get; set; }
}

The Service:

public class SyncService : Service
{
    public ReturnNewEmptyUserResponse Any(ReturnNewEmptyUser request)
    {
        var user = new ReturnNewEmptyUserResponse { User = new SyncUserDTO() };
        return user;
    }
}

On the client:

    static void SendUsersServiceReference()
    {
        var webservice = new ServiceReference1.SyncReplyClient();

        var users = new List<User>();
        for (var i = 0; i < 5; i++)
        {
            var userResponse = webservice.ReturnNewEmptyUser(new ReturnNewEmptyUser());
            var user = userResponse.User;

            user.Timestamp.Value = DateTime.Now;
            user.Timestamp.DataValid = true;
            // Continue with field population...

            users.Add(user);
        }

        // Send users with webservice method
        // ...
    }

We're wondering if it is a bad way to expose the fields this way. It is nice, because the client can use autocomplete and know exactly the types used - but is it better to force the client to create an XML/JSON in a specific format.

This should be in another question - this question I guess has been answered: Add service reference/proxy classes does not contain methods (incl. constructors for types), only types. If you really need the constructor, have it run and then exposed on the server and then consume it from the client. Like a factory-thing, as Adam wrote here: Class constructor (from C# web service) won't auto-implement properties in C# MVC

Btw - is there any security issues with this design? User is logged in via url-credentials (should probably be header authentication), only a few systems has access to it.

OTHER TIPS

try to instanciate your property by the time you are going to access it, I know that´s a workaround but it could be convenient in your scenario.

private TimestampDTO  _timestamp;
public TimestampDTO Timestamp 
{
    get
    {
       if(_timestamp==null) _timestamp=new TimestampDTO();
       return _timestamp;
    }
    set
    {
       _Timestamp=value;
     }
}

A proxy class does not keep implementation details, like a constructor. It is just a DTO. This can only be done if you share the classes, through a shared project.

Think about that servicestack is just telling the client which properties it needs, and their type.. the implementation is up to the client.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top