Tuesday, April 06, 2010

WCF Service For HTTP Get Request

In my last article I talked about how you can put a hook by implementing some interface of WCF. In this article I am talking about how you can define one method which will act as a controller and control all the income request.

In WCF when you define the ServiceContract you can also define what will be the action which will trigger that particular method.So basically I am talking about OperationContract where you can define the Action and ReplyAction attributes.

So we will see a very small example how we can handle the Http get request.

I have one Service Contract where I have define one method call Process which take message as a input parameter and the operation contract of this method define Action and ReplyAction as * it a wild card character which will invoke this method for all the request.

[OperationContract(Action="*", ReplyAction="*")]
void Process(Message msg);

When you implements this service contract into you actual class message parameter of this class will give you the income request object and you can extract out different information from this message object.

public void Process(Message request)
{
HttpRequestMessageProperty rp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
if (rp.Method.Equals("Get", StringComparison.InvariantCultureIgnoreCase))
HttpContext.Current.Response.Write(Get(request));
}
so you can see In this code I am checking the request whether it's Get or POST and do my action on the basis of that.

In this case I don't need to create any class inherited by IServiceBehaviour or some other interface this method will be called for all hit whether some body is hitting by creating a proxy of your service which is POST or just directly typing into URL which is GET.

Tuesday, March 30, 2010

Property Handling in WCF

In this article I am talking about how you can define OperationContract for your properties of Service Contract.

As you know you can't put [OperationContract] attribute on your Properties it will give you an compile time error because this attribute is only valid for method declaration.

In this case you can define this attribute on you get and set of property and these get and set will treat as normal method so for example I am define one property called CustomerId I have to define like this.

int CustomerId
{

[OperationContract]
get;
[OperationContract]
set;
}
After doing this you will get set_CustomerId and get_CustomerId as normal method in your WCF proxy class.

Monday, March 29, 2010

Hooking Your class into WCF

In this article I am talking about how you can intercept the SOAP Calling and handling of non existences message of service contract. In this example Add is a dummy method which is not a part of service contract I just mimic the web service request and response handling.

You can create you class which will be inherited from IServiceBehavior and then use ApplyDispatchBehavior of this interface to set you hook as message inspector.

void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
//ApplyDispatchBehavior

foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
if (channelDispatcher != null)
{
foreach (EndpointDispatcher endpoint in channelDispatcher.Endpoints)
{
//endpoint.DispatchRuntime.OperationSelector = this;
endpoint.DispatchRuntime.MessageInspectors.Add(new PrintMessageInterceptor());
}
}
}
}


In this method PrintMessageInterceptor is an instance of another class which is inherited from IDispatchMessageInspector which provide us two method AfterReceiveRequest and BeforeSendReply

In AfterReceiveRequest you can take out body of SOAP and then you can set you parameter and in BeforeSendReply you can check this parameter and modified the response message.

public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request,
IClientChannel channel, InstanceContext instanceContext)
{

XmlNodeReader reader;
XmlDocument document = new XmlDocument();
document.Load(request.GetReaderAtBodyContents());
//Get the body element operation
string bodyElement = document.DocumentElement.LocalName;
switch(bodyElement)
{
case "Add" :
strAction = Action.Add;
break;
}
return null;
}


public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply,
object correlationState)
{
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
//Get the body element operation
XmlDocument document;
string bodyElement;

document = new XmlDocument();
document.Load(reply.GetReaderAtBodyContents());
//Get the body element operation
bodyElement = document.DocumentElement.LocalName;
switch (strAction.ToString())
{
case "Add":
Add(document);
reply = Message.CreateMessage(reply.Version, null, localReader);
break;
}
}

Now in this case Add method will take the body of the SOAP and modified that one and send the same body to the calling method.localReader is of XmlNodeReader which I have set to create the response message.

