WCF Service Host using Console App - wcf

Is there a way to automatically add entries to the App.config of a console application that will be used a host for a WCF service or do I need to make those entries manually?
I am referring to the <system.serviceModel> section in App.config file to configure a WCF service.
Additional issues with Service library project's app.config
I understand the concept of .svc files and that those are needed only in case you want to host a service using IIS. To start with, I plan to self-host a service using cosole app. Now another issue that I am facing is with the web.config of my service library project. When I created the service library project, an app.config was automatically created and the service configuration was automatically generated. However, I had changed the class names and now I see an error in the app.config for <service name="MyServiceName"> parameter and also the an error on Service contract attribute.
What's wrong in the following configuration? I get an error with service name="ContactMgrService.ContactManager" and contract="ContactMgrService.IContactMgrService"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ContactMgrService.ContactManager">
<endpoint address="" binding="basicHttpBinding" contract="ContactMgrService.IContactMgrService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/ContactMgrService/Service1/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Service Contract
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using ContactMgrService.DataModel.Contact;
namespace ContactMgrService.Contact
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IContactMgrService
{
[OperationContract]
IList<ContactData> GetContactList(int? value);
}
}
Service Implementation class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ContactMgrService.DataModel.Contact;
namespace ContactMgrService.Contact
{
public class ContactManager : IContactMgrService
{
ContactContext db = new ContactContext();
public IList<ContactData> GetContactList(int? value)
{
IQueryable<ContactData> contacts = db.Contacts;
return contacts.ToList();
}
}
}

Your config file is incorrect. When specifying service name and endpoint contract values you need to specify the fully qualified name of the type containing the service or service definition:
<service name="ContactMgrService.Contact.ContactManager">
and
<endpoint address=""
binding="basicHttpBinding"
contract="ContactMgrService.Contact.IContactMgrService">
In response to your other questions:
Is it mandatory to have a project with svc files?
It is highly unorthodox if not impossible to use svc files in a console applicaiton. This is strinctly for IIS.
Is there a way to automatically add entries to the App.config
Nope you have to do this manually.

And do you strictly need to edit App.Config in order to define/edit service configuration?
Rather than that, I would suggest you doing it programmatically - check for example this link. Im not sure whether you want it for creating new endpoint or just changing the settings, but still, it can be done like that.

Its not mandetory to have svc file while using self hosting. it being helpfull for use outer world just like asmx files. my suggestion is to use the default configuration as refrence and create your own configs. as these consist of Address where service is geting hosted. Binding what kind of binding you want to use. and Contract what type of contract you wish to use.
Using WCFTestClient / Edit WCF Configuration utility will help you here.
https://msdn.microsoft.com/en-us/library/ms732009(v=vs.110).aspx
http://www.c-sharpcorner.com/UploadFile/Mahadesh/wcf-series-using-the-wcf-service-configuration-editor/
https://msdn.microsoft.com/en-us/library/ms731758(v=vs.110).aspx

Related

No Endpoint for WCF service in ASP.NET application

I have created and hosted a service http://www.royalbatteriesws.somee.com/Default.svc
I want to test my service for its functionality.
I have added a service reference in my Asp.Net web site called RoyalBatteriesWS
As no endpoint was added automatically in the web.config file, I had to add it manually.
web.config file:
System.ServiceModel and ServiceBehaviors sections:
<service name="RoyalBatteriesWS" behaviorConfiguration="HelloServiceBehavior">
<endpoint
address ="http://www.royalbatteriesws.somee.com/Default.svc"
binding="basicHttpBinding"
contract="RoyalBatteriesWS.IService">
</endpoint>
</service>
<serviceBehaviors>
<behavior name="HelloServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
I get an exception
Could Not find default Endpoint that references contract 'RoyalBatteriesWS.Iservice' in the ServiceModel client configuration section
Please can anybody point out my mistake?
I went through previous posts and I couldn't find what works for me.
Thanks
The name="..." attribute of your <service> must match exactly the fully-qualified name of the .NET class that implements that service.
This means: it has to be the exact class name and all namespaces of that class.
So most likely, your service class is called RoyalBatteriesWS - but there's a good chance it's stored in some namespace - so add that namespace to that attribute and you should be good to go!
On the other hand, since you said you added a service reference - do you really want to configure a service here - that's the server-side of things (where the actual service class is coded).
Don't you want to configure a class that consumes / uses that service - a client ??
If so - use the <client> tag (instead of <service>):
<client name="RoyalBatteriesWS">
<endpoint
address ="http://www.royalbatteriesws.somee.com/Default.svc"
binding="basicHttpBinding"
contract="RoyalBatteriesWS.IService">
</endpoint>
</client>

Could not find default endpoint element that references contract

