I have created a new WCF project using Visual Studio 2012,
I noticed that there is no Service node in the web.config to define the service and the contract, however i deployed the service to azure and it worked, however I`m getting this error:
The remote server returned an unexpected response: (413) Request Entity Too Large. In Silverlight
so i guess i need to increase the maximum allowed request but how do i do that with no service node ?
Beginning with VS 2010 WCF added the concept of default endpoints (as well as default bindings and behaviors), to simplify configuration.
The details can be found at this link: A Developer's Introduction to Window's Communication Foundation 4
In your case, you'll need to create a binding in your config file that has larger sizes, and either set that as the default binding or assign that binding to an explicitly defined endpoint.
By default WCF (in .NET 4+) will assign request coming in over http to basicHttpBinding. These protocol mappings can also be changed in the config file.
A couple of simple examples to help you (the article I linked goes into more detail):
To create a default binding, simply define the binding and omit the name attribute:
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="10000000" ....>
</basicHttpBinding>
</bindings>
This will make your supplied configuration the default basicHttpBinding for the service(s) using that config.
Alternatively, you can use the name attribute on a binding configuration and then assign it to an defined input. Let's say you have a binding name "MyBinding":
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="MyBinding"
contract="MyService.IMyContract" />
If you want something other than basicHttpBinding for http requests, you can do this in the protocols section:
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="wsHttpBinding" bindingConfiguration="" />
The key in your situation is to you'll need to create the binding with larger values, and then either set it as the default or assign it to an endpoint (which you'll also need to define).
As I said, these are just simple examples to give you an idea, and there's a lot more detail in the article I linked.
Related
I'm just getting familiar with WCF and I have to add additional functionality to a working web service at work. As I feel the need to be able to test the functionality before deploying it, I decided to build a test client. Here comes the problem.
I created a Console Application just for the purpose of a test client and tried to add a Service Reference through the provided WSDL but it didn't work. There was no config file created.. I tried first the "Add Service Reference" option in VS and when it didn't work, I tried creating the Proxy and Config files with svcutil.exe...
Just the proxy class gets created... When I try to instantiate a "client object" from that class, the following Exception is thrown: "Could not find default endpoint element that references contract 'eOrderingService.IeOrderingService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element."
As this is a working service (a Czech company is using it), apparently there must be a way to create a web.config or app.config even manually but I have no idea where to start.. As I said I'm just getting familiar with WCF so I started looking online but most of the problems connected somehow to my issue were in different parts of the already created Config files.. I managed to bypass that exception adding the following to app.config:
<system.serviceModel>
<services>
<service name="eOrderingService" >
<endpoint
address="http://localhost:61472/eOrderingService.svc"
binding="webHttpBinding"
contract="eOrderingService.IeOrderingService" >
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint
address="http://localhost:61472/eOrderingService.svc"
binding="webHttpBinding"
bindingConfiguration=""
contract="eOrderingService.IeOrderingService"
behaviorConfiguration="web"
name="DeliveryNote" >
</endpoint>
</client>
The service has a lot of methods and the one I need to test is called 'DeliveryNote'.
So lets say the service is at this address:
http://localhost:61472/eOrderingService.svc
The POST method I need to call is:
http://localhost:61472/eOrderingService.svc/DeliveryNote
And respectively the GET method is:
http://localhost:61472/eOrderingService.svc/DeliveryNote?DocumentFilter={DOCUMENTFILTER}&CustomerID={CUSTOMERID}&FromDate={FROMDATE}
The links are working but I cannot figure out how to call them from the client.
When I tested calling the POST method I received another exception:
The remote server returned an unexpected response: (400) Bad Request.
That shouldn't be true because the request I'm sending is already tested and is a valid request in XML format.
So I tried to test with a different GET method that works and receives just two DateTime parameters and not a Xml. If I try the following link:
http://localhost:61472/eOrderingService.svc/PriceChanges?startDate=2018-08-29&endDate=2018-08-30
the result is OK..
But if I call the automatically generated method "PriceChanges" the result is NULL.
I just don't get what I do wrong. It seems like a connection to the service is established but the methods are not called/build correctly. Probably because I cannot comprehend how to build the <system.serviceModel> in app.config.
I definitely should read more about the web services but I don't know where to start.
I have a token issuer WCF service which is using Microsoft.IdentityModel (WIF 3.5) that I need to upgrade to System.IdentityModel (.NET 4.5). The problem is that I can't change the original name of the service , Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract, to it's newer counterpart, System.ServiceModel.Security.WSTrustServiceContract. For some reason it's not recognized by IntelliSense:
The blue squiggly line error is:
The 'name' attribute is invalid - The value 'System.ServiceModel.Security.WSTrustServiceContract' is invalid according to its datatype 'serviceNameType'
I do have assembly references to System.ServiceModel and System.IdentityModel in <assemblies> node.
Even when I ignore the IntelliSense error and run the service and access it using browser I'm getting this metadata error:
Metadata publishing for this service is currently disabled.
Metadata publishing is enabled so I think it's because of the name problem of the service.
Also I'm getting this error from the VS.NET WCF test client:
Error: Cannot obtain Metadata from http://localhost:49178/Services/Issuer.svc
If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.
WS-Metadata Exchange Error
URI: http://localhost:49178/Services/Issuer.svc
Metadata contains a reference that cannot be resolved: 'http://localhost:49178/Services/Issuer.svc'.
There was no endpoint listening at http://localhost:49178/Services/Issuer.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.
HTTP GET Error
URI: http://localhost:49178/Services/Issuer.svc
The HTML document does not contain Web service discovery information.
I think the "Metadata contains a reference that cannot be resolved" line also refers to the service name resolve error.
Any ideas on what to do here? I'd appreciate any help..
Issuer.svc:
<%# ServiceHost Language="C#" Debug="true" Factory="Identity.Services.Wcf.Core.CustomSecurityTokenServiceContractFactory" Service="CustomSecurityTokenServiceConfiguration" %>
Factory:
public class CustomSecurityTokenServiceContractFactory : WSTrustServiceHostFactory
..
Service:
public class CustomSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
..
Sometimes the best way to solve this kind of problems is to create a new WCF project from scratch, configure again your endpoints etc.. and copying over your existing services from your old project, this is especially true when moving from an older version of WCF.
Here is a checklist that I follow every time I have problems with WCF services:
The Server
Make sure your service contracts are defined using interfaces with the appropriate attributes, for example:
IMyService.cs
[ServiceContract]
public interface IMyService
{
[OperationContract]
int ThisAnOperation(int a, int b);
}
Check that you have implemented your contracts using the right interface:
MyService.cs
public class MyService: IMyService
{
public int ThisAnOperation(int a, int b)
{
return a * b;
}
}
You need to have a service host to access your service, they are the files with the extension .svc:
Create a file myService.svc.
Add the following line of code, referencing the class implementing your service:
<%# ServiceHost Language="C#" Debug="true" Service="YourNamespace.MyService" CodeBehind="MyService.cs" %>
Finally, you need to set up a binding which will define which transports and protocols are available to access your server, start with a simple basic HTTP binding to check that your service is working as expected, then change it to something more production ready that includes authentication and/or encryption and compression as needed.
To setup basic HTTP binding:
Remove the block <system.serviceModel>...</system.serviceModel> from your file web.config if it's already there.
Build your solution, it should compile successfully, otherwise fix any error and try again.
Right-click your web.config file and then click on "Edit WCF Configuration", then click on "Create a New Service" and in Service type, browse and choose the DLL file generated when you compiled your service (should be in the bin folder) and select the service class you would like to publish:
Specify the contract for the service (should be automatically filled up).
In the next page select the transport protocol for your service, in this case, "HTTP", then select "Basic Web Services interoperability".
In the next page you can specify the address for the endpoint, for testing purposes, you can leave this field empty (make sure you also remove "HTTP" from the text field).
Click next, close the configuration window and save.
Now you should be able to run the service and browse to MyService.svc to access your service.
Activate metadata publishing so your service can be found, to do this, add the following behavior to your web.config:
<system.serviceModel>
<services>
<service name="WcfService1.MyService">
<endpoint binding="basicHttpBinding"
bindingConfiguration="" contract="WcfService1.IMyService"
BehaviorConfiguration="MyServiceBehaviors" />
</service>
</services>
</system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehaviors" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Now you should be able to run your project and get a metadata description page of your service within the browser, this info can be used by clients to find the service and generate a proxy of the service:
The Client
Delete any existing service references from your project.
Right click on your project name then in "Add Service Reference", input your service address and click on "Go", if everything went all right you should see your service in the Service Window:
Try to generate the proxy by finishing the wizard, rebuild your project and try it. If you still have the same problem, delete the generated reference and repeat points 1 and 2 and then:
Click on "Advanced" and uncheck "Reuse types in referenced assemblies":
Then finish the wizard and compile.
Hopefully, everything should work now!!!
I may have a similar setup as yours. In my case, I have both the STS and a service that is called by whoever wants a token. This is what you have, right?
In the Web.config for the actual STS I have:
<bindings>
<ws2007HttpBinding>
<binding name="ws2007HttpBindingConfiguration">
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false" clientCredentialType="Certificate"/>
</security>
</binding>
</ws2007HttpBinding>
</bindings>
<services>
<service name="System.ServiceModel.Security.WSTrustServiceContract" behaviorConfiguration="STSBehavior">
<endpoint address="IWSTrust13" binding="ws2007HttpBinding" bindingConfiguration="ws2007HttpBindingConfiguration" contract="System.ServiceModel.Security.IWSTrust13SyncContract" name="STSWCF"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
And in the Web.config for the service I have:
<protocolMapping>
<!-- We want to use ws2007FederationHttpBinding over HTTPS -->
<add scheme="https" binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007FederationHttpBindingConfiguration"/>
</protocolMapping>
<bindings>
<ws2007FederationHttpBinding>
<binding name="ws2007FederationHttpBindingConfiguration">
<!-- We expect a bearer token sent through an HTTPS channel -->
<security mode="TransportWithMessageCredential">
<message establishSecurityContext="false">
<issuerMetadata address="https://localhost/Identity.STS.WCF/Service.svc/mex"/>
</message>
</security>
</binding>
</ws2007FederationHttpBinding>
</bindings>
<services>
<service name="Identity.Auth.WCF.Service" behaviorConfiguration="STSBehavior">
<endpoint address="https://localhost/Identity.Auth.WCF/Service.svc" binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007FederationHttpBindingConfiguration" contract="Identity.Auth.WCF.IService" name="Identity.Auth.WCF"/>
</service>
</services>
Also, it does work for me here, even though I do get the same IntelliSense error as you, and in the very same spot.
My team and I have been working on this for the past several days but have not been able to resolve it. This is our query:
Three binding parameters, maxBufferPoolSize, maxBufferSize and maxReceivedMessageSize were included in basicHttpBinding configuration as below:
<basicHttpBinding>
<binding name="ABCBinding" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
</binding>
</basicHttpBinding>
And included the binding in the endpoint configuration:
<service behaviorConfiguration="mexBehavior" name="XYZ">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="ABCBinding"
contract="ABC"/>
We have a really large input file which we send from Client which brought us to the issue in the first place. The file was getting sent only on the below cases:
1) The binding had no name.
2) In protocol mapping when the binding configuration was specified as below:
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="basicHttpBinding" scheme="http" bindingConfiguration="ABCBinding" />
</protocolMapping>
What I doubt is that the Endpoint configuration is not taken at all. Because as stated https://learn.microsoft.com/en-us/dotnet/framework/wcf/simplified-configuration in this link-
If you do not add a "service" section or add any endpoints in a
"service" section and your service does not programmatically define
any endpoints, then a set of default endpoints are automatically added
to your service, one for each service base address and for each
contract implemented by your service.
To create default endpoints the service host must know what bindings
to use. These settings are specified in a "protocolMappings" section
within the "system.serviceModel" section. The "protocolMappings"
section contains a list of transport protocol schemes mapped to
binding types.
and
If no bindingConfiguration is specified, the anonymous binding
configuration of the appropriate binding type is used.
The configuration works when the binding name is removed or when the name is specified in protocol mapping.
So does this mean that the endpoint specified is not taken into consideration?
Please help me with this issue.
I have a service that programmatically creates two net-tcp end points of the same interface but in different scope (they do different things under the hood). Normally when services run as they are supposed to, there is no problem for a client service to discover these two points properly based on the scope of each of them. However since discovery doesn't work across subnets, when testing I usually add manual configuration into my app.config to enable my app successfully register endpoints even if discovery fails (which does). Now how can I configure my app.config so that it would work for my new endpoints?
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<client>
<endpoint
address="net.tcp://myserver:2170/"
binding="netTcpBinding"
contract="IMyServiceInterface"
name="Service1"/>
<endpoint
address="net.tcp://myserver:2173/"
binding="netTcpBinding"
contract="IMyServiceInterface"
name="Service2"/>
</client>
</system.serviceModel>
</configuration>
What if you try to make service clients with this constructor dynamically
public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress)
and push different settings manually.
Not sure what exactly is your problem in. I don't see why you look into interfaces on client side, since behavior should be defined on server. As per my understanding, you just need to generate your client class once (it's being done automaticaly by VS) and to use it's constructor like that:
var remoteAddr = "net.tcp://myserver:2173/";
var client = new MyClient("*",remoteAddr);
in your app.config there will be only one configuration, pointing to some default server.
First of all, I admit I'm a newbie in WCF. Still not out of the training wheels.
I was assigned to develop a WCF service, and part of the requirements is that a sort of "session token" needs to be passed with each request as an HTTP cookie. (Predictably, such token needs be generated in the HTTP response headers of a successful "logon" call in such service).
Is this straightforward?
Disclaimer: you're not really supposed to do any of this, because it's forcing a WCF service to behave as a web service. But if you need cookies, read on.
If all you need is the session id, you can get it from:
OperationContext.Current.SessionId
If you need cookies, you'll need to jump through some hoops. The gist of it is (1) set asp.net compatibility, and (2) reference HttpContext.Current properties.
Your service will need to use a wsHttpBinding (or another binding that supports sessions). If create your project to be a WCF service hosted in IIS, you'll get these by default. You'll also need to set asp.net compatibility in the config file.
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="MyBinding" allowCookies="false" ... </binding>
</wsHttpBinding>
</bindings>
(see the link here for why I have allowCookies=false)
To enable sessions, on your WCF Service Contract, set the following
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IMyWcfService {...}
You may also want to set the ServiceBehavior on the service itself (PerSession is the default), and you'll need to set asp.net compatibility.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
public class MyWcfService : IMyWcfService {...}
Some relevant properties you then have access to:
// Gives you the current session id as a string
HttpContext.Current.Session.SessionID
// Indicates whether the service is using sessionless cookies
HttpContext.Current.Session.CookieMode
// Indicates whether the session id is stored in the url or in an HTTP cookie
HttpContext.Current.Session.IsCookieless
// The cookies themselves
HttpContext.Current.Request.Cookies
HttpContext.Current.Response.Cookies
// The session and cache objects
HttpContext.Current.Cache
HttpContext.Current.Session
A link on sessions in WCF Services:
http://msdn.microsoft.com/en-us/library/ms733040.aspx
HTH,
James
This topic on msdn could help you out http://msdn.microsoft.com/en-us/library/bb398778.aspx.
Also, this could help you out with hosting you`r WCF service inside IIS: http://msdn.microsoft.com/en-us/library/aa702682.aspx
and http://msdn.microsoft.com/en-us/library/bb332338.aspx (Hosting Using Internet Information Services)
This just answers your question partially, but will give you a head start with config.
In your config file under the service config section, create basic http bindings like that:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="myHttpBinding" allowCookies="true">
</binding>
</basicHttpBinding>
</system.serviceModel>
Then read up on wcf binding and endpoints configuration.