private void Add(XmlDocument passedValue)
{

if (passedValue.DocumentElement.Name.Equals("Add"))
{
using (var passedReader = XmlReader.Create(new System.IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(passedValue.InnerXml))))
//using (var writer = XmlWriter.Create(new System.IO.MemoryStream(System.Text.Encoding.ASCII.GetBytes(reader.ReadInnerXml())), settings))
{
while (passedReader.Read())
{
switch (passedReader.NodeType)
{
case XmlNodeType.Element:
break;

case XmlNodeType.Text:
Sum += Convert.ToInt32(passedReader.Value);
break;
}
}
}
newNode = passedValue.CreateElement("AddResponse", "http://tempuri.org/");
childNode = passedValue.CreateElement("AddResult", "http://tempuri.org/");
childNode.InnerText = Sum.ToString();
newNode.AppendChild(childNode);
passedValue.RemoveChild(passedValue.DocumentElement);
passedValue.InnerXml = (newNode.OuterXml);

}

Let me know your feedback.

Thursday, March 11, 2010

How to Run the WCF Service on local system

For making WCF service to work you need to add the services end point and you can also define the binding with different transporter for e.g net.tcp, http
Below is the code how you can define these bindings.

1.First you need to define the ServiceHost which will take type of your class which inherited the service contract.

using System.ServiceModel;
ServiceHost selfHost = new ServiceHost(typeof("Type of your class"), baseAddress);

2. Second you need to Add service point to this service host which will take type of you service contract and also the name of class which inherited this service contract.

selfHost.AddServiceEndpoint(
typeof(IUploadInterface),
new WSHttpBinding(),
"UploadClass");
3. You need to create the service meta behaviour and need to set HttpGetEnable to true so that it will enabled Http request on your service and you also need to define the url of your service which include the port number and the class name.

ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.HttpGetUrl = new Uri("http://localhost:8000/UploadClass");
selfHost.Description.Behaviors.Add(smb);

4. You need to open the service host
selfHost.Open();

Monday, March 08, 2010

XML with Linq


System.Xml.Linq namespace provide good way of working with XML you don't need to create a DOM object you can smiply create a object of XElement object and then define you XML and after defining the complete XML you can save this XML by smiply calling Save method of XElement object.

For e.g
If I want to generate one XML through XML.Linq first I need to create an object of XElement for root tag and inside that define the nested object of XElement which will become child elements of the root XElement.

xlElement = new XElement("configuration",
new XElement("configSections",
new XElement("section", new XAttribute("name", "log4net"),
new XAttribute("type", "log4net.Config.Log4 NetConfigurationSectionHandler, log4net"))),
new XElement("log4net", new XAttribute("debug", "true")),
new XElement("appender", new XAttribute ("name", "AppTraceFileAppender"), new XAttribute("type", "log4net.Appender.FileAppender")),
new XElement("param", new XAttribute("name", "File"), new XAttribute
("value", "")));


In this case it will create an XML object with root element as Configuration and inside that we have neseted childs,In above senario we have define attribute of an elements with the help of XAttribute calss.

After defining this simply call xlElement.Save(filePath);

Thursday, March 04, 2010

Adding file as Link

Whenever you have files/dll which is going to refer from more that one project of a common solution you can put that in common location and add that dll/files as link. Benefit of adding a file as a link is one copy of that dll/file will be shared by all the project and whenever you change something in shared dll/file it will reflect in all the link refrence.

How to Add dll/file as link.

1. Right click on project choose add existing item
2. file add dialog box apprear.
3. Choose the file and click on combobox showing in Add button of file add dialog box.
4. Choose add as a link.

Wednesday, March 03, 2010

Using XPathDocument in place of DataSet

//Create object of XPathDocument
XPathDocument docNav = new XPathDocument(strPath);
//Create the XPathNavigator
XPathNavigator nav = docNav.CreateNavigator();
//Set the pointer at ShoppingRule node
expr = nav.Compile("/Rule/ShoppingRule");
//Get all the ShoppingRule node from the XML.
XPathNodeIterator parentIterator = nav.Select(expr);
//Treverse on all the shoppingRules node
while(parentIterator.MoveNext()
{
if (parentIterator.Current.HasChildren)
{
//Move to the first child node of the ShoppingRules
parentIterator.Current.MoveToChild(XPathNodeType.Element);
strTransactionCode = parentIterator.Current.Value;
}
//Get all the childs of ShoppingRules node
XPathNodeIterator children = childNode.SelectChildren(XPathNodeType.Element);
//Traverse on all the child node of the ShoppingRules nodes.
while (children.MoveNext())
{
}
}