Problems with readerQuotas in ASP.NET application - asp.net

I have an ASP.NET 4.0 Application.
A webservice is hosted using a .svc file linking a source (service implementation).
The web service .svc file is located inside a directory WebServs in the application root directory: MyApp/WebServs/mysvc.svc.
The web service is set using the Web.config (in the root directory).
<!-- Service model -->
<system.serviceModel>
<services>
<service name="DataAccessService">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="basicHttpBinding_ISRV"
contract="MyNamespace.ISRV">
</endpoint>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="basicHttpBinding_ISRV" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="1310720"
maxArrayLength="16384"
maxBytesPerRead="24096"
maxDepth="10000"
maxNameTableCharCount="16384"/>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
OK!
When I call the web service, I create the channel using a routine in order to encapsulate this commonly used logic:
public static ISRV GetService() {
try {
// Create the service endpoint
BasicHttpBinding bhttpb = new BasicHttpBinding(
BasicHttpSecurityMode.TransportCredentialOnly);
bhttpb.MaxReceivedMessageSize = 2147483647;
bhttpb.ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas();
bhttpb.ReaderQuotas.MaxArrayLength = 16384);
bhttpb.ReaderQuotas.MaxBytesPerRead = 24096);
bhttpb.ReaderQuotas.MaxDepth = 10000);
bhttpb.ReaderQuotas.MaxNameTableCharCount = 16384);
bhttpb.ReaderQuotas.MaxStringContentLength = 1310720);
ServiceEndpoint httpEndpoint =
new ServiceEndpoint(
ContractDescription.GetContract(typeof(ISRV)),
bhttpb,
new EndpointAddress());
// Create channel factory and get proper channel for service.
ChannelFactory<ISRV> channelFactory = new ChannelFactory<ISRV>(httpEndpoint);
IDAS svc = channelFactory.CreateChannel();
return svc;
} catch (Exception e) {
throw new DASException("DAS Exception: " + e.Message);
}
}
This routine is called by clients. Whilke the Web.config is used to configure the service server side.
When I try to execute my service with large messages (with tiny messages all's right) I get:
The formatter threw an exception while trying to deserialize the
message: There was an error while trying to deserialize parameter
http://((Namespace)):((Operation)). The InnerException message
was 'There was an error deserializing the object of type
((Type)),
App_Code.s5qoir2n, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null]]. 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 31, position 1309.'. Please see InnerException for more details.
Don't understand. Both service and client have common settings, and this reads defaut values????? Furthermore I did as many other users did following instructions here in StackOverflow.
Please help me. Thankyou

You specified WCF 4.0 (well, ASP.NET 4.0 to be exact), so I wonder if the problem you're encountering is that you're actually hitting a default endpoint, which would use the default values for the binding unless otherwise overridden?
WCF 4.0 will supply a default endpoint (set to where the service is located at). That default endpoint will most likely use the default values for the binding (8192 in the case of the MaxStringContentLength).
Since you do all the configuration for the service in the directory above the WebServs directory (the root), perhaps it's resorting to a default endpoint? I do realize that the Web.config files will inherit from the ones above, but this is something to at least consider, if you haven't already.
More info on default endpoints and other changes for 4.0 can be found here: A Developer's Introduction to Windows Communication Foundation 4

Related

Consuming the Tridion 2011 linking.svc service in ASP.NET

