This has happened a couple of times to me know. If I add to many OperationContract's to a ServiceContract, the WCF Test Client app throws an exception:
"Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata."
In the details it continues:
Error: Cannot obtain Metadata from . The request failed with HTTP status 400: Bad Request.
If I remove a couple of operation contracts then everything is fine. Outside of the test client is also fine.
Could you be more specific about what kinds of operations you have to remove from the service contract to make it work?
Here are some known limitations in the WcfTestClient.exe tool that comes with the .NET Framework 3.5 SDK. Note that all of these issues have been fixed in the version that ships with .NET 3.5 SP1.
The client does not maintain a session with the invoked service. All calls are made on new proxy instances
The auto-generated configuration file for the client proxy can be viewed but not edited
Services using the XML Serializer instead of of the Data Contract Serializer cannot be invoked
Services using Message Contracts cannot be invoked
Thanks for the responses.
These were the offending lines:
<OperationContract(), FaultContract(GetType(WcfService.Common.DefaultFaultContract))> _
Function GetJobSubTypesForJobTypeList(ByVal jobTypeList As Dictionary(Of Integer, String)) As List(Of JobSubTypeOfJobTypeDTO)
<OperationContract(), FaultContract(GetType(WcfService.Common.DefaultFaultContract))> _
Function GetActivityTypesForJobTypeList(ByVal jobTypeList As Dictionary(Of Integer, String)) As List(Of ActivityTypeOfJobTypeDTO)
It turned out that we were missing setters in the return types (DTO) and a default constructor.
This is one of the weirdest problems I've come across. You might have to review your code and look out for problems such as:
Private _NetPay As Boolean
<DataMember()> _
Public Property NetPay() As Boolean
Get
Return _Amount = 0
End Get
Set(ByVal value As Boolean)
_NetPay = value
End Set
End Property
I had defined a DataMember as the above. Notice the return statment. It is trying to return a computed value. I removed this data member; it worked fine.
This is what i had to add to my devenv.exe.config in order to get my WCF Test Client to work with a very large service. I then had to restart my IDE. This may not be what you are looking for, but i hope it helps.
<system.serviceModel>
<bindings>
<customBinding>
<binding name="MyBinding">
<textMessageEncoding>
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
</textMessageEncoding>
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647"/>
</binding>
</customBinding>
</bindings>
<client>
<endpoint binding="customBinding" bindingConfiguration="MyBinding" contract="IMetadataExchange" name="http"/>
</client>
</system.serviceModel>
Related
I called an WCF service and tried fetching data from database in windows 7.
I got this error.
Error in deserializing body of reply message for operation
'GetProductXml'. The maximum string content length quota (8192) has
been exceeded while reading XML data. This quota may be increased by
changing the MaxStringContentLength property on the
XmlDictionaryReaderQuotas object used when creating the XML reader.
Line 13, position 197.
I tried changing the MaxStringContentLength property to 2147483647 in web config of WCF service but i get the same above error....
You need to change it in the client.config file that was created when you added a service reference in your windows 7 application.
You can get around the error by adding the below settings in your WCF Service web.config and also on your client side web.config:
<basichttpBinding>
<binding>
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxDepth="64" maxNameTableCharCount="2147483647" />
</binding>
</basichttpBinding>
NOTE: Assuming you are using BasicHttpBinding. If using a different binding make sure to add the readerQuotas for that binding.
If you are hosting your WCF service via code and then you want to add reader quotas via code see below:
var binding = new BasicHttpBinding();
var myReaderQuotas = new XmlDictionaryReaderQuotas();
myReaderQuotas.MaxStringContentLength = 5242880;
binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);
I have a problem with a WCF service.
I have a console application and I need to consume the service without using app.config, so I had to set the endpoint, etc. by code.
I do have a service reference to the svc, but I can't use the app.config.
Here's my code:
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://localhost:8731/WcfServicio/MiServicio");
MiServicioClient svc = new MiServicioClient(binding, address);
object ob = svc.PaisesObtener();
At the last line when I do svc.PaisesObtener() I get the error:
Content Type text/xml; charset=utf-8 was not supported by service
http://localhost:8731/WcfServicio/MiServicio. The client and service bindings may be mismatched.
First Google hit says:
this is usually a mismatch in the client/server bindings, where the message version in the service uses SOAP 1.2 (which expects application/soap+xml) and the version in the client uses SOAP 1.1 (which sends text/xml). WSHttpBinding uses SOAP 1.2, BasicHttpBinding uses SOAP 1.1.
It usually seems to be a wsHttpBinding on one side and a basicHttpBinding on the other.
Do not forget check the bindings-related code too.
So if you wrote:
BasicHttpBinding binding = new BasicHttpBinding();
Be sure that all your app.config files contains
<endpoint address="..."
binding="basicHttpBinding" ...
not the
<endpoint address="..."
binding="wsHttpBinding" ...
or so.
I've seen this behavior today when the
<service name="A.B.C.D" behaviorConfiguration="returnFaults">
<endpoint contract="A.B.C.ID" binding="basicHttpBinding" address=""/>
</service>
was missing from the web.config. The service.svc file was there and got served. It took a while to realize that the problem was not in the binding configuration it self...
I saw this problem today when trying to create a WCF service proxy, both using VS2010 and svcutil.
Everything I'm doing is with basicHttpBinding (so no issue with wsHttpBinding).
For the first time in my recollection MSDN actually provided me with the solution, at the following link How to: Publish Metadata for a Service Using a Configuration File. The line I needed to change was inside the behavior element inside the MEX service behavior element inside my service app.config file. I changed it from
<serviceMetadata httpGetEnabled="true"/>
to
<serviceMetadata httpGetEnabled="true" policyVersion="Policy15"/>
and like magic the error went away and I was able to create the service proxy. Note that there is a corresponding MSDN entry for using code instead of a config file: How to: Publish Metadata for a Service Using Code.
(Of course, Policy15 - how could I possibly have overlooked that???)
One more "gotcha": my service needs to expose 3 different endpoints, each supporting a different contract. For each proxy that I needed to build, I had to comment out the other 2 endpoints, otherwise svcutil would complain that it could not resolve the base URL address.
I was facing the similar issue when using the Channel Factory. it was actually due to wrong Contract specified in the endpoint.
For anyone who lands here by searching:
content type 'application/json; charset=utf-8' was not the expected type 'text/xml; charset=utf-8
or some subset of that error:
A similar error was caused in my case by building and running a service without proper attributes. I got this error message when I tried to update the service reference in my client application. It was resolved when I correctly applied [DataContract] and [DataMember] attributes to my custom classes.
This would most likely be applicable if your service was set up and working and then it broke after you edited it.
I was also facing the same problem recently. after struggling a couple of hours,finally a solution came out by addition to
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
to your SVC markup file. e.g.
ServiceHost Language="C#" Debug="true" Service="QuiznetOnline.Web.UI.WebServices.LogService"
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
and now you can compile & run your application successfully.
Again, I stress that namespace, svc name and contract must be correctly specified in web.config file:
<service name="NAMESPACE.SvcFileName">
<endpoint contract="NAMESPACE.IContractName" />
</service>
Example:
<service name="MyNameSpace.FileService">
<endpoint contract="MyNameSpace.IFileService" />
</service>
(Unrelevant tags ommited in these samples)
In my case, I had to specify messageEncoding to Mtom in app.config of the client application like that:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="IntegrationServiceSoap" messageEncoding="Mtom"/>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:29495/IntegrationService.asmx"
binding="basicHttpBinding" bindingConfiguration="IntegrationServiceSoap"
contract="IntegrationService.IntegrationServiceSoap" name="IntegrationServiceSoap" />
</client>
</system.serviceModel>
</configuration>
Both my client and server use basicHttpBinding.
I hope this helps the others :)
I had this error and all the configurations mentioned above were correct however I was still getting "The client and service bindings may be mismatched" error.
What resolved my error, was matching the messageEncoding attribute values in the following node of service and client config files. They were different in mine, service was Text and client Mtom. Changing service to Mtom to match client's, resolved the issue.
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMySevice" ... messageEncoding="Mtom">
...
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
I had this problem in .net 6.0
The problem was the Soap Version, the BasicHttpBinding targets Soap 1.1 by default, but the service uses Soap 1.2.
The solution was to create a custom binding that targets Soap 1.2:
private Binding GetBindingConfiguration()
{
var textBindingElement = new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
};
var httpsBindingElement = new HttpsTransportBindingElement()
{
MaxReceivedMessageSize = int.MaxValue,
RequireClientCertificate = true //my service require certificate
};
return new CustomBinding(textBindingElement, httpsBindingElement);
}
var binding = GetBindingConfiguration();
var address = new EndpointAddress("https://nfe.sefa.pr.gov.br/nfe/NFeAutorizacao4"); //Brazil NF-e endpoint that I had to consume.
var svc = new MyService(binding, address);
//my service requires certificate
svc.ClientCredentials.ClientCertificate.Certificate = certificado;
object ob = svc.PaisesObtener(); //call the method
I'm publishing a service with a MEX endpoint for metadata exchange and I'm using the code below to discover it and get the metadata information
DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());
FindCriteria findCriteria = FindCriteria.CreateMetadataExchangeEndpointCriteria(ContractType);
findCriteria.Duration = TimeSpan.FromSeconds(15);
findCriteria.MaxResults = 1;// MaxResults;
FindResponse result = discoveryClient.Find(findCriteria);
discoveryClient.Close();
ServiceEndpointCollection eps = MetadataResolver.Resolve(ContractType, result.Endpoints[0].Address);
return eps[0].Binding;
When I get the metadata information in my client the binding information (OpenTimeout,
ReceiveTimeout and SendTimeout) is back to its default values.
Here is the binding information in the host
<binding name="MyServiceBinding" closeTimeout="00:05:00" openTimeout="00:05:00"
receiveTimeout="23:50:00" sendTimeout="00:05:00" maxReceivedMessageSize="50000000">
<readerQuotas maxStringContentLength="50000000" maxArrayLength="50000000" />
<reliableSession ordered="true" inactivityTimeout="00:01:00" enabled="false" />
<security mode="None" />
</binding>
here is another question i've found that is almost the same as mine.
WCF Service Binding taking default values instead of custom values
I would like to know if I'm doing something wrong or if I misunderstood the concept of metadata exchange.
What I'm trying to do is send all the info necessary to my clients so they can auto config them self and do not have any hard code configuration.
I don't think you're doing anything wrong - you're just expecting too much from the metadata exchange.
The purpose of MEX is to be able to discover new services programmatically, and create client-side proxies for those services. For this, there's the WSDL - basically anything contained in the WSDL is part of the metadata exchange:
service contract / service methods
parameters needed for those service methods
data type declarations in XML schema for the data types used
additional service related information like bindings used etc.
But MEX does not contain all WCF specific configuration settings - which is what you've discovered. MEX will create a functioning client-side proxy - but it never had the intention of transporting all configuration settings from the server to the client. You'll need to hand-code this yourself, on the client side.
I have a wcf webHttp endpoint and noticed today that when called httpGet with a long url ~364 total characters (http:// etc counted) IIS throws a 400 bad request error. Throwing a breakpoint in the code never gets reached. If I remove some parameters and have a url that is 354 the web service runs as expected.
I'm not sure where the issue is since urls can be like 2k. I'm not posting any data so I don't think I'm hitting a 4mb limit like from here
What gives?
Here's some wcf xml stuff.
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<endpoint address="" behaviorConfiguration="REST" binding="customBinding" bindingConfiguration="jsonpBinding" contract="Interface"/>
<bindings>
<customBinding>
<binding name="jsonpBinding">
<jsonpMessageEncoding/>
<httpTransport manualAddressing="true"/>
</binding>
</customBinding>
</bindings>
<extensions>
<bindingElementExtensions>
<add name="jsonpMessageEncoding" type="Microsoft.Ajax.Samples.JsonpBindingExtension, service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bindingElementExtensions>
</extensions>
I just removed the callback function name which significantly reduced the size of the url and it still threw a 400 error. This makes me think that there is a WCF size limit on the text that can be sent in as a string parameter.
here;'s some Contract stuff
[OperationContract]
[WebGet(UriTemplate = #"{userName}/layer({layerName})returnAttributes({attributeList})where({attributeName})({op})({attributeValue})", ResponseFormat = WebMessageFormat.Json)]
[JSONPBehavior(callback = "callback")]
DojoGrouping GetAttributes(string userName, string layerName, string attributeList, string attributeName, string attributeValue);
the issue is with attributeList which can be comma separated list.
so with a url call like
http://../demo/layer(OfficialsLookup)returnAttributes(USHOUSE,US_Photo,US_Web,US_Name,SENDIST,SEN_Name,SEN_Email,SEN_Party,SEN_Photo,REPDIST,REP_Name,REP_Email,REP_Party,REP_Web,REP_Photo)utmX(430)utmY(4502)
it busts. But if i shorten the return attribute text then it functions properly.
I've added I added the following entry into the registry:
Key Name: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters
Class Name: <NO CLASS>
Last Write Time: 1/25/2011 - 3:34 PM
Value 0
Name: UrlSegmentMaxLength
Type: REG_DWORD
Data: 0x200
I rebooted the machine after adding it and am still receiving the same error. Is this the correct spot to be modifying the HTTP.sys settings that WCF and IIS are using? Is there a way to test that WCF is being affected by this registry value?
Here is a related post with no answer but saying that the httpsys stuff did not fix a 64 bit server which is what we are using.
Related Post
To fix our issue we had to use the .NET 4.0 framework. We moved the web service to run under a .net 4.0 app pool and changed the target framework to 4.0. This caused the site to spit out url is too long error instead of just a bad request. After adding a web config entry in
<system.web>
added
<httpRuntime maxUrlLength="500" />
for max url length, the service is up and running as expected.
WCF uses HTTP.sys to handle HTTP traffic. HTTP.sys has system wide settings to handle various restrictions around URL. You might be hitting one of them.
See the following article to find out those settings:
http://support.microsoft.com/kb/820129
You will need to restart http service and your WCF service. If it is hosted in IIS, restart IIS. UrlSegmentMaxLength seems to be an interesting for your URI template.
I am working on a Silverlight v3 web app and I would like to secure access to the WCF service I am using to fetch my data. I currently have the WCF working just fine, but it doesn't require any user credentials.
I'm not very experienced with this aspect of WCF, so my first idea was to add username and password parameters to each of my service's operations. The problem I have with this is that this would require a lot of redundant code, and the fact that the username and password would be transferred over the wire in plain text.
What I would like is a way to specify the credentials upfront on the client side right after I create my service proxy (I am using the proxy autogenerated from "Add Service Reference").
Upon googling for a solution to this, I could only find solutions that similar to my first idea (using username/password parameters). Could someone please point me in the right direction?
Thanks!
Where are these usernames and passwords coming from? If your web site already implements Forms authentication then you can bypass setting credentials yourself and use the forms authentication cookie. If your users are logged in then the cookie will travel with the web service call. In order to read it on the other side you need to make a couple of changes.
First you need to enable ASP.NET compatibility mode for WCF in the system.ServiceModel section:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Once that is done then for each service method you want to understand the ASP.NET cookie add the [AspNetCompatibilityRequirements] attribute to your service class
[ServiceContract]
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ExampleService
{
}
Now within each method you can access the HttpContext.Current.User.Identity object to discover the user's identity.
If you only want certain methods to be called by authenticated users then you can use a PrincipalPermission thus
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Authenticated=true)]
public string Echo()
As a bonus if you're using ASP.NET's role provider then those will also be populated and you can then use a PrincipalPermission on methods to limit them to members of a particular role:
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role="Administators")]
public string NukeTheSiteFromOrbit()
And this works in Silverlight2 as well obviously.
Don't roll your own and add explicit parameters - that is indeed way too much work!
Check out the WCF security features - plenty of them available! You can e.g. secure the message and include credentials inside the message - all out of the box, no extra coding on your side required!
Check out this excellent article on WCF security by Michele Leroux Bustamante: http://www.devx.com/codemag/Article/33342
In your case, I'd suggest message security with user name credentials - you need to configure this on both ends:
Server-side:
<bindings>
<basicHttpBinding>
<binding name="SecuredBasicHttp" >
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="YourService">
<endpoint address="http://localhost:8000/MyService"
binding="basicHttpBinding"
bindingConfiguration="SecuredBasicHttp"
contract="IYourService" />
</service>
</services>
And you need to apply the same settings on the client side:
<bindings>
<basicHttpBinding>
<binding name="SecuredBasicHttp" >
<security mode="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:8000/MyService"
binding="basicHttpBinding"
bindingConfiguration="SecuredBasicHttp"
contract="IYourService" />
</client>
Now your server and client agree on the security - on the client, you'd then specify the user name and password to use like this:
YourServiceClient client = new YourServiceClient();
client.ClientCredentials.UserName.UserName = "your user name";
client.ClientCredentials.UserName.Password = "top$secret";
On the server side, you'll need to set up how these user credentials are being validated - typically either against a Windows domain (Active Directory), or against the ASP.NET membership provider model. In any case, if the user credentials cannot be verified against that store you define, the call will be rejected.
Hope this helps a bit - security is a big topic in WCF and has lots and lots of options - it can be a bit daunting, but in the end, usually it does make sense! :-)
Marc
you can pass in some sort of authentication object and encrypt it at the message level with WCF. C# aspects (http://www.postsharp.org/) can then be used to avoid redundant logic. Its a very clean way of handling it.