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.
Related
I am looking at the new api that came out 2 weeks ago. It seems like
ReqDTO : IReturn<List<ResDTO>> { //... }
The "IReturn" bit seems to be optional? The DTOs in RazorRockstars demo project works without it.
This is a new addition in ServiceStack's New API which allows you to document the expected Response Type that the Request DTO will return, e.g. with
ReqDTO : IReturn<List<ResDTO>> { ... }
Which lets you call using any of the C# Service Clients with:
List<ResDTO> response = client.Get(new ReqDto());
If you didn't have the IReturn marker your client call would have to look like:
List<ResDTO> response = client.Get<List<ResDTO>>(new ReqDto());
Which is something the client/consumer of your service needs to know about. If you had the marker on the DTO the response type is already known.
The IReturn<> marker is also used to determine the Response DTO that's used in the HTTP Responses in ServiceStack's /metadata pages.
As far as I know, this is just a convenient way of defining your request/response DTOs.
You're free to use it, or not.
In the case where you define your DTOs in a portable class library, you won't be able to use IReturn. Perhaps IReturn should be defined in a PCL in ServiceStack. Just a thought.
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'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
I have created a SoapExtension class to capture the soap request and response from specific web service calls. In order to put this SoapExtension into effect, I have to add an attribute to the method in the generated proxy client.
For example, I've added the AuditSoapCapture attribute to this method:
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://blahblah.com/webservices/AddressSearch", RequestNamespace = "http://blahblah.com/webservices/", ResponseNamespace = "http://blahblah.com/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[blahblah.TriadLite.Core.AuditSoapCapture]
public System.Data.DataSet AddressSearch(string HouseNumber, string StreetName, string ZipCode) {
object[] results = this.Invoke("AddressSearch", new object[] {
HouseNumber,
StreetName,
ZipCode});
return ((System.Data.DataSet)(results[0]));
}
I am looking for a way to add this attribute to specific methods without modifying the generated client proxy, as they will get lost when we regenerate. Can I do this in a another partial class or interface or some other way?
Thanks!
Unfortunately, you'll need to modify the proxy code. The other possibilities you mention will not work - a parial class will not overwrite existing functionality, and there is no way that I'm aware of getting an interface to do what you need (compounded by the fact that there is no way to even let the proxy generator know that you intend to implement an interface).
Something that I've done in the past, in a situation where you have access to the source of the webservice, is to write a little app that will parse the code (as text) in the .asmx.cs file of the webservice to extract the names of all the methods that are tagged with [WebMethod]. Then the app "fixes up" the References.cs by inserting appropriate attributes onto the proxied methods, based on some settings file or somesuch. This works well because the naming conventions in the proxy map very neatly to the method names in the original service.
I may just end up injecting my SoapExtension by putting it into the Web.config. This will cause it to be run on every WS call without a client proxy method attribute. Then, I will modify the SoapExtension to look up the called WS method name on a list, and if it is on the list, then do the rest of the SoapExtension logic. I figure the hit on the list in this small volume application isn't going to kill performance.
6 years ago this was posted... So not sure if this will help anyone at this point.
I ran into something similar with a call to an old SOAP web service that had a dynamically generated proxy class that we didn't want to modify as it was auto-generated from the wsdl by the project. In order to solve this problem here is what we did.
The proxy class generated by wsdl.exe is a partial class. We extended this class like so to add a property with the information we wanted to access in the soapextension. You can add as many properties as you want...
partial class mysoapwebservice
{
public string myproperty{ get; set; }
}
in the web.config we registered the soap extension globaly on the project
<webServices>
<soapExtensionTypes>
<add type="MySoapExtension" priority="1" group="Low"/>
</soapExtensionTypes>
</webServices>
In the code were we created the web service object 'mysoapwebservice' we set the value of the property we needed.
In the soapextension you can get a reference to the web service that was called as well as the values. You can also determine the method call.
`
public class MySoapExtension: SoapExtension
{
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
{
// web service client object
var webserviceobject= ((SoapClientMessage)message).Client;
// method from web service that was called
var calledMethod = (SoapClientMessage)message).MethodInfo;
// checked the client type of webserviceobject and
//added method / property specific logic here
}
}
}
// other soap extension code
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class CriptoExtensionAttribute : SoapExtensionAttribute
[CriptoExtension]
public partial class MainService{
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.