WCF SOAP and REST together - wcf

Lets say I have WCF Soap Services and I am using this library for SOAP headers
http://wcfextras.codeplex.com/
For example my interface looks like this
[SoapHeader("HelperHeader", typeof(HelperHeader), Direction = SoapHeaderDirection.In)]
[OperationContract]
string GetData(string id);
////////
public string GetData(string id)
{
HelperHeader clientHeader=SoapHeaderHelper<HelperHeader>.GetInputHeader("HelperHeader");
if (clientHeader != null)
return id
}
In Header class i have user name and password for basicHttpbinding.
Now i want to use this method "GetData" for REST service . (I also have second webHttbinding) . I want to use this Method "GetData" for REST clients , now i find that i can use attributes WebGet and Webinvoke
[OperationContract]
[WebGet(UriTemplate = "testjson/{id}", ResponseFormat = WebMessageFormat.Json)]
string GetData(string id);
My quietion is how i can use One Method "GetData" for both REST and SOAP services and with user name and password .?

When you create a HttpRequest you can add whatever you want to headers collection:
WebRequest request = WebRequest.Create("<URI>");
request.Headers.Add("username", "<UserName>");
request.Headers.Add("password", "<Pass>");
request.GetResponse();
and in the Service implementation, you can easily access to headers collection by calling this property WebOperationContext.Current.IncomingRequest.Headers

Related

Regarding UriTemplate usage in WCF and AspNetCompatibilityRequirements usage WCF

1) i never design or develop any wcf service with rest approach. so when i was going through lots of article of similar kind then i notice one keyword that is UriTemplate.
so like to know what is UriTemplate and what it does ?
i have seen few different kind of UriTemplate as follows below
UriTemplate = "/X/{y}?Z={z}")
UriTemplate = "/GetPeople"
UriTemplate = "/GetPerson?id={id}"
UriTemplate = "Auth/Login"
what does it mean /X/{y}?Z={z} or GetPerson?id={id} ??
what does this mean UriTemplate = "Auth/Login" when method name is AuthLogin
[WebInvoke(Method = "POST", UriTemplate = "Auth/Login", BodyStyle = WebMessageBodyStyle.WrappedRequest)]
public bool AuthLogin(string userName, string password)
{
var provider = (SqlMembershipProvider)Membership.Provider;
if (provider.ValidateUser(userName, password))
{
FormsAuthentication.SetAuthCookie(userName, true);
return true;
}
return false;
}
2) what is AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] and what it does or confirm.
if some one do not use it then what may happen?
URITemplate is used to control the template based generation of WCF REST Service URIs. To enable customization of the URI for each method and verb combination, WCF added the ability to define the URI for each resource by using a special template syntax. This syntax allows you to define, with replaceable tokens, the URI structure you'd like each method to represent in conjunction with the HTTP verb.
The following article provides a good overview:
http://debugmode.net/2010/06/02/urirest1/
Regarding the second question about AspNetCompatibilityRequirements, the following StackOverflow post seems to provide good details:
Why does AspNetCompatibilityRequirementsMode.Allowed fix this error?

How to ge thet data from WCF Ria Service method that returns IQueryable<> using ChannelFactory

I have a WCF RIA Service with methods that return IQueryable<>. I want to access this methods using ClannelFactory from a
console application. I have an interface on the client that matches the the methods in my RIA Service. When I run the server and
the client applications I can see that the server method is called and an IQuery<> object is returned. The problem is that on the
client I can't get the data sent by the server. I can see that data actually comes by using Fiddler, but I think that the data can't be
deserialized to IQueryable.
For me the type of the data received doesn't matter. I'll be happy with just an array. But because the method in the
service returns IQueryable my OperationContract method on the client has the same type.
So the question is how to get the data from the server, without changing the return type (IQueryable) on the server side?
Server side:
public IQueryable<Customers> GetCustomers()
{
List<Customers> customersList = new List<Customers>();
customersList.Add(new Customer())
...
return customersList.AsQueryable();
}
Client side:
[ServiceContract]
public interface CustoemrsService
{
[OperationContract]
IQueryable<Customers> GetCustomers();
}
And the ChannelFactory code:
var endpointAddress = new EndpointAddress(_endpointAddress);
var channelFactory = new ChannelFactory<VfxSystemDomainServiceSoap>(new BasicHttpBinding());
var channel = channelFactory.CreateChannel(endpointAddress);
IQueryable<Customers> customersCollection = channel.GetVfxfopenQuery();

WCF service consume, no response at all