I know this has been beaten to death, but I cannot get this to work as it should.
I have a WCF service with several contracts.
They all work fine when calling them directly e.g. http://merlin.com/CompanyServices/CompanyWcfService.svc/Get_Document_Dates_Received/223278
I have used this WCF service successfully on InfoPath Forms and Nintex Workflows.
Now I create a simple ASP.Net application, such as was done in http://www.webcodeexpert.com/2013/04/how-to-create-and-consume-wcf-services.html.
I was able to add a service reference as described in the article.
I added a button the form, and added the following code in the Button1_Click event:
protected void Button1_Click(object sender, EventArgs e)
{
ServiceReference1.CompanyWcfServiceClient x = new ServiceReference1.CompanyWcfServiceClient();
var result = x.Get_Document_Dates_Received("223278");
}
when I click on the button I get the error:
"Could not find default endpoint element that references contract 'ServiceReference1.ICompanyWcfService' 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."
So I tried adding the following to the web.config: (copied directly from the web.config file of the CompanyWcfService.
<system.serviceModel>
<services>
<service name="CompanyWcfServices.CompanyWcfService" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="CompanyWcfServices.ICompanyWcfService" behaviorConfiguration="webHttpEndpointBehavior" >
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
</endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding>
<security mode="None">
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name ="webHttpEndpointBehavior">
<webHttp helpEnabled ="true" faultExceptionEnabled="true" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
I get the same exact error, there has to be something else going on.
I finally gave up and called the service like this:
HttpWebRequest request = WebRequest.Create(#"http://merlin/Companyservices/CompanyWcfService.svc/Get_Document_Dates_Received/223278") as HttpWebRequest;
request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = null;
var result = "";
try
{
response = request.GetResponse() as HttpWebResponse;
if (response.StatusCode == HttpStatusCode.OK)
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
result = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
result = "";
}
I have spent hours reading posts and most of them suggest to copy the config information to the web.config file. This seems problematic to me (besides the fact that it doesn't seem to work). What if I need to consume a third party WCF service? Do I have to request the config information from the third party? And Visa Versa, if I create a WCF service designed to be consumed by third parties, do I need to provide them the config file as well?
The error indicates that you don't have an endpoint defined in the client configuration section. When you add the service reference to your project it should create the client section for you. If not then in the web.config for your app within the system.serviceModel section add the following
<client>
<endpoint
name="CompanyWcfService_webhttpBinding"
address="http://merlin.com/CompanyServices/CompanyWcfService.svc"
binding="webHttpBinding"
contract="CompanyWcfServices.ICompanyWcfService"
behaviorConfiguration="webHttpEndpointBehavior"
/>
</client>
If we have layered architecture make sure to
1) add app.config in "all projects"
2) add service config details in all app.config
3) run the project
If your project is referencing a library and trying to use the WCF functions from the functions of that library, then you can try copying the client endpoint from the project config file to the dll's config file. Some thing like this happened to me a while ago as the library that I referenced in the project would not use the project config file (in which the client end point was configured since the service was being referenced there) but its own so the result was the system could not find the endpoint configurations.
In my case I had a WPF project referencing an external UserControl which had a service reference. I had to add the service reference to the main project as well.
Adding binding and client values from app.config to default web.config resolved my issue.
Actually the trick to this one was to use the svcutil.exe to create the proxy. I had been trying to create the proxy through Visual Studio "Add Service" wizard. Once I did that, the configuration was a breeze.
SvcUtil.exe
When it comes down to WCF, it typically requires the configuration to be defined within the config file of the executable that calls it.
Thus, if you are unfortunate enough to having to call a WCF DLL from within a VB6 program (as may be the case when using a COM-interop .NET module, for example), and you need to debug the VB6 program, then you will need to create a VB6.exe.config file in the directory where VB6.exe is located.
Failing to do the above may cause a "Could not find default endpoint element that references contract".
As a workaround, one can load the dll's config file at runtime and then call the constructor of the used Service with a Binding and an EndpointAddress as parameters (obtained from the dll's config).

Simplest Console Hosted WCF Service generates a 404 when browse to it

I have the very simplest Console based host for a simple WCF service. The app config for the service is:
<system.serviceModel>
<services>
<service name="MagicEightBallServiceLib.MagicEightBallService"
behaviorConfiguration="EightBallServiceMEXBehavior">
<endpoint address=""
binding = "basicHttpBinding"
contract = "MagicEightBallServiceLib.IEightBall" />
<!-- Enable the MEX endpoint-->
<endpoint address="mex"
binding ="mexHttpBinding"
contract ="IMetadataExchange" />
<!--Need to add this so MEX knows the address of our service -->
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MagicEightBallService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="EightBallServiceMEXBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
The host program shows its running perfectly:
** Console Based WCF Host *
***** Host Info ******
Address: http://localhost:8080/MagicEightBallService
Binding: BasicHttpBinding
Contract: IEightBall
Address: http://localhost:8080/MagicEightBallService/mex
Binding: MetadataExchangeHttpBinding
Contract: IMetadataExchange
**************************************************
The service is ready
When I attempt to browse to or generate a proxy I get:
HTTP Error 404.0 - Not Found
I can't figure out what's wrong. You can't get any simpler than this!
I have faced the same problem when reading Troelsen's book and could not find any answer online. Anyway it seems that the problem is in the project type for MagicEightBallLib. Troelsen suggests that you create a Visual C# -> Windows -> Class Library project, but he does not explain what modifications you need to make for it to work. If you instead use the Visual C# -> WCF -> WCF Service Library project, it will automatically start the WcfTestClient.exe, and add new tab in project's Preferences called "WCF Options". I tried to compare the differences between .csproj files for both types of projects but there is just too many.
So the solution is to just start with the WCF Service Library project type instead of Class Library, and adjust names of interfaces and classes so they fit what is in the book.
If anyone knows which particular parts of the .csproj file are responsible for enabling this, I'd very much like to hear about it.
Hope this helps.
Instead of using localhost:8080 use 127.0.0.1:8080. That's how I got the example to work on my windows 10 machine.

