WebGet and object as GET parameter in WCF REST client - wcf

Let's say we have REST client with next declaration:
[ServiceContract]
interface ITestClient
{
[OperationContract]
[WebGet(UriTemplate = "SetData/?d1={d1}&d2={d2}")]
void SetData(string d1, string d2);
}
I would like tu use it with next signature (HTTP GET):
[ServiceContract]
interface ITestClient
{
[OperationContract]
[WebGet(UriTemplate = "SetData/?")]
void SetData(SetDataRequest setData);
}
[DataContract]
public class SetDataRequest
{
[DataMember(Name = "d1")]
private string Data1 { get; set; }
[DataMember(Name = "d2")]
private string Data2 { get; set; }
}
I wish that WCF serializes instance of the SetDataRequest to HTTP QueryString.
Is this possible (HTTP POST is not acceptable)?

You should not use WebGet for this you should instead do:-
[OperationContract]
[WebInvoke( UriTemplate="SetDate/" Method="POST")]
void SetData(SetDataRequest setData);
You should use a post when submitting data as you will run into security/caching issues if you don't.

Related

How to Write a WCF service method which should accept the logs as a collection in C#?

How to Write a WCF service method which should accept the logs as a collection in C# ?
My WCF service should accept the collection of log messages and then we have to insert into the DB.
Thanks !!!
You can implement that simply as follows: ( you might add yourself any other parameters you want to the service method including service headers)
[DataContract]
public class LogData
{
[DataMember]
public long LogId { get; set; }
[DataMember]
public string LogMessage { get; set; }
}
[ServiceContract]
public interface ILoggerService
{
[OperationContract]
void SaveLogs(List<LogData> logs);
}
public class LoggerService : ILoggerService
{
public void SaveLogs(List<LogData> logs)
{
// write your DB specific logic to loop through the logs object and store into the db.
}
}

DataContract not working and classes are not showing on the client

[ServiceContract(SessionMode = SessionMode.Required)]
public interface IActionService
{
[OperationContract]
MovieResponse GetReviews(MovieRequest request);
[OperationContract]
UserResponse GetUsers(UserRequest request);
[OperationContract]
UserResponse InsertUser(UserRequest request);
}
[DataContract]
public class UserRequest
{
[DataMember]
public int userId;
[DataMember]
public User user;
}
I cant see the userrequest and userresponse in my ServiceReference at the client. Why?
I had a reference to the WCF Service application assembly which should not be there. After removing the reference I could see my Classes.
Thanks

WCF Interface as parameter

I am using interface as input parameter in OperationContract. But when i generate proxy class at client side. I am not able to access the members of interface or class implemeting the ITransaction interface. I am only geeting is object
Service Interface
[ServiceContract]
public interface IServiceInterface
{
[OperationContract]
string SyncDatabase(ITransaction TransactionObject);
}
Service class
class SyncService:IServiceInterface
{
public string SyncDatabase(ITransaction TransactionObject)
{
return "Hello There!!";
}
}
Interface
public interface ITransaction
{
ExpenseData ExpData { get; set; }
void Add(ITransaction transactionObject);
}
Data Contract
[DataContract]
public class Transaction:ITransaction
{
[DataMember]
public ExpenseData ExpData
{
get;
set;
}
public void Add(ITransaction transactionObject)
{
}
}
In above case should i also copy the iTransaction class and interface on client
You actually need to make your ServiceContract aware of the implementation of the interface you pass as a parameter, so WCF will include it in the WSDL.
This should work:
[ServiceContract]
[ServiceKnownType(typeof(Transaction))]
public interface IServiceInterface
{
[OperationContract]
string SyncDatabase(ITransaction TransactionObject);
}
Use [KnownType(typeof(testClass))].
Refer these links:
msdn.microsoft.com/en-us/library/ms730167.aspx
www.codeproject.com/Tips/108807/Implementing-KnownType-Attribute
Try making your interface the [DataContract] and use the [KnownType] attribute to tell WCF what the known implementations of that interface are.
[DataContract]
[KnownType(typeof(Transaction))]
public interface ITransaction
{
[DataMember]
ExpenseData ExpData { get; set; }
void Add(ITransaction transactionObject);
}

