0

EDIT I updated my question for completeness.

I have incoming REST calls from an iPHone client. It is meant to consume type-specific objects in response to generic requests. For example:

http://localhost:81/dashboard/group/id/0

returns data from the Regions type

http://localhost:81/dashboard/group/id/1

returns data from the Customers type

http://localhost:81/dashboard/group/id/2

returns data from the Users type

and so on.

The WCF Dashboard.svc service exposes a base method GetGroupById which I use to determine and return the type-specific response:

public class Dashboard : GroupBase, Contracts.IDashboardService { private string name = String.Empty;

    public Dashboard() : base()
    {

        if (!ServiceSecurityContext.Current.PrimaryIdentity.IsAuthenticated)
            throw new WebException("Unauthorized: Class: Dashboard, Method: Dashboard()",
                System.Net.HttpStatusCode.Forbidden);

        name = ServiceSecurityContext.Current.PrimaryIdentity.Name;

    }

    public override System.IO.Stream GetGroupById(string id)
    {
        return base.GetGroupById(id);
    }

}

Now, inside my abstract base class the GetGroupById has a switch/case statement that populates and returns unique data transfer objects based on the corresponding groupid parameter:

            public abstract class GroupBase
{

    protected GroupBase () { }

    public virtual Stream GetGroupById(string id)
    {
         // I have tried assigning response to null or, in this case,
         // assigning it to a random service object. I have also tried
         // IObjectFactory response; The last fails at compile-time and
         // the other two always produce null  
         IObjectFactory response = 
            ObjectFactory<IObjectFactory, UserService>.Create();  

        var groupId = System.Convert.ToInt32(id);
        var serializer = new JavaScriptSerializer();

        byte[] bytes = null;

        var message = String.Empty;

        try
        {

            switch (groupId)
            {
                case 0: // regions

                    response = ObjectFactory<IObjectFactory, RegionService>.Create();
                    break;

                case 1: // customers

                    response = ObjectFactory<IObjectFactory, CustomerService>.Create();
                    break;

                case 2: // users
                    response = ObjectFactory<IObjectFactory, UserService>.Create();
                    break;
            }

        }

        catch (EngageException oops)
        {
            message = oops.Message;
        }



        bytes = Encoding.UTF8.GetBytes(serializer.Serialize(response));

        return new MemoryStream(bytes);

    }

}

A customer ObjectFactory class is used to create the type-specific object:

public static class ObjectFactory where T : F, new() { public static F Create() { return new T(); } }

WHERE I AM HAVING PROBLEMS IS what is going on under the hood of my ObjectFactory. I am always getting ** null ** back. For example, consider the following REST HTTP GET:

http://localhost:81/dashboard/group/id/2

The above command is asking for a JSON string of all Users in the database. Accordingly, the UserService class is passed into the ObjectFactory method.

  public class UserService : IObjectFactory
{
    DomainObjectsDto IObjectFactory.Children
    {
        get
        {

            return new Contracts.DomainObjectsDto(UserRepository
                                .GetAllUsers().Select
                                (p => new Contracts.DomainObjectDto
                                 {
                                     Title = GroupTypes.Customer.ToString(),
                                     Id = p.CustomerId.ToString(),
                                     Type = p.GetType().ToString()
                                 }));
        }

    }

    string IObjectFactory.Method
    {
        get;
        set;
    }

    string IObjectFactory.Status
    {
        get;
        set;
    }

    etc...

And, the readonly Get property gets data from the UserRepository, populates the Data Transfer Object (illustrated below)

[DataContract]
public class DomainObjectDto
{
    [DataMember]
    public string Title { get; set; }
    [DataMember]
    public string Id { get; set; }
    [DataMember]
    public string Type { get; set; }
}

   [CollectionDataContract]
    public class DomainObjectsDto : List<DomainObjectDto>
    {
        public DomainObjectsDto() { }
        public DomainObjectsDto(IEnumerable<DomainObjectDto> source) : base(source) { }
    }

And should return the serialized JSON string of User data to the client. But, my generic type T in my object factory class is always null:

 public static F Create()
    {
        return new T(); // <-- always null!
    }

Any ideas??

Peter
  • 5,251
  • 16
  • 63
  • 98
  • 1
    You've given us bits and pieces of code. If you could post a short but complete program demonstrating the problem, it would be a lot easier to find out what's going on. – Jon Skeet Feb 08 '11 at 19:50
  • Thanks Jon. I agree :) I have reposted a complete question (I hope). Please let me know if I have left anything else out and thanks for your attention. – Peter Feb 08 '11 at 21:03
  • Interesting - Seems that everything works correctly on the back-end and then when the JSON string should be posted to the client, WCF goes through the whole process again and produces null. Soft of like a second and unnecessary post-back – Peter Feb 09 '11 at 14:56

3 Answers3

2

Hard to tell without seeing the invocation of your factory in context, but my gut feel is that groupId is not in the switch range and thus you are getting the null you defaulted it to. I would add a default case and throw an out of range exception and see if that's your problem.

James Michael Hare
  • 37,767
  • 9
  • 73
  • 83
  • Thanks James. No, it doesn't ever evaluate to the default condition. In debug mode I can see that the groupid parameter is evaluating to the appropriate switch/case condition. – Peter Feb 08 '11 at 21:15
0

It's a good idea to add default cases to your switch statements, like:

default: 
  throw new Exception( "groupId " + groupId + " not found" );
Chris Hogan
  • 868
  • 6
  • 9
0

Change the line IObjectFactory response = null; to remove the default, i.e. IObjectFactory response;. Now the compiler will tell you if there is a branch that doesn't assign it (of course, it can't tell you if you assign to null somehow). Note also that there are at least 2 ways of getting null from a new (etc), but these are edge cases - I doubt they are contributing (mentioned for completeness only).

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks - I played around with the response assignment but still get a null response. I have reposted my question for completeness - maybe something here is more obvious to you? – Peter Feb 08 '11 at 21:06