WCF From Class Library - hosting in IIS and wsdl generation - c#

Allmost all day today I am trying to research on WCF and one of my aim was to create a WCF service manually (or almost so).
Based on few articles on web on how to structure WCF application I have created contracts project which contain service interfaces and implementation project. Both have Runtime.Serialization
I have created app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="FulFillmentServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="FulFillmentServiceBehaviour"
name="Project.Services.Fulfillment">
<endpoint address="http://localhost:8080/Services" binding="basicHttpBinding"
bindingConfiguration="" contract="P.Infrastructure.Services.IFulfillment" />
<endpoint binding="mexHttpBinding" bindingConfiguration="" />
</service>
</services>
</system.serviceModel>
</configuration>
1) How can I host this service in IIS
I already created virtual directory pointing to folder containing project Services (url http://localhost:8080/Services)
2) How to create wsdl file so that I can use SOAPUI to test it
I tried adding a file "fulfillment.svc" with markup
<%# ServiceHost Language="C#" Debug="true" Service="Project.Services.Fulfillment" CodeBehind="Fulfillment.cs" %>
for the purpose of testing but it gave error
The type Project.Services.Fulfillment', provided as the Service attribute value in the ServiceHost directive could not be found.
Update 1******
just found this on net - may be this will help. one imp ino is that i will need web.config
http://wncadmb026d.na-idm.na-gad.nec.com/Services/Fulfillment.svc?wsdl
Update 2:*****
SOAP UI is able to generate SOAP request but gers http 404 as response...
http://www.aspfree.com/c/a/ASP.NET/Developing-a-WCF-Service-Library-and-Hosting-it-as-WCF-Web-Service-Using-VS2K8/

I was able to get the basic service up with help from
http://www.aspfree.com/c/a/ASP.NET/Developing-a-WCF-Service-Library-and-Hosting-it-as-WCF-Web-Service-Using-VS2K8/
and
http://msdn.microsoft.com/en-us/library/ms733766(v=VS.90).aspx
I copied service model section from app.congig to web.config
I also had to chaNGE BUILD FOLDER TO /BIN Instead of /bin/debug/
will add more code tomorrow morning

For WSDL page you have the correct attribute:
<serviceMetadata httpGetEnabled="true" />
And you can access it by adding ?wsdl to the URL, ie http://localhost:8080/Service.svc?wsdl
As for the error, I think the problem is that you are not using the .svc extension:
<%# ServiceHost Language="C#" Debug="true"
Service="Project.Services.Fulfillment" CodeBehind="Fulfillment.svc.cs" %>
You are using a .svc file, right?
If you are not using an .svc file one thing to do is use routing, see this link for an example: http://geekswithblogs.net/michelotti/archive/2010/08/21/restful-wcf-services-with-no-svc-file-and-no-config.aspx

Related

My wcf client side shows exception but WcfTestClient Tool works fine

I have coded a WCF server side with netTcpBinding. Then I coded a client side. But it shows exception while excute "var sc = new CommondServiceClient();" at runtime. What should I do?
Below is the exception message:
System.InvalidOperationException
HResult=0x80131509
Message=Could not find default endpoint element that references contract 'ICommondService' 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.
Source=System.ServiceModel
StackTrace:
......
I have tried something:
I can consume the services with WcfTestClient.
The service reference is added by visual studio "add service reference...". I guess I get the service mex data. But I meet runtime exception like above
I also tried generate code with svcutil tool, but it still not work
Here is the wcf config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="ServiceContractor.CommondService">
<endpoint address="" binding="netTcpBinding" contract="ServiceContractor.ICommondService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="False" httpsGetEnabled="False"/>
<!-- 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>
</system.serviceModel>
</configuration>
It's a self host wcf service:
var baseAddress = new Uri($"net.tcp://localhost:{PORT}/Company/service");
_host = new ServiceHost(typeof(CommondService), baseAddress);
try
{
var smb = _host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null) _host.Description.Behaviors.Add(new ServiceMetadataBehavior());
_host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
_host.AddServiceEndpoint(typeof(ICommondService), new NetTcpBinding(), "");
_host.Open();
}
catch (CommunicationException ce)
{
_host.Abort();
}
I have no idea what is wrong. What document I should ask for? Can you help me?
But I have another question now. Is it possible to get rid of the configuration. So that the application just needs the DLL and knows nothing about the WCF service.
Generally speaking, there are two ways to call the WCF service (Soap service) in the web application.
Generate the client proxy class by adding service reference, this way
commonly need to configure the service settings in the configuration
file(web.config), most of service information need to be called are
stored in the configuration file. For class library project, we have
to migrate the configuration to the configuration file of the actual
project.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
Use the ChannelFactory to create the communication channel, we set
up the service configurations programmatically. From your
description, this way to call the web service might be the
appropriate solution. Customize the service configuration
programmatically in the code. One thing must be noted that all the
service configuration is hard-coded, such as binding type and service
endpoint information. You could refer to the following documents.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-the-channelfactory
Feel free to let me know if there is anything I can help with.