I receive the following error when attempting to add a service reference to /linking.svc in my ASP.NET application:
There was an error downloading http://localhost:82/linking.svc/. The request failed with HTTP status 404: Not Found. Metadata contains a reference that cannot be resolved: http://localhost:82/linking.svc/. There was no endpoint listening at http://localhost:82/linking.svc/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. The remote server returned an error: (404) Not Found. If the service is defined in the current solution, try building the solution and adding the service reference again.
I thought I could consume the linking service in the same way as odata (add service reference in Visual Studio) as odata works fine for me. I've checked the web.config of my services installation and both endpoints look correctly configured.
<!-- HTTP support -->
<service name="Tridion.ContentDelivery.Webservice.ODataService">
<endpoint behaviorConfiguration="webHttp" bindingConfiguration="HttpBinding" binding="webHttpBinding" contract="Tridion.ContentDelivery.Webservice.IODataService" />
</service>
<service name="Tridion.ContentDelivery.Webservice.LinkingService">
<endpoint behaviorConfiguration="webHttp" bindingConfiguration="HttpBinding" binding="webHttpBinding" contract="Tridion.ContentDelivery.Webservice.Ilinking" />
</service>
<service name="Tridi
I assume i'm attempting to consume the linking.svc in an incorrect way.
My question... Am I following the correct procedure for using the linking.svc service in a Visual Studio ASP.NET project? If not, please could you help me to understand how to utilise this api.
Many thanks
Did you consider writing your own client for the linking service? It is a quite simple REST-ful web service, so you can access it with a standard WebClient:
From an example by Mihai Cadariu:
WebClient client = new WebClient();
string linkingServiceUrl = "http://tridion.server:8080/services/linking.svc";
string COMPONENT_LINK = "/componentLink?sourcePageURI={0}&targetComponentURI={1}&excludeTemplateURI={2}&linkTagAttributes={3}&linkText={4}&showTextOnFail={5}&showAnchor={6}";
string url = linkingServiceUrl +
string.Format(COMPONENT_LINK,
sourcePageUri,
targetComponentUri,
excludeTemplateUri,
HttpUtility.UrlEncode(linkTagAttributes),
HttpUtility.UrlEncode(linkText),
showTextOnFail,
showAnchor);
return client.DownloadString(url);
Have you read the documentation here (requires login):
http://sdllivecontent.sdl.com/LiveContent/content/en-US/SDL_Tridion_2011_SPONE/reference_277A2D7264B04A39870C3FE18EF245BB

WCF - More than one endpoint configuration for that contract was found - Error

