We've been using MassTransit to act as a ServiceBus between our microservices.
We have on microservice in python and the other in .Net, in this case the python service publish a message like so bus.publish('x.y.z', message)
And of course the .Net side has a type of x.y.z, we want to change the namespace of x.y.x to a.b.c and still let the system to work without changing the python side.
I've tried cfg.Message<A.B.C>(x => x.SetEntityName("x.y.z"));
But it does not work, i can see the message in the queue and that someone reads it but no consumer is triggered.
Thanks
You need to look at the serialized message envelope (in JSON) to see how the message should be formatted (from Python, or any other language) and include the message types (using the type name formatting style required by MassTransit) in the envelope.
See this page in the documentation for details: http://masstransit-project.com/MassTransit/advanced/interoperability.html
It isn't just the entity name, that's for publishing and subscribing, but you need to look at the actual types in the envelope to be able to deserialize the message by a consumer.
Related
I have a 3rd party that is sending SOAP XML messages, as the HTTP message body (using HTTP Post). I need to write a program to accept / process these messages.
I have a specification document which contains 2 WSDL definitions - GetTransaction and CutOff.
I am trying to use Postman to send a test message. Content-Type is set to application/xml and the body is set to raw / XML.
I am using C#, ASP.Net (4.7.2), the code is in a Class Library. I have a Controller (ApiController) with:
[HttpPost]
[ValidationAttributes.RequireHttps]
public HttpResponseMessage Service(XmlDocument reqData)
but reqData is always null. I have tried different types instead of XmlDocument.
Now if probably a good time to say that this is all new to me - I've not created a program to accept SOAP messages before.
Should I be creating a WCF Service Application (rather than a .Net Framework Class Library)?
I've tried adding the WSDL "definitions" but they don't seem to produce anything useful. E.g. there is reference to a "GetTransaction" method, but it has a parameter list of about 150 items!?
I have found quite a lot of stuff via Google but it always seems to be about sending, rather than receiving, SOAP messages.
I appreciate that I have not really included much code to look at, but I feel like I've started from the wrong place. So, any basic guidance, suggestions or links to tutorial sites would be most welcome.
It's surprising, but I haven't yet found a sample where the Message received at a subscription could be of different types and the type needs to be known in order to deserialize its content with the right type. This is related but it doesn't contemplate that scenario
I have a publish-subscribers scenario. For the subscriber, to create the Message that can be published with the Azure Service Bus library as per https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions
I need to pass an array of bytes. It does not seem to have anything like custom metadata that I could use to specify the assembly type for the message or similar.
When the subscription receives the message, it must deserialize it, but I cannot know which type the specific message is in order to do a JsonConvert.DeserializeObject<TDestType>(Encoding.UTF8.GetString(message.Body))
Does anybody have any link or sample to achieve this? Or is a recommended practice to use a topic and a topic-subscription just with one type of messages? (I doubt it, but I know MassTransit for example creates a topic for each message behind the scenes..)
UPDATE 1: For now I'll use the ContentType property at the Message to store the EventType so that the suscriptor can use it to deserialize. But if feels "hacky" because this field is supposed to store the format type (json, xml, etc.)
It does not seem to have anything like custom metadata that I could use to specify the assembly type for the message or similar.
Azure Service Bus does offer headers/metadata available as UserProperties with every message. A topic can receive multiple message types and subscribers can peek which ones they'd be handling using subscriptions. A subscription can either be a simple one and leverage the message's ContentType property using correlation filters or have a more advanced SQL filters to provide a more advanced subscription mechanism.
For now I'll use the ContentType property at the Message to store the EventType so that the suscriptor can use it to deserialize. But if feels "hacky" because this field is supposed to store the format type (json, xml, etc.)
You can keep ContentType for serialization and use custom headers for filtering messages for subscribers. Or you can choose to store both in the custom headers. It's your call.
It's surprising, but I haven't yet found a sample where the Message received at a subscription could be of different types and the type needs to be known in order to deserialize its content with the right type.
This is what NServiceBus is doing with Azure Service Bus as a transport. A single receiver (endpoint) can handle different message types. The subscriber creates the filters that check for a custom header value to identify what type the message is.
I try to consume custome type message by my MassTransit service that subscribes to a azure service bus topic.
The messages has custom type and data of message stored is in custom properties. Here is an image of message from azure service bus explorer:
When trying to consume this I got :
MassTransit does not recognizes custom type unless it is in message header :/
Is there any way to configure endpoint so it can consume this type of message ?
Without a ContentType to differentiate the message serialization from the formats supported by MassTransit, there isn't currently a way to change it. And blank or null is not a valid content type, so that cannot be used to select it.
You would need to either add a content type, or change the message format at this point. You could submit an issue and if somebody gets around to making it possible to add an empty or unsupported serializer.
I'm relatively new to WCF services, so I apologize in advance if I'm missing the obvious. My business uses EasyPost as our shipping solution, and I've written a WCF service to handle the shipping status webhook calls from EasyPost, described here: https://www.easypost.com/docs/webhooks
Briefly, EasyPost sends an update object as JSON via POST. The problem is that it sends several different types of (non-configurable) updates to the same service method, and I'm finding it difficult to write a DataContract that encompasses all the possibilities. For example, if the argument it sends is a tracking number update, update.result.status will be a string value; if it's a batch status update, update.result.status will be an object. It's a bit of a mess.
I tried handling just the update type that I care about and returning a 400 status code on the others, but EasyPost interprets that as an outage and drops my service as a webhook endpoint.
From what I've read, it looks like I could abandon the comforts of a Data Contract in favor of using a System.ServiceModel.Channels.Message parameter as a catch-all, then parse the message manually. That doesn't strike me as a wise/clean solution, though.
I'd be grateful for any alternatives.
This is probably not the best way I could have handled this, but it works.
I have an HTTP Module that identifies whether the incoming request is for the proper service method, and if so, converts the ContentType header from "application/json" to "text/plain".
My service method accepts the content body as a System.IO.Stream parameter. By converting the stream to a byte[] and then to a string, I end up with the raw JSON string sent by EasyPost.
After that, it's just a matter of using Newtonsoft.Json to attempt to deserialize the JSON string into the expected Type.
Even if the deserialization fails, I can still log the data and send a success response to the caller. That's good enough for my purposes.
I've generated a WCF proxy from a WSDL file, but now when I call the proxy methods, they return null. I've enabled message logging, and can see that the messages from the server are correctly returned.
I've checked the answer of this question, but in my case at least the name of the returned object was the same in the message and in the WSDL. I still believe the problem has to do with the WSDL file, since it is not fetched the usual way through the "?wsdl" URL (it is a 3rd party webservice), but was given separately.
The return type of the method is just a string.
Has anyone else had similar problems, and what was the corresponding solution, if any? What is the most likely source of the problem?
Re-edit:
It is a RPC/Encoded web service. As written, I can see the SOAP response through message logging, but WCF seems not to be able to parse the information.
The message part of the response from the service looks like this:
<ns1:ServiceResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="the target namespace">
<ns1:ReturnValue xsi:type="xsd:string">
However, when inspecting the outgoing message from my client, it's different:
<ns1:ServiceRequest soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="the target namespace">
<RequestValue xsi:type="xsd:string" xmlns="">
So maybe the proxy expects the response to have the same namespace structure, and thus fails to parse it.
I've tried to change the type attribute to element in the wsdl message definitions, and adding some new elements in the types part of the wsdl definition, but then the svcutil chokes when generating the proxy, complaining that there's a clash between the inferred style document and specified style rpc.
From the WSDL specification, section 3.5:
If use is encoded, then each message part references an abstract type using the type attribute.
But then I'm a bit confused, since it doesn't seem to have been a problem in this question. What would be needed to make a similar change, with the restriction that it is a RPC/encoded service?
You'll have to give specifics about the Java service in order to resolve this. However, I suspect that the Java service is using message parts defined with the type attribute. These do not conform to WS-I Basic Profile 1 because there is ambiguity about which namespace should be used for the elements of the message. Some services will use the namespace of the type, while others will (correctly) use the namespace of the web service itself.
Using the element attribute removes the ambiguity, and is therefore preferred.
Please post a snippet of the WSDL containing one of the messages you're having trouble with. When you then compare the definition of the message with what you're seeing on the wire, and then compare that to the details of the proxy class that's meant to consume the message, I believe you'll see what I mean. The proxy class is expecting one namespace, but on the wire, a different namespace is being used.
We have had something similar when using a WCF client against a WSDL from a Java web service.
Our problem was that we could not see the data that was coming back from the service, it looked like the data was missing.
However, when we looked at what was going over the wire, the data was there.
The problem was that the WSDL had many types that inherited from other types. By default we would only see the information in the base type.
The solution was to cast the object to the type we expected, then all the fields appeared.