Result from a sub-property of wcf service is null - wcf

Ok so I have two objects that look like this in my WCF service. When my MyProfile property in my User class comes back to the client all of its properties are null; however, nothing else is.
[DataContract]
[Serializable]
public class User {
private WebProfile.UserTable _MyProfile;
public WebProfile.UserTable MyProfile {
get { return _MyProfile; }
set { _MyProfile = value; }
}
}
[DataContract]
[Serializable]
public class WebProfile {
[DataContract]
[Serializable]
public class UserTable {
}
}
On the WCF service it looks like this.
#region User Contract...
[ServiceContract]
public interface IUser {
List<User> GetAllUsers();
}
#endregion
public List<User> GetAllUsers() {
return _users;
}
I have only listed the property in question because I believe its specific to that property being in a subclass.
Here is what I have done. I have verified that the data is actually being obtained from the database on the service end from the database. Also, that MyProfile has values for its properties via Event Log.
When the client requests a list of Users I write to the event log on the server hosting the service to make sure MyProfile's properties have values. So the issue is either when the client deserializes the information or when the server serializes it to send to the client. Is it possible that my WebProfile class needs to be decorated with some type of attribute?
Again, I have verified that the User is coming back with values for all of its extra properties and that before the object leaves the server that the values are populated.
Any suggestions?

None of the class's properties for said object were decorated with the [DataMember] attribute.

Related

WCF - call method from service implementation

What I'm trying to do is the following:
1) I have the following WCF service contract:
[ServiceContract]
public interface IUploadService
{
[OperationContract]
ServiceData Upload(Request request);
}
[DataContract]
public class Request
{
[DataMember]
public long AbnNumber;
[DataMember]
public string Email;
}
2) This contract is implemented like this.
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
// Some code
}
}
In the "Some code" section I would like to call a validation class to validate the clients request, so something like this:
var result = validation.ValidateRequest(request);
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method? Like this:
public class UploadService : IUploadService
{
public bool Upload(Request request)
{
var validation = new Validation();
var result = validation.ValidateRequest(request);
}
}
I know you can get around this by creating a constructor but as far as I know you can't create a constructor inside a WCF service implementation class, or am I wrong?
I'm new to WCF so if I'm totally heading the wrong direction please let me know.
Thanks
Personally I like as little as possible in my service methods. I would have a separate project to handle the Upload. This then allows you to reuse this code more easily, and to test the functionality without creating the service.
As to whether you should create your Validation like this it really depends on what it does, but generally I would make sure the Validation class implements an interface containing ValidateRequest(Request) and then inject that. You can then mock it in your tests if you need to.
So your service code would look like
public class UploadService : IUploadService
{
private readonly IUploadHandler _uploadHandler;
public UploadService(IUploadHandler uploadHandler)
{
_uploadHandler = uploadHandler;
}
public bool Upload(Request request)
{
//would possibly do some mapping here to create a different type of object to pass to the handler
_uploadHandler.Upload(request);
}
}
and the handler in a different project would look like
public class UploadHandler : IUploadHandler
{
private readonly IValidation _validator;
public UploadHandler(IValidation validator)
{
_validator = validator;
}
public bool Upload(Request request)
{
return _validator.ValidateRequest(request);
}
}
So my question is: Is it a bad idea to create an instance of my validation class inside the Upload method?
It comes down to whether you will be using Singleton or Per Call services. Usually it is better to have new instance of Service created for every request, and in that case it is OK to create all instances in your operation.
Interesting discussion on this topic Should WCF service typically be singleton or not?
If you decide to not to create Validation class for each then request there are two options:
Make it singleton
Create custom ServiceHostFactory for your service and initialize your Service in it (with constructor). Useful links on this topic:Extending Hosting Using ServiceHostFactory, Integrating StructureMap with WCF

Using DataContract Proxies In WCF

