Sharing the same message contract for two actions - c#

My services are supposed to parse a SOAP request for an action ILogging/LogMessage which has 'log-entry' as the root element inside the SOAP body. For that, I have a method LogMessage that expects parameter of type LogMessageRequest.
LogMessageRequest has the MessageContract attribute set with WrapperName as log-entry:
[MessageContract(WrapperName = "log-entry")]
public class LogMessageRequest
{
...
}
I am also expecting another SOAP request for an action ILogging/LogException with 'log-entry' as root element in the SOAP body. For this, there's a method LogException and a param of type LogExceptionRequest.
The difference between both the SOAP actions is that a child element 'message' inside 'log-entry' is different (for LogMessage, 'message' is a string and for exception, it's a complex entity).
The issue:
Since both LogMessageRequest and LogExceptionRequest have the same wrapper names (log-entry), I'm getting an exception originating from LogException saying "log-entry has already been exported by LogMessage".
I tried using the same request class for both and have the 'message' of type object. But that refuses to work.
Any pointers? (there's no scope of changing the SOAP request by the way).

While there might be a way to match the different schemas with a common interface, I suggest a more prudent approach: build an adapter over one of the service interfaces to match the interface of the other.
This way, the ugliness is isolated and the application will only have to work with only one service interface.

I don't believe you can implement this using MessageContract/data contract from your description. You might be able to do it with XmlSerializer attributes, but it sounds like you will need to use the Message class in the operation contract and peek at the message xml to figure out which one it is. Can you post the relevant bits of the WSDL/SOAP definitions?

Related

How to identify model property descriptiion (lke name, type) and fault exception details from wsdl using c#

I would much appreciate any suggestion on the following requirement.
Problem statement: I need to parse a wsdl file to get properties of the data contract(model property name and type etc) as well as fault exception details. The wsdl of a service will contain details of various operations. I will pass the operation name and in return list of properties of the following data contract. If there are nested object graph , we need to grab those info as well. Kind of recursive call. another hand we need to get the fault exceptions for the passed in operation. So two separate methods basically.

Skip Serializing properties generically during Web API processing

During WebAPI Response processing, we need to log the response/request body and headers with the security properties being skipped. With Newtonsoft Json, Since the actual response should contain the properties, "Ignore" attribute cannot be placed. We have implemented general filter to handle all Web API Methods that takes excluded property key names as list. Following are approaches tried.
Doing Jobject.Parse and traversing through JTokens and excluding.
Using JsonTextReader and applying conditions while reading.
Both are taking milli seconds time which was not acceptable because its just for logging.
Is there any Optimal way to acheive this?
Create a base class without the security property, use the base class for logging the data and the child one to have everything.
Or create an interface from your class and create a new class with Ignore attribute which you use to log the result.

stuck up to call the WCF object

This is quite embarrassing ,tried to find the solution by myself but real lack of knowledge i couldn't able to ,so am posting my question here.
my wcf service return this value when i call my service
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetProcessLocationsResponse xmlns="http://tempuri.org/">
<GetProcessLocationsResult >
<a:ProcessLocationData>
<a:Id>1</a:Id>
<a:Name>IL</a:Name>
</a:ProcessLocationData>
<a:ProcessLocationData>
<a:Id>2</a:Id>
<a:Name>MD</a:Name>
</a:ProcessLocationData>
<a:ProcessLocationData>
<a:Id>3</a:Id>
<a:Name>NY</a:Name>
</a:ProcessLocationData>
</GetProcessLocationsResult>
</GetProcessLocationsResponse>
</s:Body>
</s:Envelope>
in my service class i wrote this method
public Array GetProcessLocations()
{
return this.GetSoapServiceClient().GetProcessLocations().ToArray();
}
public List<ProcessLocationData> GetProcessLocationsOnlyName()
{
return this.GetSoapServiceClient().GetProcessLocations().ToList();
}
i call this service in my xyz.class like below
Array GetProcLocation= new GatewayService().GetProcessLocations();
this return whole object like ID and Name
but i was trying to get only the name by calling the "GetProcessLocationsOnlyName" method
i was trying to do like below
array ProcName= ProcessLocationData.Name
should return all the name in the service like (IL,MD,NY) in the array but i couldn't able
to see ProcessLocationData at all.
In another way i was trying to split the array(GetProcLocation) and get only the name and add in to new array ? is that make sense ?
Please some one guide me in to right path.thanks in advance.
I am a little confused about your question.
I do understand that you want to have 2 service methods, both of them returning an array of ProcessLocationData, one returning the list with id and name (GetProcessLocations) and one returning an array of ProcessLocationData with name only (GetProcessLocationsOnlyName).
And your problem is that the client proxy doesn't contain the GetProcessLocationsOnlyName method.
You should make sure that both methods are annotated with OperationContract, otherwise they won't be exposed by your service. You should have this attribute in either your service interface or in service directly. You can see that your service exposes both methods in either wsdl or using the WCF Test Client.
And then you must make sure your client proxy is up to date.
If your client proxy is was generated using visual studio, you should try to update your service reference
If your client proxy is generated using svcutil you must regenerate it manually
Related to your comment, if you want to return only the name field you have the following options.
you can use the same DataContract, that means returning a list of ProcessLocationData and returning an empty Id for each object
you can create a new DataContract that has only one property, Name, and return a list of these objects
My advice is to use the same DataContract and to load only the needed data in the data access method. For example, make a new method GetProcessLocationsName(), that will create your list of ProcessLocationData with only their Name loaded.

Get operation name in Message Inspector?

Im using the IClientMessageInspector to log in/out messages but the problem is that I canĀ“t find how to get the operation name from AfterReceivedReply and BeforeSendRequest.
I have tested the following :
if ((action = reply.Headers.Action.Split('/').LastOrDefault()) != null)
{
callInformation.Action = action;
callInformation.Address = reply.Headers.Action.Replace(action, "");
}
This works fine in BeforeSendRequest but in the AfterReveivedReply it returns something different, often with the "Response" on the end?
How do I only get the operation name in those methods?
Say, that my operation is named MyOperation and a OperationContract attribute states the action = "MyOpeation" (wrong spelling). This result of this is that MyOpeation will be extracted in BeforeSendRequest while the AfterReceiveReply will return MyOperationResponse.
So the BeforeSendRequest will extract the stated action in the attribute and the AfterReceiveReply will extract the real operation name but with the add of "Response" on the end?
Its important to be able to match the in/out messages and the only way of doing this as I see it is to match the operation names but if that is not possible then I do not see a good solution to this?
I have seen solution when using OperationContext.Current.IncomingMessageHeaders.Action but the OperationContect.Current is null when doing this on the client side.
From your question I assume you want to match In/Out messages by any means - the framework provides for this:
In the implementation of IClientMessageInspector.BeforeSendRequest you can return a unique correlationState which in turn allows you to relate the reply message in your implementation of IClientMessageInspector.AfterReceiveReply since the Framework will call your implementation with it as the second parameter.
EDIT - as per comments below:
IF you really need to get the name of the operation/method called you could do this is by implementing IClientMessageFormatter.SerializeRequest OR IParameterInspector - this will allow you to to record which method with which parameters have been called and what Message object the framework created for it.

Mixing XML and JSON in RESTful WCF without separate methods

I have a RESTful WCF service that can return XML, JSON, or JSONP, depending on the arguments, e.g. /service.svc/stuff?format=xml or service.svc/stuff?format=json&callback=myCallback. To do this, I've created a custom Behavior, MethodEncoder and MethodEncoderFactory which handle wrapping the JSONP callback and chooses the writer based on the format argument. In my encoder's WriteMessage() method, I do something like
XmlWriter writer = IsXmlRequested() ? XmlDictionaryWriter.CreateTextWriter(stream) :
JsonReaderWriterFactory.CreateJsonWriter(stream)
message.WriteMessage(writer);
Then, I define my service methods as if they just return JSON but use my custom binding element:
[OperationContract, JSONPBehavior, WebGet(ResponseFormat = WebMessageFormat.Json,
UriTemplate = "stuff")
public List<Thing> GetStuff(){...}
And it almost works. When I ask for XML or JSON, I get something in the right format, but the XML isn't serialized as I expect. Here's what the XML looks like:
<root type="array">
<item type="object">
<FirstPropertyOnAThing>1</FirstPropertyOnAThing>
Whereas if I were to just set the WebMessageFormat to XML, I would get something like this:
<ArrayOfThings xmlns="...>
<Thing ...>
<FirstPropertyOnAThing>1</FirstPropertyOnAThing>
I definitely want the latter. I guess this is happening because the result is serialized to a dictionary when the Message object is created; my custom encoder is just deciding how to write that dictionary to the response stream. So it gets the encoding right, but not exactly the format, which has already been decided by the ResponseFormat.
First, is that right? If so, how can I fix this? For example, can I write my own WebMessageFormat? Or do I just have to give in and write separate methods (and URI templates) that have different ResponseFormat properties for /json/* and /xml/*?
Update: In .net 4, there's a WebOperationContext.Current.OutgoingResponse.Format property you can just set. I guess my issue boils down to: is there a way to accomplish that in .net 3.5?
Yes, there's a way to accomplish what you want in .NET 3.5, without writing separate methods.
This blog post deals with the situation you describe: varying the content-type of the response based in the incoming request. But, the post describes a slightly different approach to the solution.
In particular, the requester specifies the desired content type NOT in the request URL, but rather in the Accept header of the request.
The solution involves the use of a custom WebHttpBehavior that inspects the Accept header and formats the response appropriately. A very elegant solution, in my opinion. There's nothing you have to do in your business logic to get the adaptive formatting. Just attach the behaviour and it works.
Also check out the WCF REST Contrib library on CodePlex.

Categories

Resources