IIS hosted wcf returns me blank page

I have a wcf application. It has "Service1.svc" file. In the web.config file I specified
http://localhost:2005/EmployeeService.svc
as an endpoint. When clicking browse from Visual Studio there is no problem. But, when I hosted it on IIS server I get a blank page. The interesting thing is, If I remove the address from the web. config this time I can see the service at this address.
http://localhost:2005/EmployeeService.svc
web.config file is as below:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="EmployeeServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="EmployeeServiceBehaviour" name="EmployeeConfiguration">
<endpoint address="http://localhost:2005/EmployeeService.svc" binding="basicHttpBinding"
bindingConfiguration="" contract="IEmployeeConfiguration" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Could you please explain, why I get a blank page on IIS when I provide the adress.
This may happen in HTTP Activation is not installed in Programs and Features in your Windows installation. Check HTTP Activation for both .Net 3.5 and 4.6 to enable opening WCF service via HTTP request to .svc file hosted in IIS.
I think you can remove all text on the address before Service.svc. This might be an issue with different urls.
When you specify the address part, you tell WCF the service is only available on that address. When going through the endpoints, WCF will not find one that matches the given URL and bail out.
When you have multiple endpoints you need the address field. Otherwise you don't.
Read http://msdn.microsoft.com/en-us/library/ms733749(v=vs.110).aspx
And in particular this part:
When hosting with IIS, you do not manage the ServiceHost instance yourself. The base address is always the address specified in the .svc file for the service when hosting in IIS. So you must use relative endpoint addresses for IIS-hosted service endpoints. Supplying a fully-qualified endpoint address can lead to errors in the deployment of the service.
Check if Service attribute in SVC markup equals your implementation class.
Check endpoint contract name. It has to be exactly full name of your interface. Don't add assembly name, it won't work.
Check <serviceMetadata httpGetEnabled="true" />. If false, you get blank page too.
And 4th change which helped me (but I have no idea why): Remove behavior name <behavior name=""> and remove behaviorConfiguration attribute from service element. It becomes default so the behavior will be used anyway.
Be sure you made an Application Pool with active user like this: https://stackoverflow.com/a/19654633/2148387
Be sure you created Web Application where your WCF is hosted
Check if AppPool and WebApp are running
Enable Directory Browse in your Web.config like here: https://stackoverflow.com/a/19630263/2148387

Blank/Empty WSDL file