So, I have created a couple of WCF services. Each return lists of a certain type of data contract. However, these data contracts have list properties of other data contracts. I am trying to implement lazy-loading of data contract collections.
What I've thought of is to implement a class at the client that inherits from the data contract with collection properties overriden so the setter and getter methods call the service and get the actual collection items.
My question is: How can I make the base channel to return the class that implements the data contract instead of the actual data contract? how can I control what the base channel returns?
My service client looks like this:
public class ServiceClient : BaseClient<IServiceClient>
{
public IList<DataObject> FindAll()
{
// how to control what base.Channel.FindAll return during deserialization.
return base.Channel.FindAll();
}
}
Note that I don't want to do something like this:
public class ServiceClient : BaseClient<IServiceClient>
{
public IList<DataObject> FindAll()
{
var dtos = base.Channel.FindAll();
var dtoProxies = Mapper.Map<DataObject, DataObjectProxy>();
return dtoProxies;
}
}
I want a way so WCF automatically returns a List<DataObject> which elements are actually of type DataObjectProxy.
Any suggestions on how to do this?
Thanks!
EDIT: Sample DataObject class:
[DataContract]
public class DataObject
{
public virtual List<OtherDomainObject> SubItems { get; set; }
}
public class DataObjectProxy : DataObject
{
public override List<OtherDomainObject> SubItems
{
get { // Custom way to retrieve collection... }
set { // Etc.. }
}
}
First, decorate the DataObjectProxy with the [DataContract] attribute, WCF requires explicit contract identifications for all the types - no matter what you gonna do with them later. Then, set [DataMember] on each and every field (property in your case) of the data contract types that you want to expose to the client.
Finally, add [KnownType(typeof(DataObjectProxy))] attribute on the DataObject class. KnownType defines all sub-types of the given base for polymorphic substitutions on the client.
This should work.
[DataContract]
[KnownType(typeof(DataObjectProxy))]
public class DataObject
{
[DataMember]
public virtual List<OtherDomainObject> SubItems { get; set; }
}
[DataContract]
public class DataObjectProxy : DataObject
{
[DataMember]
public override List<OtherDomainObject> SubItems
{
get { // Custom way to retrieve collection... }
set { // Etc.. }
}
}

Common WCF Response Handler?

I have a WCF Client, and the Endpoint has just been upgraded with a new method (OperationContract). I want to write a common method to handle the response from this new method as well as from the existing method at the endpoint.
I am trying to create a "Base" response class and adding common properties to it provided by the WCF endpoint, but I notice in my handler method, the properties are not being retained.
The code for the class I want all responses to inherit from looks like this :
public class ResponseBase
{
public string[] ItemsReturned;
public bool ItemsWereAvailable;
}
So I add partial declarations to get this onto the objects in the endpoint.
public partial class RetrieveResponse :ResponseBase
{
}
public partial class RetrieveResponse2 :ResponseBase
{
}
This way I have a handler method that just accepts "ResponseBase" as its input.
Am I doing this all wrong?
Any class whose instances will be return values and/or parameters of an operation contract should be decorated with the DataContract attribute, and the properties, as DataMembers:
[DataContract]
public class ResponseBase
{
[DataMember]
public string[] ItemsReturned { get; set; }
[DataMember]
public bool ItemsWereAvailable { get; set; }
}
http://msdn.microsoft.com/en-us/library/ms733127.aspx
If they are not, the DataContractSerializer doesn't serialize them.

Passing List<T> as parameter to WCF service operation

I have a WCF operation contract which looks like this:
public void SavePersons(List<Person> list, bool IsSelected)
{
}
I am passing it a strongly typed list of Person objects (List<Person>) in my client. However, I am getting a bad request 400 message when calling the service. What am I doing wrong?
May I suggest you create you create a contract to encapsulate the parameters like so:
public void SavePersons(PersonCollectionContract Request)
{
...
}
[DataContract]
public class PersonCollectionContract
{
[DataContract]
public List<Person> People { get; set; }
[DataContract]
public bool IsSelected { get; set; }
}
[DataContract]
public class Person
{
...
}
I was facing a similar problem in passing a List<Health> of class Health type as a parameter to a wcf service method. I created a data contract in wcf service as below:
[DataContract]
public class Health
{
...
}
Defined a method in wcf service class such as:
public string GetData(List<Health> healthValues)
In my client application, while configuring/updating the service, I followed these steps:
Add/Update URL
Under Data Type (in Advanced), selected option, Collection type: System.Collection.Generic.List
And finally, I created a list and added the code in client as follows:
List<WcfService.Health> listHealth = new List<WcfService.Health>();
WcfService.Health h = new WcfService.Health();
.
.
listHealth.Add(h);
WcfService.Service1Client s = new WcfService.Service1Client();
string str = s.GetData(listHealth);
This solved my purpose and I was able to send the data as a list through wcf service.

Error while running WCF service library

I have built a WCF service library, I have added reference to few 3rd party dll's. This is my interface
[ServiceContract]
public interface IService1
{
[OperationContract]
3rdpartyreturntype GetObj(System.Windows.Controls.Control txtcontrol);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations
[DataContract]
public class nclass
{
[DataMember]
public System.Windows.Controls.Control txtcontrol
{
get { return txtcontrol; }
set { txtcontrol = value; }
}
[DataMember]
public 3rdpartyreturntype nobj
{
get { return vuiobj; }
set { vuiobj = value; }
}
[DataMember]
public System.Windows.Input.TouchDevice tchdev
{
get { return tchdev; }
set { tchdev = value; }
}
}
and I have implemented the above interface. When I run the service I get the below error, can anyone help me out?
type 'System.Windows.Input.TouchDevice' cannot be serialized. Consider
marking it with the DataContractAttribute attribute, and marking all
of its members you want serialized with the DataMemberAttribute
attribute.
if you want a complex type like a class to be serialized you have to declare each of its members as data member and class as datacontract.
In this case touch device is the complex type(class) so you need to mark all of its members as datamembers and class as datacontract.
but as i can see from type that it belongs to system.windows.input the class may not be serialized. hence you cannot use this as a data member.
If you are using only a set of members belonging to touchDevice class, you can create your own class which will map only the set of touchdevice members which can be serialized. and decorate this new class with datacontract and datamember attributes.
It would appear that the type "System.Windows.Input.TouchDevice" is itself not marked as serializable or a DataContract.
Instead of trying to pass the TouchDevice and the Control directly like that, maybe you can just pass the properties you care about. I'm guessing in the case of the TextControl you just care about the Text value. And for the TouchDevice, maybe the source and target control name?