C# - Design Problem Advice: Can't Use Dictiona

2019-05-16 22:01发布

I need to return a Dictionary (or some List, I just don't know) via a web service, specifically through a WCF Data Services. It looks like WCF Data Services does not support Dictionary types.

Something to look like this via the web service:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
- <Employees xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">
    <element>employee1, True</element> 
    <element>employee2, False</element>
    <element>employee3, True</element>
  </Employees>

I first tried a 1-dimensional array and this seems to work but of course only brings those 1 dimensional array with 3 elemetns:

[WebGet]
public string[] Employees()
{
   return new[]
   {
        "employee1",
        "employee2",
        "employee3"
   };
}

Basically, I need some List (?) with two parameters in each, that is, EmployeeName and a booleann value, IsActive.

Any advice will be greatly appreciated.

Update: I added the following to my web service:

public class Employee
    {
        public string Name{ get; set; }
        public bool IsActive{ get; set; }

        public Employee(string name, bool isActive)
        {
            Name = name;
            IsActive = isActive;
        }
    }

[WebGet]
        public List<Employee> Employees()
        {
            var emp1 = new Employee("Test1", true);
            var emp2 = new Employee("Test2", true);
            var list = new List<Employee> { emp1, emp2 };
            return list;
        }

And when like the .svc file via my web browser, I get this on load:

Request Error

The server encountered an error processing the request. The exception message is 'Unable to load metadata for return type 'System.Collections.Generic.List`1[Web.Employee]' of method 'System.Collections.Generic.List`1[.Web.Employee] Employees()'.'. See server logs for more details. The exception stack trace is: 

at System.Data.Services.Providers.BaseServiceProvider.AddServiceOperation(MethodInfo method, String protocolMethod) at System.Data.Services.Providers.BaseServiceProvider.AddOperationsFromType(Type type) at System.Data.Services.DataService`1.CreateProvider() at System.Data.Services.DataService`1.HandleRequest() at System.Data.Services.DataService`1.ProcessRequestForMessage(Stream messageBody) at SyncInvokeProcessRequestForMessage(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Any ideas?

Update 2:

Here is more information on my DataService.svc class. I am using V2 of WCF Data Services with the .NET 4.0 framework:

public class WebDataService : DataService<MyModelEntities>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.UseVerboseErrors = true;
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead | EntitySetRights.AllWrite);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }

5条回答
仙女界的扛把子
2楼-- · 2019-05-16 22:22

Can you try returning IQueryable instead of List? Your return statement will change to return list.AsQueryable(); in that case. Also, you will need to add [DataServiceKey] attribute to the Employee class (e.g. [DataServiceKey("Name")]).

查看更多
等我变得足够好
3楼-- · 2019-05-16 22:33

Why dont you just create a user defined data type with two attributes a string and a boolean?

public class MySillyWCFObject
{ 
 boolean b;
 string name;

 public MySillyWCFObject(boolean b, string s)
  {
   this.b = b;
   this.name = s;
  }
}

Then you can say:

MySillyWCFObject m = new MySillyWCFObject(true, "Hi");
查看更多
够拽才男人
4楼-- · 2019-05-16 22:37

I have used this before How to Return Generic Dictionary in a WebService.

It is code to provide you with a serializable dictionary. It works great. We have a real-time system which passes these around and it works perfectly.

查看更多
Juvenile、少年°
5楼-- · 2019-05-16 22:38

you can create a little transfer object class like:

[DataContract]
public class EmployeeDTO {

public EmployeeDTO(string empName,bool isActive){
   EmployeeName = empName;
   IsActive = isActive;
}
[DataMember]
public string EmployeeName {get;private set;}
[DataMember]
public bool IsActive {get;private set;}

}

your service method

[WebGet]
public EmployeeDTO[] Employees(){
 return new []{new EmployeeDTO("employee1",true),
               new EmployeeDTO("employee2",false),
               new EmployeeDTO("employee3",true),};
}
查看更多
仙女界的扛把子
6楼-- · 2019-05-16 22:46

If you don't need to create your own class just for this, you can use a Tuple:

var tuple = Tuple.Create(true, "Hi");

This will create a Tuple<bool, string> by inferring the types from the method call's parameters. You can then access true and "Hi" as Tuple.Item1 and Tuple.Item2.

查看更多
登录 后发表回答