I'm trying to understand WCF, so my questions may be dumb. I believe I have a firm understanding of "GET" operations. I'm now working on some "POST" operations. My question is, can I write a WCF Service operation, with WebInvoke, that accepts multiple parameters? Or, when I POST data, will it only accept a single serialized parameter?
Thank you!
Yes, but your POST will have to be passed in using a common understanding of the data, aka a "data contract".
In WCF, the typical approach here is that you'd create a contract class (just an off-my-head example, not 100% working))
[DataContract(Namespace="http://yournamespace.com")]
public class MyContract
{
[DataMember(Order=1)]
public string MyData1 { get(); set{};}
[DataMember(order=2)]
public string MyData2 { get(); set{};}
}
Then you'd specify your WCF operation to accept that contract type as its parameter
[WebInvoke(method="POST")]
public string DoSomethingFromPost(MyContract postedData)
{
}
On your client, you'd serialize the data to an xml/json that matches your contract. Again, loose example:
<MyContract xmlns="http://yournamespace.com">
<MyData1>value</MyData1>
<MyData2>value</MyData2>
</MyContract>
When the contract matches, WCF will deserialze your POST into your contract object, at which point you can use it like any other class.
It seems like there is a bit of confusion between wcf (which is the name given to microsofts overall abstraction for network programming) and a specific protocol HTTP, that defines verbs like "POST" and "GET", that wcf will be using to communicate.
When you define a wcf service operation and attribute it with [WebInvoke] you are going to access to the service using REST over HTTP. See webinvoke for more detail, however the remarks sum it up well
The WebInvokeAttribute attribute is
applied to a service operation in
addition to the
OperationContractAttribute and
associates the operation with a
UriTemplate as well as an underlying
transport verb that represents an
invocation (for example, HTTP POST,
PUT, or DELETE). The
WebInvokeAttribute attribute is a
passive operation behavior (the
IOperationBehavior methods do nothing)
that adds metadata to the operation
description. Applying the
WebInvokeAttribute attribute to a
service operation has no effect unless
a behavior that looks for this
metadata in the operation description
(such as WebHttpBehavior) is added to
the service's behavior collection. The
WebInvokeAttribute determines what
HTTP method that a service operation
responds to. By default, all methods
that have the WebInvokeAttribute
applied respond to POST requests.
Also further down the article defines how to map values to your service contract. Something like..
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "Mod?x={x}&y={y}")]
long Mod(long x, long y);
EDIT: To make this a bit more informative for people new to the field.
an intro into REST without going into platform specifics.
and a how to set up a simple REST style wcf service using wcf
Related
For particular endpoints on my rest service I need to check a token, rather than doing this in each of those endpoints:
IncomingWebRequestContext woc = WebOperationContext.Current.IncomingRequest;
string tok = woc.Headers["tok"];
// validate etc
I'd like to put an attribute on the endpoint's method and do something like this:
[Restricted]
public Blog Get(string id)
And make the endpoint return custom responses, can I get headers and control method return values like this?
There is two ways to do this:
You can use an external tool like postsharp to implement aspect oriented programming. That means your attribute (plain metadata right now with standard .NET) becomes an Aspect and executes code. This is achieved through a post-compiler that weaves IL code. Cool stuff, but it costs money.
You write your own IEndpointBehavior to apply a dispatch behavior to your service endpoint, that in turn will add an IDispatchMessageInspector that can examine the message (for example for headers) and act accordingly for all messages to your endpoint. It could also check your endpoint actions, whether they have such an attribute set and act only on those that have it.
I am trying to port some existing WCF code to Web API. The code acts as an interface for ADO.NET Sync Services and consists of the following method signatures...
[OperationContract]
SyncContext ApplyChanges(SyncGroupMetadata groupMetadata, DataSet dataSet, SyncSession syncSession);
[OperationContract]
SyncContext GetChanges(SyncGroupMetadata groupMetadata, SyncSession syncSession);
[OperationContract]
SyncSchema GetSchema(string[] tableNames, SyncSession syncSession);
[OperationContract]
SyncServerInfo GetServerInfo(SyncSession syncSession);
I then want to be able to call these methods from other .NET client applications, some of which will be on Compact Framework!
I have seen lots of suggestions and examples around the web as to the use of JObject, custom model bindings (with an encapsulating object) and even FormDataCollection - but all of these examples have JavaScript clients and I cannot then see how I might code a .NET client in such a way as to be able to pass all of the parameters correctly and also get back the results I am looking for (for example, are these PUT/POST as I am passing parameters as input, or GET as I am expecting content in the result)?
Can anybody offer any assistance here?
I have yet to determine how I name the methods in such a way as they can be called (I have found the ActionName attribute and the Http* attributes along with a custom routing example that allows the action name to be passed as a part of the URL but again I cannot really see how these map correctly to the HttpClient Get/Put/Post/Delete methods and of course the HttpClient is not - as far as I know - available on Compact Framework).
I'm new to WCF, and googled on that problem, but to no avail. I basically have WCF client/server application, using basicHttpBinding with HTTPS enabled as a transport. What I would like is to be able to send various types of data (i.e. various messages) using just one generic method.
I have my data defined like this in the WCF service:
[DataContract]
public class Payment
{
[DataMember]
int Pay_id
{
get { return Payment_Id; }
set { Payment_Id = value; }
}
[DataMember]
...
etc.
I will also have classes other than Payment, f.e. Config, Update, Log. Is it possible in WCF to write and use just one [Operation Contract] method to send any of these custom class objects? Like
SendMessage (Payment p);
SendMessage (Config c);
Instead of writing new method for each new type of message, which is, I think, bad design choice (hard to extend)? As of now, it seems I can instantiate in WCF client proxy only types stated in the definition of [OperationContract] method, so if it's
SendMessage(GenericMessage message)
then I can't use
Payment payment = new Payment();
in the client, even if Payment is child class of GenericMessage.
Check this answer:
Naming Generic DataContracts in WCF
Also if you have method like:
SendMessage(ParentClass object)
you can use child class objects:
class ChildClass : ParentClass
just add to your wcf client something like this:
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type="Your.Namespace.ParentClass, Your.Assembly">
<knownType type="Your.Namespace.ChildClass, Your.Asembly"/>
</add>
</declaredTypes>
</dataContractSerializer>
</system.runtime.serialization>
Also, take a look at this article:
All About KnownTypes
If you have a scenario where you have a base class (GenericMessage in your example) you simply need to use the KnownType attribute on your operation contract like so:
[OperationContract]
[KnownType(typeof(Payment))]
[KnownType(typeof(Config))]
SendMessage(GenericMessage message);
You can also specify the known types in the configuration if you prefer. More information about that here: system.runtime.serialization config.
Not ideal but it works.
If you need to do completely different things (so an overload for each type would be more appropriate) you will have to put the Name on the OperationContract like so:
[OperationContract(Name ="SendPayment")]
SendMessage (Payment p);
[OperationContract(Name ="SendConfig")]
SendMessage (Config c);
Check in to Agatha, it's a request/response pattern. You have a request/response for each action. On the client, you add the request to the Dispatcher and then you can ask the response, or trigger the request.
I have been provided with a WSDL and have generated the proxy class based on this WSDL. Sorry cannot provide the WSDL due to security concerns. The method in the proxy class that I'd like to call is:
public HeaderValueType GetStatus(System.DateTime RequestorTrxTime, string RequestorContext, string MessageIdentifier, string ProfileNumber, string ProfileType, int RequestIndicator, out ResponseBodyType Response) {//Some code}
I am just wondering what the fields
string RequestorContext, string MessageIdentifier
Are meant to be because I have seen requestorContext being passed as an object like this:
OperationContext.Current.InstanceContext
But not as a string the same goes for MessageIdentifier.
I have not got access to the creators of this WSDL for a while and cant get access, so I thought if any one would have a clue.
Did you try calling the service just be passing some values into these fields? It looks more like naming coincidence. Check that linked XSDs from WSDL specify this as message content. Also check that WSDL contains policy assertion called CompositeDuplex and assertions for reliable messaging (it should be called RMAssertion). It it doesn't it is not WsDualHttpBinding where InstanceContext is used to expose callback contract and those parameters are only data related - meaning of those parameters must be described by service provider.
I am using a class in a C# ASP.NET project to allow a script written in some random scripting language to expose webservice methods dynamically - in other words, the script should be able to expose a method of any name with any signature (as long as it's valid, anyway) to the outside world through this SOAP interface (able to add and remove them at will, without needing a hard code change), and as such I need to be able to create a webservice class in C# while being able to dynamically add and remove methods at runtime.
Now, the best plan I've been able to come up with so far is (runtime) generating C# code to represent the webservice, using System.Reflection.Emit to compile it and then loading the assembly at runtime - all whenever the script adds or removes a method to/from the service (should not happen very often, mind).
Does anyone have a better idea than this?
You can modify WSDL by using SoapExtensionReflector class. From Kirk Evans Blog:
The SoapExtensionReflector is called when your type is being reflected over to provide the WSDL definition for your service. You can leverage this type to intercept the reflection call and modify the WSDL output.
The following example removes the first method out of 2 web service methods:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Multiply(int a, int b)
{
return a * b;
}
}
Create a class inherited from SoapExtensionReflector:
namespace TestWebservice
{
public class MyReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
if (description.PortTypes[0].Operations.Count == 2)
description.PortTypes[0].Operations.RemoveAt(0);
if (description.Messages.Count == 4)
{
description.Messages.RemoveAt(0);
description.Messages.RemoveAt(0);
}
foreach (Binding binding in description.Bindings)
{
if (binding.Operations.Count == 2)
binding.Operations.RemoveAt(0);
}
if (description.Types.Schemas[0].Items.Count == 4)
{
description.Types.Schemas[0].Items.RemoveAt(0);
description.Types.Schemas[0].Items.RemoveAt(0);
}
}
}
}
Add this to configuration/system.web section in web.config:
<webServices>
<soapExtensionReflectorTypes>
<add type="TestWebservice.MyReflector, TestWebservice" />
</soapExtensionReflectorTypes>
</webServices>
This should give you a starting point to dynamically removing methods from WSDL document. You would also need to throw NotImplementedException from web method if it is disabled.
Finally, you need to disable web service documentation produced by invoking .asmx endpoint without ?WSDL parameter. Set href attribute of wsdlHelpGenerator element to some URL. You can use DefaultWsdlHelpGenerator.aspx as a starting point for your own documentation handler. See question on web service documentation in XML Files, August 2002.
XMLRPC is fairly dead, isn't it?
SOAP implies a WSDL. How do you generate the WSDL dynamically?
You should look into using WCF. I expect you'll be able to take control of the process of generating the WSDL (and other metadata), yet you should also be able to take control of the processing of incoming messages. In particular, you will be able to examine the incoming messages to determine which script to run, what parameters to pass, etc.
You could create a WCF service with an input and output type of xs:any and handle the incoming request as a raw Message. That would allow you to accept any type of data and return any type of data. You would not use data contracts or static types, just a Message in and a Message out.
The problem with this approach is that generating a proxy from the WSDL really does nothing to help the consumer other than provide a wrapper to call the method. Providing data that is acceptable to the method would require hand-rolling data types, etc which is not that hard, it is just not as intuitive as a hard, typed contract.
Does it have to be a SOAP interface? That sounds like it might be more suitable to a route/REST/etc based API. You could do something in ASP.NET MVC (with a custom IController.Execute method that resolves the action to the method) pretty easily (in fact, I'm working on something very similar for some of my own code at the moment).
For example, you might have routes:
http://myserver/myservice/mymethod
that accepts (either in the body or args) the payload (parameters), and returns the result in the response. In non-MVC you should be able to do something similar with a wildcard-mapped generic handler.
Here is a suggestion:
Use WCF.
Create a WSDL from WCF using
information in the following blog
post:
http://www.pluralsight.com/community/blogs/kirillg/archive/2006/06/18/28380.aspx
You can then publish this information
using MEX.
The services are then open for your
clients to down load the meta data
and call the services.