File upload functionality and message contract usage - c#

i am new in WCF. once i was searching code for uploading file to web server by wcf. i found a code which uses message contract for file details. i just do not understand why people use message contract. according to that situation the coder can use data contract only instead of message contract....so why they used message contract is not clear.
here is the link of source code for file upload by wcf. just have a look and tell me can we use data contract for file information instead of message contract. give some few good situation when one has to use message contract instead of data contract. thanks
These are the link
http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP
http://kjellsj.blogspot.in/2007/02/wcf-streaming-upload-files-over-http.html
http://stefanoricciardi.com/2009/08/28/file-transfer-with-wcp/

The main difference between Data contract and message contract are:
DataContracts are used to descibe the data types used by a service. This enables the types to be described in metadata to enable clients to interop with the service. DataContracts can be used to describe either parameters or return values. DataContracts are unnecessary if the service only uses simple types.
MessageContracts are used to explicitly describe the soap message format. It can be used to declare which headers various message elements go.
On Some critical issue, developer will also require control over the SOAP message format. In that case WCF provides Message Contract to customize the message as per requirement.
Very good link is here:
http://izlooite.blogspot.co.il/2010/01/wcf-why-use-messagecontract-when.html
Can i use datacontracts in WCF for streaming

Related

Azure Service Bus Message deserialize to an unknown type at runtime in subscriptions

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.

MassTransit Custom MessageType Name

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.

Implementing a SOAP web service

I have a WSDL definition for a SOAP service and I have successfully generated *.cs file from it using SvcUtil.
Implementing client is quite straightforward - I just need to call the necessary functions from the generated *.cs and that's it.
Implementing server seems more complicated. As I understand I need to implement an interface from the generated *.cs and then use some magic to turn it into the web server.
But I don't need a new web server, I already have a web server written in C# which already has many functionality unrelated to the SOAP service that I need to implement. I don't want to create another web server but I want my SOAP service to be just a part of my existing application (server), that is my server can answer e.g. requests http://example.com/request1, http://example.com/request2 etc. and I want this SOAP service to be just http://example.com/request3.
Since HTTP is already handled by my server I don't need .NET to handle it for me, basically my server can accept client connections and call the necessary handler based on the URL. I have a handler for SOAP request which looks approximately like this:
MyResponse HandleSOAPRequest(MyRequest request)
{
// 1. parse soap message from request.body
// 2. process it
// 3. generate response, serialize it in SOAP format and return it
}
The question is - can I rely on WSDL definition and .NET libraries to do it?
Currently I'm parsing SOAP request using XDocument and manually extract fields from it and serialize using simple string concatenation. Using .NET built-in functions to serialize or parse XML doesn't work. That is if I try to serialize response from an object of the class defined in the generated *.cs file then produced XML is different from what is expected by the protocol, similarly, if I try to parse request as an object of the class defined in the generated *.cs file I get error because XML parser expects different format. This applies to both the SoapFormatter and XmlSerializer.
Since .NET can implement client this means that everything that is necessary to parse and serialize SOAP messages is already implemented, I just need to figure out a way how to use this functionality.
The documentation for ServiceModel wasn't very helpful.
The easiest way would be to start the service via the ServiceHost:
ServiceHost host = new ServiceHost(typeof(YourService));
host.Open();
(I assumed here the configuration will come from the app.config and will not be setup in code like in the linked example below.)
How to: Expose a Contract to SOAP and Web Clients
The only drawback of this is that the application has to run with admin rights or otherwise a weird cofiguration is necessary.

WCF wsHttpBinding and XML Signatures

I have a WCF SOAP service that responds with licensing information. The client will save the SOAP response and load it every time the program loads, verifying the user is not passed the expiration date etc. Because of this, one of the requirements of the response is to have a signature such that the client can run the data through some encryption algorithm and check the result against the signature that was sent over to verify nothing has been changed about the file. This is nothing new, this is XML signing. However, the service is written with DataContractSerializer, so I can't just take the data, create an XML signature, and inject that straight into the SOAP response.
I know WsHttpBinding has some security features, the WS-Security page on MSDN describes the Ws binding protocol WRT to SOAP as having the ability to...
Identify the entity or entities involved with the message.
Prove that the entities have the correct group memberships.
Prove that the entities have the correct set of access rights.
Prove that the message has not changed.
but I can't find exactly how it does that last part. Looking at the SOAP response I get with WsHttpBinding on, I see CipherData and CipherValue, but researching that leads me to believe that's more to do with the actual message encryption, not content validation. I see something like ValidateResponse and ValidateResult, but those look like spaces for another endpoint to validate the information, and this product needs to work on devices not connected to the internet once the file is gotten from this service.
I know I could theoretically just put all the data into a variable and SHA256 it and tell my client to do the same process but that's dirty and very unstandardized. I feel like there should be an equivalent to XML Signatures for SOAP responses but I can't find anything through searching.
wsHttpBinding supports WS-Security, which includes digital signature in the SOAP message. To enable it, you need to use the ServiceContractAttribute.ProtectionLevel or the OperationContractAttribute.ProtectionLevel on the service contract definition, rather than doing it in the service configuration like you would expect
So, on your service contract:
[ServiceContract(ProtectionLevel=ProtectionLevel.EncryptAndSign)]
public interface IMyServiceThatIWantToEncyptAndSign
{
...
}
or
[ServiceContract(ProtectionLevel=ProtectionLevel.Sign)]
public interface IMyServiceThatIWantToSign
{
...
}
or
[OperationContract(ProtectionLevel=ProtectionLevel.EncryptAndSign)]
string MyOperationThatIWantToEncryptAndSignSign(string msg);
or
[OperationContract(ProtectionLevel=ProtectionLevel.Sign)]
string MyOperationThatIWantToSign(string msg);
The default value for this is ProtectionLevel.None which is why I think you are not seeing any signature.
The relevant MSDN links are here for the service contract:
http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.aspx
and here for the operation contract:
http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.aspx

WCF proxy generated from WSDL, proxy method returns null

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.

Categories

Resources