Sorry to bother you guys again.
I am going to consume a WCF service on a server. The service was created by outside. If I look at it in the browser, it is fine. Please see the image below.
To consume it, I add service reference. with the url http://wsvc01/BOERPI/BOERPI.svc
Then I instantiate the proxy by the code.
BOERPI.PostPhoneCallResponse client = null;
client = new BOERPI.PostPhoneCallResponse();
double x = client.ActualCallCharge; // suppose to get a proper value but not
Some of the code of the service is:
[ServiceContract]
public interface iBOERPI
{
[OperationContract]
PostPhoneCallResponse PostPhoneCall(PostPhoneCallRequest objCDRRequest);
[DataContract]
public class PostPhoneCallResponse
{
[DataMember]
public double ActualCallCharge = -1.0;
I assume the service code is 100% right, is any thing wrong when I consume the service?
When I righted click the definition of PostPhoneCallResponse, it is:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="PostPhoneCallResponse", Namespace="http://schemas.datacontract.org/2004/07/nsBOERPI")]
[System.SerializableAttribute()]
public partial class PostPhoneCallResponse : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private double ActualCallChargeField;
Thanks.
client = new BOERPI.PostPhoneCallResponse(); You are trying to use your DataContract here instead of Service client.
Check under Service References for your service name you used in your client application and
use it:
eg.
using(var client = new BingMapsGeocodeService()) // This should be your service client name
{
}
Update:
Sending and Received messages using request and response objects:
You need to create a request object as per your operation shows:
var request = new PostPhoneCallRequest(){ // populate all your properties you need to send to the service};
var client = new BOERPI.MyClient(); // Instantiate your client with the name you have given for your service client.
PostPhoneCallResponse response = client.PostPhoneCall(request); // You are sending your request and getting a response as PostPhoneCallResponse object

Ignore content type for specific WCF OperationContracts

I have a WCF REST Service that primarily sends and receives JSON.
In general, I'm okay with using the DataContractJsonSerializer, but for some objects that are passed in as parameters to the OperationContact methods, I need to use JSON.NET for the deserialization.
To do this, the standard approach is to have a Stream as an input parameter.
[OperationContract]
[WebInvoke(UriTemplate = "DoStuff", Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare)]
public void SetAppSettings(Stream input)
{
// parse input as JSON string, deserialize, process
}
However, when I try to POST content with Content-Type: application/json to this method, I get an exception saying that Raw content was expected.
From the point of view of the client, I am always sending application/json content. I don't want the client to have be aware that it should be setting Content-Type: text/plain instead of application/json (which is used in every other case).
Is there a way to get WCF to ignore the request content type for specific OperationContracts (rather than switching to a raw model for the entire service)?
Alternatively, is there some way I could omit the Stream parameter, and instead get the raw bytes of the request body from, say, HttpContext.Current while inside the method?
Have you tried explicitly setting the request format at the operation contract level?
[OperationContract]
[WebInvoke(UriTemplate = "DoStuff", Method = "POST",
BodyStyle = WebMessageBodyStyle.Bare
**RequestFormat = WebMessageFormat.Json**)]
public void SetAppSettings(Stream input)
{
// parse input as JSON string, deserialize, process
}

How to define attributes to upload data to a REST web service implemented through a WCF service?

I created a WCF service, that returns some data and also allow to post some data to.
The methods of the service are as below:
[OperationContract]
bool UploadStream(Guid key, List<StreamRecord> values);
[OperationContract]
bool RegisterStream(Guid key);
[OperationContract]
StreamCollection GetStreams(Guid key);
I need to implement this with a REST interface.
I created a new interface, IRestService as below
[WebInvoke(
Method = "GET",
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "/bitpool/{poolKey}/streams")]
BitStreamCollection GetBitStreams(string poolKey);
and it works ok (I can test it from the browser address bar and all is fine)
Now I want to implement also the Upload method, but I'm not sure how to do it
I tried with
[WebInvoke(
Method = "POST",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "/stream/{streamKey}/records/{values}")]
bool UploadStream(string streamKey, List<StreamRecordEntity> values);
But when I try to access the service in browser it gives error
http://localhost:6767/RestServer.svc/
it gives an error:
Operation 'UploadBitStream' in contract 'IRestServerJson' has a path variable named 'values' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'.
I think for POST I cannot define such URL, but how should I do it?
Also, method RegisterStream should check if stream with key exists and if not, create it and return true, otherwise return false.
Should I define it as GET (since it must return result) or as PUT or POST?
Thanks
Pass the values in the body of the POST request, formatted in xml, not on the url. An easy way to test this is to use Fiddler.
Regarding RegisterStream, both POST and PUT can return information in the response body. You could use POST and return an appropriate HTTP status code depending on the action taken by the server: 201 Created if the resource is created, a different status code that makes sense in your application if the resource already exists.
The caller can determine whether the resource was created or already existed based on the HTTP status code returned, so the bool return value wouldn't be needed.
Side note: you can use the [WebGet(...)] instead of [WebInvoke(Method = "GET"...)].