I'm struggling to have my WCF web service output a wsdl file with no luck so far (it's empty?).
the svc file:
<%# ServiceHost Language="C#" Debug="true" Service="xxx.WCF.SubsetMID" CodeBehind="SubsetMID.svc.cs"
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
%>
the cs file :
namespace xxx.WCF
{
[ServiceContract(Namespace = "SubsetMID")]
public interface ISubsetMID
{
[OperationContract]
[WebInvoke(BodyStyle=WebMessageBodyStyle.Wrapped)]
long[] GetMIDs(Guid guid, int subsetID);
}
[DataContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class SubsetMID : ISubsetMID
{
public long[] GetMIDs(Guid guid, int subsetID)
{
[...]
return returnValue;
}
}
}
My web config file :
<system.serviceModel>
<services>
<service name="xxx.WCF.SubsetMID">
<endpoint address=""
binding="wsHttpBinding"
contract="xxx.WCF.ISubsetMID" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
multipleSiteBindingsEnabled="true"
aspNetCompatibilityEnabled="true"
/>
</system.serviceModel>
I don't get any error when I access the wsd (http://.../SubsetMID.svc?wsdl) but it's just a blank page.
The following is a best guess based on some research I did - I'm not that familiar with RESTful WCF services, so I might be wrong but this should give you a starting point at least.
You didn't specify, but it looks like you're trying to write a RESTful WCF service. I'm not entirely certain, because you use wsHttpBinding in your endpoint, but you also decorate the method in the service with [WebInvoke].
In any event, REST services do not have WSDLs - that's a SOAP thing. Additionally, I believe WCF supports REST with the webHttpBinding. As you are using WebServiceHostFactory in your .svc file, I think this is what is happening:
You do not have any webHttpBinding endpoints defined. WCF will create a default webHttpBinding endpoint, with the address based on the location of the .svc file. However, when default endpoints are used according to WebServiceHost Class:
...the WebServiceHost also disables the HTTP Help page and the Web Services Description Language (WSDL) GET functionality so the metadata endpoint does not interfere with the default HTTP endpoint.
If you're writing a REST service, you won't need a WSDL. If you're planning on having a SOAP service, then use ServiceHostFactory in your .svc file and remove the [WebInvoke] attribute from the method.
Again, this is a (relatively) educated guess, and it may be wrong, but it's a place to start.
Im guessing that you are using a wcf service website project which contains the svc file. if you dont, i strongly recommend you to do that and set it as the startup project in your solution, so you could debug it properly. for me, and good chances that for you too if you followed codeproject step by step instructions, the problem was that i didn't reference the wcf services from the website, thus the directive in the svc couldn't find the service. hope i helped

Hosting WCF Service on IIS

I am new to WCF and windows mobile development. I am trying to create an occasionally connected application that utilizes the MSFT sync framework and this requires the use of a WCF service.
I have a visual studio project containing my smart device project, a WCF Service Library project, and a WCF Service website project.
The service is hosted fine on my local machine not using IIS and I can access it at http://localhost:55149/ElectricReadingServiceSite/ElectricReading.svc
However when I add it to IIS it gives me an http 404 resource cannot be found error. I cannot figure out why it thinks the resource is not there.
Here is my web.config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="MiddleTierServiceLibrary.ElectricReadingCacheSyncService"
behaviorConfiguration="MiddleTierServiceLibrary.ElectricReadingCacheSyncServiceBehavior">
<endpoint
address=""
binding="basicHttpBinding"
contract="MiddleTierServiceLibrary.IElectricReadingCacheSyncContract">
<identity>
<dns value="10.104.238.123"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MiddleTierServiceLibrary.ElectricReadingCacheSyncServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
My ElectricReading.svc looks like this:
<%# ServiceHost Language="C#" Debug="true"
Service="MiddleTierServiceLibrary.ElectricReadingCacheSyncService" %>
Any help is greatly appreciated!
EDIT: Are there any tools or steps I can take to get a better idea of what is going wrong? The 404 error does very little to help me.
There can be a number of reasons to why this could be happening.
Some of them might include:
Make sure you uploaded the assembly in the Bin folder
You have set up a website on IIS, but you are not accessing it with
the correct address(make sure the port is correct)
Your application pool is not set up for the website(if you are using
.NET 4.0 you need to set the applictation pool to version 4.0) In IIS manager go to ApplicationPools and set the pool to the version of .NET that you are using
Try using Fiddler. It should log the calls it makes and thus give you a little more detail on what it is not finding.

WCF .svc worked but not the config file

I am trying to use the configuration file to define endpoint and services information. I have a very simple code that contain OneWay service and a Duplex service. The OneWay worked when I haven't try to alter the configuration file.
Now, I want to use the configuration file to define both service.
Service1 contract name is IOneWayService and the Service2 contract name is ICallBackService.
Both have implemented code in their concrete respective classes name OneWayService.svc.cs and CallBackService.svc.cs.
The configuration file at this moment look like that :
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<serviceActivations>
<add relativeAddress="OneWayService.svc" service="TestingWcf.OneWayService"/>
<add relativeAddress="CallBackService.svc" service="TestingWcf.CallBackService"/>
</serviceActivations>
</serviceHostingEnvironment>
<services>
<service name="TestingWcf.OneWayService">
<endpoint address="http://localhost:60847/One"
binding="wsHttpBinding"
contract="IOneWayService" />
</service>
<service name="TestingWcf.CallBackService">
<endpoint address="http://localhost:60847/Two"
binding="wsHttpBinding"
contract="IDuplexService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
I always have this error when trying to execute the OneWayService via this url : http://localhost:60847/OneWayService.svc
The contract name 'IOneWayService'
could not be found in the list of
contracts implemented by the service
'OneWayService'.
Anybody have an idea why?
Edit
I have removed the multipleSiteBindingsEnabled= true from the servinceHostingEnvironment tag and in the contract added the namespace and I could runt the OneWayService.
Also, the Duplex cannot be bound to the wsHttpBinding. I had to change it to NetTcpBinding. But, I had an other error with the Duplex :
Configuration binding extension
'system.serviceModel/bindings/NetTcpBinding'
could not be found. Verify that this
binding extension is properly
registered in
system.serviceModel/extensions/bindingExtensions
and that it is spelled correctly.
From this point, I am lost again.
Edit 2
I did an error in the binding name. I had a capital letter for NetTcpBinding and it does require a lowercase: netTcpBinding. However, it's still not working, now I have:
The protocol 'net.tcp' is not
supported. >.< !!!
OK, that explains it - Visual Studio by default uses the built-in Cassini web server (unless you've already switched to using IIS Express) - and that server doesn't support anything but plain http.
Cassini doesn't support net.tcp and anything like that.
You will need to start using a separate IIS virtual directory and first enable all the necessary support stuff (in the Add/remove Windows Features dialog)

Categories

Resources