问题
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;
}
回答1:
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");
回答2:
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
.
回答3:
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.
回答4:
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),};
}
回答5:
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")]).
来源:https://stackoverflow.com/questions/5570173/c-sharp-design-problem-advice-cant-use-dictionary-then-what