Accepting form fields via HTTP Post in WCF - wcf

I need to accept form data to a WCF-based service. Here's the interface:
[OperationContract]
[WebInvoke(UriTemplate = "lead/inff",
BodyStyle = WebMessageBodyStyle.WrappedRequest)]
int Inff(Stream input);
Here's the implementation (sample - no error handling and other safeguards):
public int Inff(Stream input)
{
StreamReader sr = new StreamReader(input);
string s = sr.ReadToEnd();
sr.Dispose();
NameValueCollection qs = HttpUtility.ParseQueryString(s);
Debug.WriteLine(qs["field1"]);
Debug.WriteLine(qs["field2"]);
return 0;
}
Assuming WCF, is there a better way to accomplish this besides parsing the incoming stream?

I remember speaking to you about this at DevLink.
Since you have to support form fields the mechanics of getting those (what you are currently doing) don't change.
Something that might be helpful, especially if you want to reuse your service for new applications that don't require the form fields is to create a channel that deconstructs your stream and repackages it to XML/JSON/SOAP/Whatever and have your form clients communicate with the service through that while clients that don't use forms can use another channel stack. Just an idea...
Hope that helps. If you need help with the channel feel free to let me know.

You can serialize your form fields with jquery and package it as json request to wcf service.

Related

WCF and Data Transfer Object

I am stuck on this simple question. In my console application, I want to consume a wcf service. So I add the web reference to the project and call it. That is it.
But why I saw some examples especially using RESTSHARP, they never add web reference. They just use so called "DTO" to return object by the service and consume it.
I hope somebody can clarify the concepts for me. Is DTO used inside WCF?
sample:
private static List<ApplicationDTO> features;
RestClient client = new RestClient("http://" + baseUrl + "/FacilityData.svc");
var request = new RestRequest(Method.GET);
request.Resource = "/GetFeatures";
request.Parameters.Clear();
request.AddParameter("Id", 888);
var response = client.Execute(request);
features = JsonConvert.DeserializeObject<List<ApplicationDTO>>(response.Content);
from this post:
For REST service, it provides a generic way for WCF service consuming
which doesn't rely on the SOAP. That's why we no longer need "Add
ServiceReference..." for consuming it. REST service operations can be
accessed through standard HTTP GET/POST request, so any webrequest
enabled client can consume it. For example, you can use HttpWebRequest
to invoke a REST operation and use LINQ to XML to load and extract
values from the response XML data. It's very flexible.
DTO, usually used for Data Transfer Object - is nothing more then entity you want to pass as parameter / receive as a result.
In your example, ApplicationDTO - is probably some entity to hold Data about Application Feature object (Name, Type, ...)

How to allow all Operations and Namespaces

