WCF Client code does not reflect WCF service data contract changes automatically - wcf

I originally have defined a data contract for testing purpose as
[DataContract]
public class CreditCard: ISensitive
{
[DataMember]
public string CardNumber { get; set; }
}
The Wcf client reads this contract properly and I can use client reference classes for manipulating CardNumber field. However, when I use .NET Entity framework to generate the data contract's actual implementation I do not see the changes reflected completely in the client reference classes.
[DataContract]
public partial class CreditCard: EntityObject
{
// all Properties coming from database table
[DataMember]
public string CardNumber { get; set; }
[DataMember]
public string CardHolderName { get; set; }
[DataMember]
public DateTime ExpiryDate { get; set; }
}
public partial class CreditCard: ISensitive
{
// interface implementation and other methods
}
I am only able to manipulate CardNumber property, while other properties are not generated in the client code. I also do not see other entity types being generated on client code. Is there some versioning problem I am neglecting? Am I updating the service reference incorrectly? Why does the client code does not show DataContract classes generated by Entity Framework?

If you need to update your service definition on Client side, go to Solution Explorer. Under your client project, open 'Connected Services' and right-click on your Service Reference that connects to your buggy service. Select 'Update Service'.
That should renew the service definition on your client side to match the host.

Related

WCF: How to create an object as a parameter of message on client side

I have WCF service that uses raw messages (Message class).
1) Service side:
[DataContract]
public class Person
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
[ServiceContract]
public interface ITestService
{
[OperationContract(Action = TestService.RequestAction3)]
void AddNewPerson(Message newPerson);
public void AddNewPerson(Message newPerson)
{
Person personToAdd = newPerson.GetBody<Person>();
Employees.Persons.Add(personToAdd);
}
2) Client side:
TestServiceClient client = new TestServiceClient();
String RequestAction3 = "http://localhost:4249/Message_RequestAction3";
TestService.Person person = new TestService.Person
{
Id = 6,
FirstName = "Aleksey",
LastName = "Alekseyev"
};
Message request3 = Message.CreateMessage(MessageVersion.Default, RequestAction3, person);
string soapRequest = request3.ToString();
client.AddNewPerson(request3);
What's the problem here? I have Person class (data contract) on service side that is placed in TestService namespace: TestService.Person. Everything is fine on service side. But after I added service reference to client side by using "Add Service Reference..." option in VS2008, there's no such a type (TestService.Person) on client side. What I did to resolve this issue? I've simply copied the file with original data contract (TestService.Person) on client side, created object of Person type and passed it to the service method.
My question is - did I do it in correct way or there is another way to do this?
Thank you in advance.
Goran
Because Person class is not exposed in none of your service contracts their information is not shared via service metadata. That's why you get an error on the client side. If you copy the classes to your client with the same namespace that will do.
However a better solution is to place Person class in another assembly and reference this assembly from your client.

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.

WCF callback occurs error when serialize

I am programming a Azure WCF application.
A datacontract defined as below:
[DataContract]
public class UserInfo
{
[DataMember]
public string UserName { get; set; }
[DataMember]
public int UserID { get; set; }
[DataMember]
public bool IsOnline { get; set; }
}
then I define a datacontract in my WCF service:
[DataContract(Name="UserInfo")]
public class ServiceUserInfo : UserInfo
{
[IgnoreDataMember]
public ICallback Callback { get; set; }
}
Then in the service contract, it will callback to client, the method as below
private void NoticeUsers(UserInfo currentuser)
{
var users = UserManager.GetAllActiveUsers();
foreach (var user in users)
{
if (user.UserName == currentuser.UserName)
continue;
user.Callback.UpdateUserList(currentuser);
}
}
Actually I pass a ServiceUserInfo object as parameter to the NoticeUsers method. Then an error will occurs as below:
There was an error while trying to serialize parameter http://tempuri.org/:user. The InnerException message was 'Type 'WCFServiceWebRole.ServiceUserInfo' with data contract name 'UserInfo:http://schemas.datacontract.org/2004/07/WCFServiceWebRole' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
I am not able to find solution for this issue.Please help.
I think I have found the root cause of the issue, however I do not know why.
The problem is caused by the Namespace attribute of the Service contract.
I didn't set the namespace of my service contract interface and data contract interface. I thought it would be set by default and it won't cause any problem. But actually the issue of this thread is caused by the Namespace attribute. I set a Namespace attribute for both service contract and data contract, of course the same namespace, then it worked. The problem never happens again.
However, I do not know why it caused this issue. If I do not set Namespace, it will be a default value of "http://tempuri.org", isn't it?