How can I register a WCF service programmatically within an IIS environment

Let's say we have 2 projects with following layout
Project "web"
global.asax (I thought of this destination for registration within eg void Application_Start(System.Object sender, System.EventArgs e)
web.config
Project "wcf"
DemoService.cs
IDemoService.cs
web.config would look like this
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="fooBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="wcf.DemoService"
behaviorConfiguration="fooBehavior">
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<endpoint address=""
binding="wsHttpBinding"
contract="wcf.IDemoService" />
</service>
</services>
</system.serviceModel>
</configuration>
So ... now ... somewhere (as mentioned above I thought of global.asax) I need to register, that when browsing to URI wcf.DemoServiceget's resolved and for a mex-request the wcf.IDemoService gets resolved for reading the attributes to get a WSDL.
This would usually be done by creating a .svc file and put header in the first line, e.g.:
<%# ServiceHost Language="C#" Debug="true" Service="wcf.DemoService" %>
In e.g. a console application by
var serviceHost = new ServiceHost(typeof (wcf.DemoService));
serviceHost.Open();
And combine this with a host element within the service element to specify the URI - or use another ctor-overload of ServiceHost
But I would rather go for a static registration (or any web.config registration which works for IIS 7.5) - is this possible? If so, how?
WCF 4 (.NET 4.0) offers both code based registration of services and configuration based registration of services.
Code based configuration is achieved through ASP.NET Routing by new ServiceRoute:
RouteTable.Routes.Add(new ServiceRoute("DemoService",
new ServiceHostFactory(), typeof(wcf.DemoService));
Routes are usually used with REST services but it works for SOAP services as well.
Registering service in configuration is called configuration based activation. You will define virtual .svc file in web.config:
<serviceHostingEnvironment>
<serviceActivation>
<add relativeAddress="DemoService.svc" service="wcf.DemoService" />
</serviceActivation>
</serviceHostingEnvironment>
In both cases you are defining only relative path to your service because base address is always specified by your web site hosted in IIS.

Service as ASMX and WCF

I have an existing web service (ASMX) that needs to be exposed as WCF as well. ASMX must remain and preferably with no change on the client. As per this I have configured as follows. The service layer is generated with CodeSmith and whilst I didn't write these services I know they are fine as they have been used in the wild for many years. The names have been changed to protect the innocent .. grin.
In the service layer there is an XXX.YYY.MyService class generated by CodeSmith which is double decorated with
[ServiceContract( Namespace = "http://XXX.YYY" )]
and
[WebService( Namespace = "http://XXX.YYY", Name = "MyService" )]
I have also created an empty interface XXX.YYY.IMyService which is implemented by MyService. At this point I can consume the ASMX service with no issues.
Now I add a .svc file to the service layer which contains ...
<%# ServiceHost Language="C#" Debug="true" Service="XXX.YYY.MyService" %>
... and I configure the service layer's web.config with ...
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="XXX.YYY.MyService">
<endpoint binding="basicHttpBinding" contract="XXX.YYY.IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
If I build and then try and make a service reference in Visual Studio 2010 to the service, I see both .ASMX and .SVC versions of MyService. Expanding the .svc branch in the Add Service Reference dialog results in an error referring to an empty XML document.
If I examine the event log I get ...
WebHost failed to process a request.
Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/39449526
Exception: System.ServiceModel.ServiceActivationException: The service '/System/MyService.svc' cannot be activated due to an exception during compilation. The exception message is: The contract name 'XXX.YYY.IMyService' could not be found in the list of contracts implemented by the service 'MyService'.. --->
... but MyService is marked as implementing IMyService ...
public partial class MyService : IMyService
I have also tried changing the contract attribute for the service to MyService instead of the interface. That works but for the client code breaks as any attempt to create an instance of the service fails as it is now an interface.
I hope that makes sense. Please feel free to ask anything extra. I have tried to be as detailed as possible.
(No IIS involved .. this is purely in Visual Studio 2010).
Thanks.
Your code implements IMyService are you sure that it is XXX.YYY.IMyService.
The answer for me was to move the [ServiceContract] and [OperationContract] declarations to the interface. This has fixed the issue for me.
HTH.