Bad request 400 on sending xml request in wcf rest

I am writing a sample application using wcf rest for authentication. Here is the snapshot of the code:
service Interface:
[ServiceContract]
public interface IAuthenticate
{
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Bare,
Method = "POST", UriTemplate = "/VUser",RequestFormat= WebMessageFormat.Xml ), ]
string CreateUser(VUser user);
}
Datacontract class:
[DataContract]
public class VUser
{
public VUser()
{
}
[DataMember]
public string NickName { get; set; }
[DataMember]
public string lName { get; set; }
[DataMember]
public string fName { get; set; }
[DataMember]
public string Email { get; set; }
[DataMember]
public string PhoneNumber { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string Gender { get; set; }
[DataMember]
public int CountryCode { get; set; }
}
Service class:
public class Authenticate : IAuthenticate
{
#region IAuthenticate members
public string CreateUser(Vuser user)
{
//processing xml for response
}
#endregion IAuthenticate
}
client code:
Uri baseAddress = new Uri("http://localhost:8000");
using (WebServiceHost host = new WebServiceHost(typeof(Authenticate), baseAddress))
{
host.Open();
Console.WriteLine("Press any key to terminate");
Console.ReadLine();
host.Close();
}
Now I am using fiddler to send the request after host.open() and send the the request has shown:
post http://localhost:8000/Vuser/
User-Agent: Fiddler
Host: localhost:8000
content-length: 233
content-type: text/xml
and in request body :
sandy
r
sunil
sunil.r
919900101948
winter
male
01
but it is returning me HTTP/1.1 400 Bad Request. My question is am I passing the vuser class correctly to the create user method or is there any other way to send the vuser.
Please help me.
It could be a problem with serialization.
Serialization uses the default consrtuctor, without parameters.
In C# the compiler will automatically create a default constructor, except if you create a constructor with a parameter.
The Authenticate class is missing a default constructor, you will therefore have probelms sending it over WCF.
Kindly specify The Datacontract Namespace in DataContract Class
[DataContract(Namespace = "http://xxx.xxx.xxx/Service.svc")]
and follow same in Xml file
The Namespace in both client and server should match. Try to add namespace name as
[DataContract(Namespace = "http://sample.com")]
public class VUser
in the server contract. And then make sure the xml string has the xmlns value with the same namespace
"<VUser xmlns=\"http://sample.com" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">...</VUser>"

WCF Rest client and Transfer Encoding Chunked: Is it supported?

I have a datacontract as defined below:
[DataContract(Namespace="",Name="community")]
public class Community {
[DataMember(Name="id")]
public int Id{get; set;}
[DataMember(Name="name")]
public string Name { get; set; }
[DataMember(Name="description")]
public string Description { get; set; }
}
and the service contract goes like this:
[OperationContract]
[WebGet(
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "{id}"
)]
Community GetCommunity(string id);
When I make a rest call to the host, I get data but only Id and Name properties are populated. The Description property is null! I am creating the channel by inheriting from ClientBase.
Does anybody know why WCF serializes Id and Name but not Description? The Transfer Encoding is set to 'Chunked' on the response from the host and I would like to know if that has anything to do with it ?
I found out that some of the properties were not getting serialized because the response xml had the elements in a different order. The solution was to explicitly set serialization order on the datacontract. Here is the datacontract after I added order attribute:
[DataContract(Namespace="",Name="community")]
public class Community
{
[DataMember(Name = "name",Order=2)]
public string Name { get; set; }
[DataMember(Name="id",Order = 1)]
public int Id{get; set;}
[DataMember(Name="description",Order=3)]
public string Description { get; set; }
}