access wcf interface method from client

This is one of the classes in Interface file.
[DataContract]
public class ClassX
{
public ClassX()
{
ClassXParameters = new List<ClassXParameter>();
}
public void Add(string name, string value)
{
ClassXParameters.Add(new ClassXParameter() { Name = name, Value = value });
}
[DataMember]
public List<ClassXParameter> ClassXParameters { get; set; }
}
[DataContract]
public class ClassXParameter
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Value { get; set; }
}
on the client I'm trying to do something like this
ClassX classx = new ClassX();
classx.Add("testname", "testvalue");
But this .Add method is not even visible.
currently I'm doing
ClassX classx = new ClassX();
List<ClassXParameter> params = new List<ClassXParameter()>;
params.add(new ClassXParameter() {Name="testname", Value="testvalue"});
classx.ClassXParameters = params;
Is there anyway I can do what I'm trying to do?
Note: I am not sure why some of the text above are in bold.
If you autogenerate the client code from scratch, it will generate a new class, which contains those members and properties that are marked with DataContract.
If you have methods that you want available on the client, you can accomplish this by putting the DataContract types in an own assembly, which you reference from both the server and the client. When you generate the service reference you have to choose the option to reuse existing classes instead of generating new ones.
Often it is suitable to put data validation rules in the data contract classes property setters. Reusing the data contract assembly in the client will cause the data validation to occur directly on the client, without the need for a roundtrip. It also causes the error in a place where it is much easier to spot than if it is reported as deserialization error.
Data Contracts are for data only. Any methods will not be visible on the client.
The bold was because of the "-----".

How can I pass a List<Interface> over WCF?

I have a WCF service where I am trying to return a List (where IWatchable is a custom interface I have built) in one of my operation contracts. When I test the service on the client the method returns an object[] instead of List<IWatchable>. Is it possible to return a List of IWatchable, since IWatchable is an interface with WCF?
Method:
public List<IWatchable> GetWorkload( Guid nodeId, int maximum )
IWatchable:
public interface IWatchable
{
string ActionName { get; set; }
Guid ActionReference { get; set; }
}
Hopefully a bit more info will be helpful...
I have a derived interface:
public interface IAMRAWatchable: IWatchable
And three concrete implementations from IAMRAWatchable:
public class InstrumentationWatch: IAMRAWatchable
public class OutputWatch: IAMRAWatchable
etc...
In my WCF method that returns List<IWatchable> I want to send an InstrumentationWatch and an OutputWatch to the client... Is this possible or am I going about this the wrong way?
Resolved
Thanks to John I found my solution. KnownType wasn't working since I was using List<IWatchable> - So I wrapped my list into a new class and added the attributes to it. I'll need to re-factor my code but for others who are interested here is the class:
[DataContract]
[KnownType( typeof( InstrumentationWatch ) )]
[KnownType( typeof( OutputWatch ) )]
public class WorkInfo
{
[DataMember]
public List<IWatchable> WorkQueue { get; set; }
}
and my WCF method:
public WorkInfo GetWorkload( Guid nodeId, int maximum )
An interface can never be serialized. It is only a description of behavior.
You can serialize objects which implement the interface, but you must tell WCF what their types are. See Data Contract Known Types.