We have working ASP.Net web application with WCF. wcf service hosted as a windows service. All is fine. Then we made a change so that service contract will have different namespace (From Namespace1.IserviceContract to Namespace2.IserviceContract). After the change we deployed to the server and getting following error when we try to instantiate the service object.
System.InvalidOperationException: An endpoint configuration section for contract 'Namespace2.IserviceContract' could not be loaded because more than one endpoint configuration for that contract was found. Please indicate the preferred endpoint configuration section by name.
Generated: Fri, 06 Jul 2012 21:02:56 GMT
System.Web.HttpUnhandledException: Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.InvalidOperationException: An endpoint configuration section for contract 'Namespace2.IserviceContract' could not be loaded because more than one endpoint configuration for that contract was found. Please indicate the preferred endpoint configuration section by name.
at System.ServiceModel.Description.ConfigLoader.LookupChannel(String configurationName, String contractName, Boolean wildcard)
at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName, Configuration configuration)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
at System.ServiceModel.ChannelFactory`1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress)
at System.ServiceModel.EndpointTrait`1.CreateSimplexFactory()
at System.ServiceModel.EndpointTrait`1.CreateChannelFactory()
at System.ServiceModel.ClientBase`1.CreateChannelFactoryRef(EndpointTrait`1 endpointTrait)
at System.ServiceModel.ClientBase`1.InitializeChannelFactoryRef()
at System.ServiceModel.ClientBase`1..ctor()
at TestApplication.ManagementWrapper.VerifyAuthentication(Int32 appId, String Token)
at TestApplication.VerifyAuthentication(String tokenstring)
we did a research about this issue and found that this type if exception shows up if we have two client endpoints defined in our web.config file. however we are certain that we have only one client endpoint defined. More over this exception shows up only in the server. local works fine. here is our service model:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_Management" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="4194304" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="32768" maxNameTableCharCount="2147483647" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://servername:9010/Management/service/ManagementService" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_Management" contract="Namespace2.IserviceContract" name="NetTcpBinding_IserviceContract" />
</client>
</system.serviceModel>
we also tried to restart IIS and application pool. Still getting the same exception.
Try searching your web.config for another that is using the web address as your ManagementService. Also, search the web.config for any reference to the old namespace (contract="Namespace1.IserviceContract"). Don't forget to check for extra .config files. That little gotcha has burned me before.
Whatever protocol is being called like basic, net.tcp or wshttp, that address should be in web config file remove other addresses from client section in app.config file, in my case i am calling the service as htp://machinename:700/test.svc but in the client section there were addresses with net.tcp and wshttp configurations, removed those addresses and issue is fixed for me.
Please right click on svc file of your wcf service and click on View markup.
then modify namespace there also. It should work fine then.
If everything in your web.config appears to be correct, this error can be caused by another application on the same server. I spent several days troubleshooting a similar issue.
In my case, the environment had a large number of WCF services deployed as web applications in IIS under a single website as follows.
/Root Website
/Service1
/Service2
/Service3
/ServiceX
One of the child services was mistakenly deployed to the root website physical folder rather than to it's own physical folder. This bad deployment contained a client endpoint definition that was common to all of the services and caused all of the child services to break. Apparently, the same client endpoint cannot be used by the parent website and a child web application.
Removing the client endpoint from the root website fixed the issue for me.

ASP.NET: Exposing same core functionality as SOAP _and_ REST interfaces

We need to support both SOAP as well as REST interfaces into what is effectively the same function call. I understand SOAP is a protocol while REST is an architecture style, but I'm also sure web service developers know what I'm talking about; so lets not get distracted by the pedantic details. Also, I'd request avoiding a SOAP versus REST debate - we need both for business needs across different customers. The platform is ASP.NET 4.0.
REST:
I'm using WCF and essentially inputData is consumed by FunctionA to produce OutputData. I've got the abstract interface defined via the [ServiceContract] and the actual service logic exposed via the [WebInvoke] keyword. i.e.
[WebInvoke(UriTemplate = "funcA", Method = "POST", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
public OutputType FunctionA(InputType inputData)
SOAP
For the SOAP interface, I essentially need the same inputData going into the same FunctionA() which spits out the same OutputData (of type OutputType). Of course, these will be wrapped inside SOAP envelopes etc.
So my question is: How can I leverage the framework so that supporting a SOAP interface into the same functionality can be done with minimal custom code?
Find my service below that provides support for both SOAP and REST
[ServiceContract]
public interface ISampleService
{
[WebGet]
[OperationContract]
string GetData();
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class SampleService : ISampleService
{
public string GetData()
{
return "Welcome to server";
}
}
My web.config would have the following
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="RestBinding">
<readerQuotas maxStringContentLength="5242880" maxArrayLength="16384"
maxBytesPerRead="4096" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="XMLService.SampleService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
bindingConfiguration="RestBinding" name="SampleService" contract="XMLService.ISampleService" />
<endpoint address="soap" binding="basicHttpBinding" contract="XMLService.ISampleService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
</system.serviceModel>
Now the URL for your service would look like as follows:
REST --> http://localhost/SampleApp/SampleService.svc/GetData
SOAP --> http://localhost/SampleApp/SampleService.svc
If you want the REST url to be clean i.e. not have .svc in it then you can follow the WebAPI approach where you register your route in Global.asax and removed the endpoint from the config. You can perform tha same for your POST operation. Also make sure that if you are passing in complex types you need to let the service know if the types as shown below
[KnownType(typeof(SampleItem))]
The above attribute needs to be placed on the class implementing the interface.
One of the projects I'm working on has this exact functionality.
Our WCF service is multi tired
Data Access Layer
Business Logic Layer
Service Layer
The Service Layer has 2 End Points
SOAP
Rest
The End Points are very thin and basically consume methods from the BLL. So taking your example, Function A would be defined in the Business Logic Layer, where all the work would be done. Each of your Endpoints Would also have FunctionA which calls FunctionA from the BLL.
The Visual Studio Solution for this consists of a project for each of the BLL and DAL layers and a project for each of the end points. There are also a couple of other projects for unit tests etc
You have two good options:
Create a SOAP Service and a REST Service. The Endpoint of each calsl a shared class (so there is no code duplication, eg:
//SOAP endpoint
[webmethod]
public void DoSomething(int id)
{
myClass.MethodThatActuallyDoesTheWork(id);
}
//in another service we have the REST methods
//REST endpoint
public void DoSomething(int id)
{
myClass.MethodThatActuallyDoesTheWork(id);
}
OR (my prefered method)
Install the WCFWebAPI via Nuget (or whatever) as this allows content negotioation in that you write one method in your service. If THE CLIENT specifies Accept: application/xml then they get XML returned, if the client specifies Accept: application/json then they get JSON back.
I am not sure if this generates a WSDL though - if your using soap 'cos you want XML then this is a good method. If you need a WSDL then two services might be better.
Food for thought anyway. Hope this helps.
If you need to test a WSDL based XML service the WCFTestClient is pretty handy.
The WCFWebApi actually generates test/help pages for you too. It's great.

WCF Endpoints & Binding Configuration Issues

I am running into a very strange issue here folks. For simplicity I created a project for the sole purpose of testing the issue outside the framework of a larger application and still encountered what is either a bug in WCF within Visual Studio 2010 or something related to my WCF newbie skill set : )
Here is the issue:
I have a WCF endpoint I created running inside of an MVC3 project called "SimpleMethod". The method runs inside of a .svc file on the root of the application and it returns a bool.
Using the "WCF Service Configuration Editor" I have added the endpoint to my Web.Config along with a called "LargeImageBinding".
Here is the service:
[OperationContract]
public bool SimpleMethod()
{
return true;
}
And the Web.Config generated by the Config Tool:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="LargeImageBinding" closeTimeout="00:10:00" />
</wsHttpBinding>
</bindings>
<services>
<service name="WCFEndpoints.ServiceTestOne">
<endpoint address="/ServiceTestOne.svc" binding="wsHttpBinding"
bindingConfiguration="LargeImageBinding" contract="WCFEndpoints.IServiceTestOne" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
The service renders fine and you can see the endpoint when you navigate to: http://localhost:57364/ServiceTestOne.svc - Now the issue occurs when I create a separate project to consume the service. I add a service reference to a running instance of the above project, point it to: http://localhost:57364/ServiceTestOne.svc
Here is the weird part. The service automatically generates just fine but In the Web.Config the endpoint that is generated looks like this:
<client>
<endpoint address="http://localhost:57364/ServiceTestOne.svc/ServiceTestOne.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServiceTestOne"
contract="ServiceTestOne.IServiceTestOne" name="WSHttpBinding_IServiceTestOne">
As you can see it lists the "ServiceTestOne.svc" portion of the address twice!
When I make a call to the the service I get the following error:
The remote server returned an error: (404) Not Found.
I tried removing the extra "/ServiceTestOne.svc" at the end of the endpoint address in the above config, and I get the same exact error.
Now what DOES work is if I go back to the WCF application and remove the custom endpoint and binding references in the Web.Config (everything in the "services" and "bindings" tags) then go back to the consumer application, update the reference to the service and make the call to SimpleMethod()....BOOM works like a charm and I get back a bool set to true.
The thing is, I need to make custom binding configurations in order to allow for access to the service outside of the defaults, and from what I can tell, any attempt to create custom bindings makes the endpoints seem to run fine, but fail when an actual method call is made.
Can anyone see any flaw in how I am putting this together? Thank you for your time - I have been running in circles with this for about a week!
When hosting a WCF service in IIS, the base address of the service is formed using the following format: {protocol}://{host}:{port}/{applicationName}/{svcFileName}. This is the address you can browse to get the WCF help page and/or the metadata (on a default configuration).
To form the actual address of the endpoint (the one your client needs to use), the following format is used: {serviceBaseAddress}/{endpointAddress}
Comparing the format above and the sample configuration you provided explains why you're getting ServiceTestOne.svc twice in your client address.
If you want the address of your service to be http://localhost:57364/ServiceTestOne.svc, I'd recommend leaving the address attribute empty in your endpoint configuration:
<endpoint address="" ... />

WCF Service support file jsdebug fails to load

I have a WCF service that gets called from client side JavaScript. The call fails with a Service is null JavaScript error. WebDevelopment helper trace shows that the calls to load the jsdebug support file results in a 404 (file not found) error.
Restarting IIS or clearing out the Temp ASP.Net files or setting batch="false" on the compilation tag in web.config does not resolve the problem
From the browser
https://Myserver/MyApp/Services/MyService.svc displays the service metadata
however
https://Myserver/MyApp/Services/MyService.svc/jsdebug results in a 404.
The issue seems to be with the https protocol. With http /jsdebug downloads the supporting JS file.
Any ideas?
TIA
Figured it out!
Here is the services configuration section from web.config
Look at the bindingConfiguration attribute on the endpoint. The value "webBinding" points to the binding name="webBinding" tag in the bindings and that is what tells the service to use Transport level security it HTTPS. In my case the attribute value was empty causing the webservice request to the /js or /jsdebug file over HTTPS to fail and throw a 404 error.
<services>
<service name="MyService">
<endpoint address="" behaviorConfiguration="MyServiceAspNetAjaxBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="Services.MyService" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="Transport">
</security>
</binding>
</webHttpBinding>
</bindings>
Note that the bindingConfiguration attribute should be empty ("") if the service is accessed via http instead of https (when testing on local machine with no certs)
Hope this helps someone.
If you still get the same error after all your possible work done. Just add a "AJAX Enabled WCF-Service".
For me the issue was the following; we added MVC to a solution with routing. Our WCF services were not being ignored. I resolved this by adding the following rule (where "WCF" is the folder we keep our services in).
routes.IgnoreRoute("WCF/{*pathInfo}");
Hope that saves somebody a few hours.

Resources