I'm new to WCF, but not new to C# and .Net. and am using Visual Studio 2008 and .Net 3.5.
I'm trying to build a Web Service that can receive any inbound Request XML and any namespaces. It would behave like a transparent receiver and simply intake the inbound request XML.
Once I get the request I'm going to pass it to some custom .Net C# Project to invoke a MQPUT to IBM MQ Series.
Right now I have the WCF Web Service Application receiving a generic inbound operation called RunTest(). I consume the WSDL into SoapUI, build a sample request and breakpoint and it works. But, when I try to pass our company request XML it doesn't land on the breakpoint.
Here is the ServiceContract and Operation:
[ServiceContract(Name="IService1",Namespace="cfg-env=http://www.co.com/schemas/cfg- env/")]
//[ServiceContract]
public interface IService1
{
[OperationContract]
void RunTest();
[OperationContract]
void CFX();
Here is the Method for the Operation:
public void RunTest()
{ <<<it does break here using the request from the WSDL
string serviceName;
string queueManager;
string queue;
string requestMessage;
//Capture the Service Name
serviceName = "";
//Save the QueueManager
queueManager = "";
//Save the Request Queue
queue = "";
//Save the Message
requestMessage = "";
//Call MQ Put
Engine eng = new Engine();
try
{
eng.Put(serviceName, queue, requestMessage, queueManager);
}
The main thing I need to do is receive the inbound XML, interogate it for a few pieces of information and call this Method to do the MQPUT function on MQ.
The inbound namespace will look like the above but I'd like to ensure I can receive and interogate any XPATH that may be namespace qualified. If I have to I can work with the cfg-env namespace prefix exclusively as our services do use that as a standard.
What are my key hurdles in doing this in VS 2008 WCF? If you have any links please pass them along if you can.
I believe you specify the name property on the OperationContract attribute as "*" to accept all requests. To make the parameter itself schema agnostic, it should be of type System.ServiceModel.Channels.Message.
What you are building is a "WCF router".
Included in the latest .NET release is a configurable Routing Service.
If the routing service doesn't meet your needs, building your own router is possible but can get really complicated when secure messages are a requirement. This set of MSDN articles is the best resource. They answer your question of how to have a service accept any message, and then continue on into addressing and security issues.
Building a WCF Router, Part 1
Building a WCF Router, Part 2

passing Dictionary in WCF service [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to serialize Dictionary<string, string> through WCF?
How to pass a dictionary in a method in WCf ...
I'm doing this
public void SendData(Dictionary<string, string > data)
{
foreach (KeyValuePair<string, string> item in data)
{
Console.WriteLine("{0} : {1}", item.Key, item.Value);
}
}
When I access it as 192.X.X.X//Akhil/service.svc/SendData?data={}
here What/How should I pass arguments in data...some example please.
Generate your proxy (Say, "TestProxy") then do:
TestProxy.YourServiceClient client = new TestProxy.YourServiceClient();
Dictionary<string, string> testDict = new Dictionary<string, string>();
testDict.Add("test", "test1");
client.SendData(testDict);
WCF will serialize your Dictionary with no problem. The problem here is that you are trying to access your WCF service as if you exposed it as a REST Service through an HTTP Get request. I'm pretty sure based on your question, you aren't exposing this as a REST service. If you want to be able to do Get Requests, then google .Net WCF REST.
*Note: you might also want to look into the Request/Response SOA pattern, it's going to save a bunch of trouble down the road.
Update:
Here are some links that might point you in the right direction, you'll probably want to expose your WCF service as a JSON endpoint.
JSON / REST Link
Search Dictionary in this LINK to get some details on alternatives and gotchas in WCF JSON.
Hope these help. I have never done an Iphone app so I don't have any source code to give you.

How to write a WCF REST service that image data can be POSTed to?

I've been looking for examples for how to write a WCF REST service that allows image data to be POSTed to. I may be missing something (I generally am), but does anyone know how to do it? Is it as simple as getting the HTTP request from inside your WCF REST service, and extracting the binary data? If so, is there an example as to how to do that? Would I be able to do that using WebOperationContext.IncomingRequest?
Or, is there a way to do something like this...
[ServiceContract]
public interface IImage
{
[OperationContract]
[WebInvoke(
Method = "POST",
UriTemplate = "/images")]
void StoreImage(byte[] imageData);
}
Any ideas?
This post is more or less the answer I was looking for.

WCF Chunking / Streaming

I'm using WCF and want to upload a large file from the client to the server. I have investigated and decided to follow the chunking approach outlined at http://msdn.microsoft.com/en-us/library/aa717050.aspx
However, this approach (just like streaming) restricts the contract to limited method signitures:
[OperationContract(IsOneWay=true)]
[ChunkingBehavior(ChunkingAppliesTo.InMessage)]
void UploadStream(Stream stream);
The sample uses the rather convenient example of uploading a file from a fixed path and saving it to a fixed path on the server. Therefore, my question is how do I pass additional parameters to specify things like filename, filepath etc.
eg. I would like something like:
[OperationContract(IsOneWay=true)]
[ChunkingBehavior(ChunkingAppliesTo.InMessage)]
void UploadStream(Stream stream, String filePath);
Thanks in advance,
Mark.
This article explains how to use the MessageHeader attribute to force things to be passed in the header, and therefore not count as a parameter. So, instead of passing a stream and other meta data, create a class that has the attribute MessageContract and mark all of the meta data as a MessageHeader. Then, mark the stream as a MessageBodyMember (which the article incorrect calls "MessageBody"). Have your UploadStream method take a single parameter whose type is that of the MessageContract class you've just created. I've done this successfully, but I haven't done it in tandem with chunking. Good luck.
You could make your service session-ful and have an initialization method in the contract with the IsInitiating property set to true. Something like:
[OperationContract(IsInitiating = true)]
void InitializeUploadService(string filename);
[OperationContract(IsOneWay = true, IsInitiating = false)]
[ChunkingBehavior(ChunkingAppliesTo.InMessage)]
void UploadStream(Stream stream);
I have never tried it with streaming services but it should basically make WCF enforce that InitializeUploadService is always called before UploadStream.
More documentation can be found here:
http://msdn.microsoft.com/en-us/library/system.servicemodel.description.operationdescription.isinitiating.aspx
I would look at MessageContracts and add those values as message headers to your object. This should allow you to pass the stream and any values related to the stream as message headers.
Setting up the maxItemsInObjectGraph in the Client side and Server side worked for me.
(Dont forget the client side.) http://social.msdn.microsoft.com/Forums/en/wcf/thread/0af69654-2d89-44f3-857a-583b57844ca5