With migration to .NET 4.0, we got rid of a lot of WSE libraries, including the XopDocument class. What is the recommended class to replace XopDocument class, which represents an XOP package that is part of an MTOM-encoded SOAP message
Today I found your question when trying to understand how to add some attachment to SOAP message. In my requirements I have sample SOAP where <inc:Include href="cid:SOMEXML" xmlns:inc="http://www.w3.org/2004/08/xop/include"/> and I have to implement service which can consume such requests. I'm not experienced in WSE, so it's interesting for me for what purpose XopDocument was used there.
I resolved my issue using WCF configurations. I set messageEncoding="Mtom"
<basicHttpBinding>
<binding messageEncoding="Mtom" />
</basicHttpBinding>
and my DataContract has byte[] property.
[DataContract]
public class RootObject
{
[DataMember]
public byte[] SOMEXML { get; set; }
}
In SOAP request it looks like
<xop:Include href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634654497430144369" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
In general it is what I wanted to find.
Related
Hi it might be a duplicate but writing here since i was unable to fix the issue from the posts i have seen so far.
I am having DataContracts in my WCF services and on my client I want to consume my services as DataContract objects only, but when i am creating a Service reference my WCF services generating the message contracts for all the methods.
[ServiceContract]
public interface IUserService
{
[OperationContract]
UserVO GetUser(int Id);
}
[DataContract]
public Class UserVO
{
[DataMember]
public int Id{get;set;};
}
I have un-checked the "Always generate message contracts" and checked reuse types in referenced libraries where entities are available(Data Contract).
My reference.cs is having a message contract like
System.ServiceModel.MessageContractAttribute(WrapperName="GetUser", WrapperNamespace="http://tempuri.org/", IsWrapped=true)]
public partial class GetUserRequest {
}
EDIT 1:
my Reference.svcmap has client configuration like this
<ClientOptions>
<GenerateAsynchronousMethods>false</GenerateAsynchronousMethods>
<EnableDataBinding>true</EnableDataBinding>
<ExcludedTypes />
<ImportXmlTypes>false</ImportXmlTypes>
<GenerateInternalTypes>false</GenerateInternalTypes>
<GenerateMessageContracts>false</GenerateMessageContracts>
<NamespaceMappings />
<CollectionMappings>
<CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
</CollectionMappings>
<GenerateSerializableTypes>true</GenerateSerializableTypes>
<Serializer>Auto</Serializer>
<UseSerializerForFaults>true</UseSerializerForFaults>
<ReferenceAllAssemblies>true</ReferenceAllAssemblies>
<ReferencedAssemblies />
<ReferencedDataContractTypes />
<ServiceContractMappings />
EDIT 2:
I am trying to achieve something like below
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IUserService/GetUserDetails", ReplyAction="http://tempuri.org/IUserService/GetUserDetailsResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(UserServiceFaultContract), Action="http://tempuri.org/IUserService/GetUserDetailsUserServiceFaultContractFault", Name="UserServiceFaultContract", Namespace="http://schemas.datacontract.org/2004/07/mynamespace")]
MyEntities.UserVO GetUserDetails(int id);
By default, WCF uses the DataContractSerializer class to serialize data types. If your scenario requires the use of the XmlSerializer, instead, then you can manually switch to the XmlSerializer by applying the XmlSerializerFormatAttribute attribute to your service
The following MSDN article describes the process:
https://msdn.microsoft.com/en-us/library/ms733901(v=vs.110).aspx
Recommend careful consideration of the security notes before switching serialization classes.
Then share the assembly with the client! Put the service interface and all the DataContracts in one assembly. Then the client can use the channel channelfactory "pattern" to connect to the WCF service.
I have created a RESTful web service in C# and have deployed it to IIS. When I access the service HeadOffice.svc, I have the option to view the WSDL (HeadOffice.svc?wsdl). What I would like to do is have the option of viewing the WADL (e.g. HeadOffice.svc?wadl). Is this possible?
I have read around the place that the general opinion is that this is not the best practice. However, I need the WADL for a school assignment, so any help would be much appreciated.
Suppose you already know that WADL is not standard / not supported widely. And when somebody needs WADL, may be then better to use WS*/SOAP service + WSDL. So your task looks like very strange.
Anyway WADL is not supported "out of the box" in any REST implementation from Microsoft, neither WCF 3.5 Rest Starter Kit, neither WCF 4 REST, and ASP.NET WebAPI.
There are no reliable tools for WADL for .NET.
When your goal is to generate C# client code using WADL, believe me, you will spend more time as writing client code by yourself. And there are better solutions for that.
You can use new classes like HttpClient class or RestSharp or similar libraries to easily manually write your client and it will be even faster then googling for reliable WADL solution for .NET
Similar question on stackoverflow: Restful service in .NET with WADL instead of WSDL
UPDATE - Swagger:
For some years swagger has established itself as such format. You can either start writing service definition using swagger's YAML in the Swagger editor or let generate swagger from existing services, for .NET using Swashbuckle library. The second is something we had with WSDL, and swagger editor let's you generate client and server boilerplates. Regardless you are generating your server or client or not fan of it, swagger is actually a very good contract exchange format for REST service, not ideal but good option.
Why Swagger4Wcf
•Manually writing yaml description for swagger and maintain it especially WCF services are boring.
•There is a nuget package called Swagger4WCF that automatically generates yaml description for swagger 2.0 for each interface matching attributes used by WCF (ServiceContract/OperationContract/WebGet/WebInvoke).
2. How Swagger Works in the Background
Swagger4WCF uses NuPack post build pattern to trigger at build time.
https://www.codeproject.com/Tips/1190360/How-to-setup-a-managed-postbuild-without-scripting
At build time, it will detect assemblies present in output directory, open them with mono.cecil (to reflect assemblies) to generate expected yaml description for swagger 2.0.
Swagger4WCF detects WebGet/WebInvoke to provide Verb/Method in serialization style in yaml.
Steps to implement Swagger in your application:
Install SwaggerWcf package
Configure WCF routes
We have to add the route in the Application_Start method inside Global.asax
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("v1/rest", new WebServiceHostFactory(), typeof(BookStore)));
RouteTable.Routes.Add(new ServiceRoute("api-docs", new WebServiceHostFactory(), typeof(SwaggerWcfEndpoint)));
}
Note: Edit Web.config and add the following (if it doesn't exist yet) inside the system.serviceModel block
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
Configure WCF response auto types (optional)
We have to add the following to Web.config. This will allow the WCF service to accept requests and send replies based on the Content-Type headers.
<behavior name="webHttpBehavior">
<webHttp defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
Decorate WCF services interfaces
For each method, we have to configure the WebInvoke or WebGet attribute, and add a SwaggerWcfPath attribute.
[SwaggerWcfPath("Get book", "Retrieve a book from the store using its id")]
[WebGet(UriTemplate = "/books/{id}", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Book ReadBook(string id);
Decorate WCF services class
• Add the SwaggerWcf and AspNetCompatibilityRequirements attributes to the class providing the base path for the service.
• For each method, add the SwaggerWcfTag to categorize the method and theSwaggerWcfResponse for each possible response from the service.
[SwaggerWcfTag("Books")]
[SwaggerWcfResponse(HttpStatusCode.OK, "Book found, value in the response body")]
[SwaggerWcfResponse(HttpStatusCode.NoContent, "No books", true)]
public Book[] ReadBooks()
{
}
Decorate data types used in WCF services
[DataContract]
[Description("Book with title, first publish date, author and language")]
[SwaggerWcfDefinition(ExternalDocsUrl = "http://en.wikipedia.org/wiki/Book", ExternalDocsDescription = "Description of a book")]
public class Book
{
[DataMember]
[Description("Book ID")]
public string Id { get; set; }
[DataMember]
[Description("Book Title")]
public string Title { get; set; }
[DataMember]
[Description("Book First Publish Date")]
public int FirstPublished { get; set; }
[DataMember]
[Description("Book Author")]
public Author Author { get; set; }
[DataMember]
[Description("Book Language")]
public Language Language { get; set; }
}
Reference:- https://github.com/abelsilva/swaggerwcf
That's it wcf for Swagger implemented.
Please free if you face any issue.
Thanks,
Abhi
I'm trying to write a .Net client to a vendor's SOAP Service, but I'm having trouble getting the parameters to the SOAP messages to serialise to a form that the service recognises.
Using wsdl.exe I generated a service proxy class which works fine in itself. However, one of the messages takes an argument which is an array of key/value pairs - this is the bit I'm having problems with.
The WSDL for the message is:
<message name='Execute'>
<part name='ContextHandle' type='xsd:string'/>
<part name='ScriptLanguage' type='xsd:string'/>
<part name='Script' type='xsd:string'/>
<part name='Params' type='xsd:anyType'/>
</message>
The service proxy class has this code:
[System.Web.Services.WebServiceBindingAttribute(Name="EngineSoapBinding", Namespace="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts/wsdl/")]
internal partial class Service : System.Web.Services.Protocols.SoapHttpClientProtocol {
....
[System.Web.Services.Protocols.SoapRpcMethodAttribute("http://www.smarteam.com/dev/ns/iplatform/embeddedscripts/action/Execute", RequestNamespace="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts", ResponseNamespace="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts", Use=SoapBindingUse.Literal)]
[return: System.Xml.Serialization.SoapElementAttribute("Result")]
public object Execute(string ContextHandle, string ScriptLanguage, string Script, object Params) {
object[] results = this.Invoke("Execute", new object[] {
ContextHandle,
ScriptLanguage,
Script,
Params});
return ((object)(results[0]));
}
....
}
In the vendor's documentation the Params argument should be an array of key/value pairs.
I've been able to capture network traffic from another working client to this service and got the following example of a message that the service recognises (SOAP envelope removed and formatted for clarity):
<STES:Execute xmlns:STES="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts" xmlns:sof="http://www.smarteam.com/dev/ns/SOF/2.0">
<ContextHandle>0019469#00228</ContextHandle>
<ScriptLanguage>javascript</ScriptLanguage>
<Script><![CDATA[Context.Result = Context.Params("Number");]]></Script>
<Params SOAP-ENC:arrayType="sof:DictionaryItem[2]">
<sof:DictionaryItem>
<key xsi:type="xsd:string">Number</key>
<value xsi:type="xsd:int">10</value>
</sof:DictionaryItem>
<sof:DictionaryItem>
<key xsi:type="xsd:string">Hello</key>
<value xsi:type="xsd:string">World</value>
</sof:DictionaryItem>
</Params>
</STES:Execute>
I've tried various data structures for the Params argument, but nothing I've tried gives anything close to this XML serialisation.
The closest I've been able to get is to write a DictionaryItem class which implements IXmlSerializable with the following WriteXml method:
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("key");
writer.WriteValue(Key);
writer.WriteEndElement();
writer.WriteStartElement("value");
writer.WriteValue(Value);
writer.WriteEndElement();
}
I then give the Params argument a List<DictionaryItem> which results in the following serialization on the wire.
<Execute xmlns="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts">
<ContextHandle xmlns="">0022541#00228</ContextHandle>
<ScriptLanguage xmlns="">javascript</ScriptLanguage>
<Script xmlns="">Context.Result = Context.Params("Number");</Script>
<Params xmlns="">
<DictionaryItem xmlns="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts">
<key>Number</key>
<value>10</value>
</DictionaryItem>
<DictionaryItem xmlns="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts">
<key>Hello</key>
<value>World</value>
</DictionaryItem>
</Params>
</Execute>
Can anyone point me in the right direction to get this working?
** Update **
It doesn't surprise me in the slightest that this vendor is using a deprecated message format. Their whole product is a mess, and I'd gladly ditch it if I could. It's written in .Net, but has a COM API and this web service in a deprecated format. They do supply a client library for the web service, but it's writtn in Java. Huh?
I'm going to go back to my original idea and write a wrapper around the Java client, using ikvmc. At least I know I can get that to work, even if all the type conversion will be messy.
As for picking an answer #Cheeso and #Aaronaught have both been very helpful, so I've flipped a coin and given it to #Cheeso.
The example message you've shown there shows a message using what is known as "SOAP Section 5 encoding". SOAP encoding (not to say SOAP) was deprecated by all major tools and services vendors a looooong time ago, due to problems with compatibility and interoperability. Like in 2004 or so.
Seriously. Nobody should be using that stuff any longer. There is no excuse.
But even so, you should be able to get it to work.
The challenge is to get the XML namespaces right on each of the request and response elements. Just looking at the example request message - the one that "works" - you can see it's sort of deranged. There's the namespace with the STES prefix on the toplevel request element - Execute. Then, all the child elements get no namespace at all. This is weird.
The same weird on/off namespace thing occurs in the Params array. The wrapper element is in the namespace with the sof prefix. But the key and value child elements are not in that namespace- they are in no namespace at all.
In your attempt, you have a couple mismatches then;
In your case, the DictionaryItem element is in the http://www.smarteam.com/dev/ns/iplatform/embeddedscripts namespace. It should be in the http://www.smarteam.com/dev/ns/SOF/2.0 namespace.
In your case, the key and value elements are in the
http://www.smarteam.com/dev/ns/iplatform/embeddedscripts namespace. They should be in no namespace at all.
Normally a proper WSDL means you do not have to worry about any of these things. I am puzzled as to why your WSDL is not generating a proxy that does the right thing. What I recommend people do in this case is get a wSDL that really works. Oftentimes that means writing a mock version of the service in ASMX.
If you can generate a service in ASMX that accepts messages of the form accepted by the real service, and if you can generate a client that interacts with that ASMX service, then the client should also work with the real service. the reason I recommend ASMX is that it's so easy to tweak and retry things.
Toward that end, here's what I cam eup with.
<%# WebService Language="c#"
Class="Cheeso.CooperService"
%>
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Protocols;
using System.Xml.Serialization;
using System.Collections;
namespace Cheeso
{
[SoapType(Namespace="http://www.smarteam.com/dev/ns/SOF/2.0")]
public class DictionaryItem
{
public string key { get; set; }
public string value { get; set; }
}
[System.Web.Services.WebService
(Name="EngineSoapBinding",
Namespace="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts/wsdl/")]
public class CooperService : System.Web.Services.WebService
{
[WebMethod]
[SoapRpcMethod
("http://www.smarteam.com/dev/ns/iplatform/embeddedscripts/action/Execute",
RequestNamespace="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts",
ResponseNamespace="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts",
Use=SoapBindingUse.Encoded)]
[return: System.Xml.Serialization.SoapElementAttribute("Result")]
public object Execute(string ContextHandle,
string ScriptLanguage,
string Script,
DictionaryItem[] Params)
{
return "The answer is 42. What is the question?";
}
}
}
This ASMX file should produce a WSDL and an interface that is equivalent to your real service. Generate the WSDL from it (using the ?wsdl query), and then write a test client. Examine the messages on the wire and tweak as necessary.
You can see that I applied a REAL type to the Params array. Also I decorated that type with the SoapType attribute and specified the desired xml namespace.
In your problem statement you didn't describe the response message. You'll need to go through a similar exercise - tweaking and adjusting - in order to shape the response message "expected" by your client to match the responses actually generated by the real service.
Also, remember that the xmlns prefixes are not significant. It's nto the prefix you need to match, it's the XML namespace itself. You don't need STES:Execute. You can use any namespace prefix, as long as it maps to the correct xml namespace.
Good luck.
If you get a chance, convince them to move to a WS-I compliant service interface. Interop is much easier when the service complies with the WS-I recommendations.
EDIT
This is a trace of the actual message from the client, generated using that WSDL:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts/wsdl/"
xmlns:types="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts/wsdl/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<q1:Execute xmlns:q1="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts">
<ContextHandle xsi:type="xsd:string">00913983</ContextHandle>
<ScriptLanguage xsi:type="xsd:string">Canadian, eh?</ScriptLanguage>
<Script xsi:type="xsd:string">To be or not to be....</Script>
<Params href="#id1" />
</q1:Execute>
<soapenc:Array id="id1"
xmlns:q2="http://www.smarteam.com/dev/ns/SOF/2.0"
soapenc:arrayType="q2:DictionaryItem[2]">
<Item href="#id2" />
<Item href="#id3" />
</soapenc:Array>
<q3:DictionaryItem id="id2"
xsi:type="q3:DictionaryItem"
xmlns:q3="http://www.smarteam.com/dev/ns/SOF/2.0">
<key xsi:type="xsd:string">17</key>
<value xsi:type="xsd:string">s9dkjdls</value>
</q3:DictionaryItem>
<q4:DictionaryItem id="id3"
xsi:type="q4:DictionaryItem"
xmlns:q4="http://www.smarteam.com/dev/ns/SOF/2.0">
<key xsi:type="xsd:string">fish</key>
<value xsi:type="xsd:string">barrel</value>
</q4:DictionaryItem>
</soap:Body>
</soap:Envelope>
Even though this is different than your target message, this should be parseable by your server-side, if it conforms to SOAP v1.1 section 5 encoding spec. This request message uses the "multiple reference" serialization whereas your example target message uses "single reference". But they should be equivalent to the server side. Should be.
But as I said originally, there were lots of problems getting SOAP section 5 encoding to work interoperably.
The WCF solution is really rather simple, just use these classes in your import:
[DataContract(Namespace = "http://www.smarteam.com/dev/ns/iplatform/embeddedscripts")]
[KnownType(typeof(SofDictionaryItem[]))]
[XmlSerializerFormat(Style = OperationFormatStyle.Rpc, Use = OperationFormatUse.Encoded)]
public class Execute
{
[DataMember(Order = 0)]
public string ContextHandle { get; set; }
[DataMember(Order = 1)]
public string ScriptLanguage { get; set; }
public string Script { get; set; }
[DataMember(Name = "Script", Order = 2, EmitDefaultValue = false)]
private CDataWrapper ScriptCData
{
get { return Script; }
set { Script = value; }
}
[DataMember(Order = 3)]
public object Params { get; set; }
}
[DataContract(Namespace = "http://www.smarteam.com/dev/ns/SOF/2.0", Name = "DictionaryItem")]
public class SofDictionaryItem
{
[DataMember]
public object Key { get; set; }
[DataMember]
public object Value { get; set; }
}
I'm using Marc Gravell's CDataWrapper here to force the CDATA tags around the Script.
The DataContractSerializer will generate output that's nearly identical to what you're seeing over the wire already:
<Execute xmlns="http://www.smarteam.com/dev/ns/iplatform/embeddedscripts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ContextHandle>0019469#00228</ContextHandle>
<ScriptLanguage>javascript</ScriptLanguage>
<Script><![CDATA[Context.Result = Context.Params("Number")]]></Script>
<Params i:type="a:ArrayOfDictionaryItem" xmlns:a="http://www.smarteam.com/dev/ns/SOF/2.0">
<a:DictionaryItem>
<a:Key i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Number</a:Key>
<a:Value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">10</a:Value>
</a:DictionaryItem>
<a:DictionaryItem>
<a:Key i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Hello</a:Key>
<a:Value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">World</a:Value>
</a:DictionaryItem>
</Params>
</Execute>
The only potential problem is the ArrayOfDictionaryItem, which is a convention that .NET always seems to use for array types. If you actually look at the generated WSDL for these types, you'll see that it actually references the soapenc:arrayType, but that may not be sufficient here if the endpoint is unaware of this convention. If that is the case, then unfortunately I think you'll have to resort to IXmlSerializable, because I've never been able to find a way to disable the ArrayOf generation in .NET.
As Cheeso mentions, the RPC/encoded SOAP format is officially deprecated by the WS-I and should never be used in production services anymore. One of the reasons it was deprecated was because it was lousy for interop and painful to implement. If possible, you really should talk to the vendor about getting an update, which ought to be using the standard document/literal wire format.
Hi I would like to create an API for my website to send and receive data.
For example I need my customers to upload products, single or multiple items. Product feeds can be send daily, weekly or monthly.
Product Name:
Product Color:
Product Weight:
Product Images:
Also I need functionality to send this data to another server. And it should be user friendly.
But I don't have any idea where to start, what technology to use to make it simple and sufficient.
I have background in Asp.Net, C#. It would be great to see an example how to approach it.
Its better you go for the WEB SERVICES (WCF SERVICE) to achieve this easily.
REST via WCF would be the best option. Here is a good article series introducing you to REST with WCF: REST in WCF
There are two distinct pieces of functionality here, and keep in mind that they should essentially be kept separate. Each of them is defined by "who is integrating to whom."
In the first piece, you want to expose a web service API to which clients can connect and send/receive data (the latter of which is on request only). How you want to define this web depends on how you want to expose it to clients, how they want to connect, etc. Common options are:
SOAP Web Service (classic ASP .NET web service)
WCF Service (think of it as a more modern ASP .NET web service)
You can even expose a manual service by defining your own WSDL for clients to consume, or a service that accepts and returns JSON to be more JavaScript-friendly for clients, etc. There are many options. But the above two are your most common choices.
The second piece is where you want to "push" data to another service. This is something that the other service needs to expose and you need to integrate to that. So the design should begin on that side. If you're in charge of that design, just approach it the same way as above. Expose a service there and then, using the same technologies that expose the services, consume them in your application.
The main thing to keep in mind here is to keep the two separate, because trying to expose a web service which at the same time consumes another web service will likely lead to confusion and some non-obvious work-arounds. These are separate concerns and need to keep separated on a logical level, even if the end user doesn't know how separated they are.
Here is a bare minimum WCF Service which returns a product in JSON. To try it out, create a .NET 4.0 Full Profile console application. Run the program, and put this in your browser's address bar: http://localhost:8080/productservice/Product/23
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFServiceExample
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
}
[ServiceContract(Namespace = "")]
public interface IProductService
{
[WebGet(UriTemplate = "Product/{id}", ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Product Product(string id);
}
public class ProductService : IProductService
{
public Product Product(string id)
{
return new Product { Id = id, Name = "A Sample Product" };
}
}
class Program
{
private static ServiceHost servHost;
static void Main(string[] args)
{
StartService();
Console.WriteLine("\n\nPress any key to exit...");
Console.ReadKey();
}
public static void StartService()
{
servHost = new ServiceHost(typeof(ProductService));
servHost.Open();
}
~Program()
{
if (servHost != null)
{
servHost.Close();
}
}
}
}
App.config
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logKnownPii="true" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
<endToEndTracing propagateActivity="true" activityTracing="true"
messageFlowTracing="true" />
</diagnostics>
<services>
<service name="WCFServiceExample.ProductService">
<endpoint
address="http://localhost:8080/productservice"
contract="WCFServiceExample.IProductService"
kind="webHttpEndpoint" />
</service>
</services>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
This exception is consistently thrown on a SOAP Request which takes almost three minutes to receive and is 2.25 megs in size.
When scouring the web I find all sorts of posts which all seem to be about setting headers on the Request, some want me to not send the "Expect:" header, some want me to send the "Keep-Alive:" header, but irregardless of the headers I send I still get this pesky error. I don't believe that setting any headers is my answer, because I can recreate the exact same request using "curl" and a response does eventually come back with no problems what-so-ever.
My <httpRuntime maxRequestLength="409600" executionTimeout="900"/>.
I feel as if I'm running out of options. If anyone can provide any assistance I would be most grateful. A few other things to note would be that the server I'm Requesting data from is out of my hands, also these requests are over https and other requests with smaller responses work flawlessly.
Thanks
You tagged the post as .NET35, so are you using WCF?
If so, here is an example of the App.config we use for large data sets:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="8388608" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:1602/EndPoint.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding" contract="IEndPointContract" name="EndPoint" behaviorConfiguration="EndpointBehaviour" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="EndpointBehaviour">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
I hope it's not too late for answering this question.
Try adding the following attribute on the definition of your contract interface: [ServiceKnownType(typeof(ReturnClass))]
For more generic solution that allows returning polymorphic classes please refer to this post:
http://www.goeleven.com/blog/entryDetail.aspx?entry=45
If you are using dbml instead of edmx you will get this( The underlying connection was closed: The connection was closed unexpectedly.) as dbml will not return serialisable data it needs datacontract so go to properties of dbml file and change the Serialization mode to unidirectional.
Have you tried the sugestion of this Blog Post? The problem will most probably lie in the TCP/HTTP stack implementation of .NET .
i got this error because my datatransfereobjects refered to each other in an recursive manner.
For example:
Customer-> (has) -> Rating
Rating-> (belong to) -> Customer
so you have to remove cycles.
[DataContract]
public class Rating
{
private Customer _customer;
//[DataMember] // <- EITHER HERE
public Customer Customer
{
get { return _customer; }
set { _customer = value; }
}
}
[DataContract]
public class Customer
{
private long _customerID;
[DataMember]
public long CustomerID
{
get { return _customerID; }
set { _customerID = value; }
}
[DataMember] // <- OR HERE
public Rating Rating
{
get { return _rating; }
set { _rating = value; }
}
}
Tried several ways to get rid of this error message until I found this solution:
http://kiranpatils.wordpress.com/2008/09/22/the-underlying-connection-was-closed-the-connection-was-closed-unexpectedly-while-returning-data-table-from-wcf-service/
You may change your List<> to DataSet. I suspect DataSet can handle much amount of data than the List<>.
Hope it helps.
I've got the same issue, and after deep investigations I found this article:
Merrick Chaffer's Blog
It was all related to setting the "dataContractSerializer" for both client and server.
Hope this to be helpful.
I have added another field, but didn't have a set on the property.
That was my solution for the same error.
[DataMember]
public bool HasValue
{
get { return true; }
set { }//adding this line made the solution.
}
This is a generic error raised if there is an internal error.
Try adding tracing here: http://msdn.microsoft.com/en-us/library/ms732023(v=vs.110).aspx
You will see the full log then.
For WCF with EF, just add the following code in the context class.
base.Configuration.ProxyCreationEnabled = false;