Custom ServiceHostFactory: The contract name 'IMetadataExchange' could not be found - c#

I'm following the example from the following page. http://msdn.microsoft.com/en-us/library/aa395224.aspx but I get the following error when running it
The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service MyServiceLibrary. Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract.
The MyServiceHostFactory is pretty much copied from that page and I am adding it into my route table like follows.
RouteTable.Routes.Add(new ServiceRoute("V1", new MyServiceHostFactory(), typeof(MyServiceLibrary)));
My Config file
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true" />
</system.webServer>
</configuration>
If I add config update(below) to my config file the service runs but that makes it find the ServiceMetaDataBehaviour and really makes the whole SelfDescribingServiceHost redundant?
ServiceMetadataBehavior mexBehavior = this.Description.Behaviors.Find<ServiceMetadataBehavior>();
Config
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>

I found the issue. I was getting this error because I forgot to add the mexBehaviour before calling AddServiceEndpoint()on the ServiceHost class
mexBehavior = new ServiceMetadataBehavior();
Description.Behaviors.Add(mexBehavior);

This should help you
And the error changes contract not found which might be because of missing endpoint address.

Related

C# WCFServiceApplication - Create Virtual Directory fails by using Local IIS -> Unable to create... Web Server 'http..." not found?

Im making a small WCFServiceApplication as homework for my school.
When I try to create a virtual directory (change from IISExpress to Local IIS) i get the following
Error:
Unable to create the virtual directory. The Web Server 'http://localhost/WcfServiceApp' could not be found.
Error in Detail with Configuration
Here is my Web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
And here my csproj.user
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<UseIISExpress>true</UseIISExpress>
<Use64BitIISExpress />
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<LastActiveSolutionConfig>Debug|Any CPU</LastActiveSolutionConfig>
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<StartPageUrl>
</StartPageUrl>
<StartAction>CurrentPage</StartAction>
<AspNetDebugging>True</AspNetDebugging>
<SilverlightDebugging>False</SilverlightDebugging>
<NativeDebugging>False</NativeDebugging>
<SQLDebugging>False</SQLDebugging>
<ExternalProgram>
</ExternalProgram>
<StartExternalURL>
</StartExternalURL>
<StartCmdLineArguments>
</StartCmdLineArguments>
<StartWorkingDirectory>
</StartWorkingDirectory>
<EnableENC>True</EnableENC>
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
I have tried to rermove the line true but still fails.
Thanks for help!
I found the answer!
in my IIS Manager the DefaultWebSite was missing.
I just created it manually and the error was gone.
Tutorial:
Recreate the default website in IIS

multi service contract in one endpoint c# wcf

I have a domain called cmsmanagement but it has several entity .I create a service for each entity in this domain .as you can see here :
So if my clients want to call my service ,they have to add each entity service one by one .I want to have one endpoint for all these service ,For example if the client call this mydomain/cmsmanagementservice.svc .all these services are called .
Here is my webconfig :
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
You can enable WS-Discovery feature in your project. More here: https://msdn.microsoft.com/en-us/us-us/library/dd456791(v=vs.110).aspx
In short, it can be done programmaticaly like this:
Uri baseAddress = new Uri(string.Format("http://{0}:8000/discovery/scenarios/calculatorservice/{1}/",
System.Net.Dns.GetHostName(), Guid.NewGuid().ToString()));
// Create a ServiceHost for the CalculatorService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
{
// add calculator endpoint
serviceHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), string.Empty);
// ** DISCOVERY ** //
// make the service discoverable by adding the discovery behavior
ServiceDiscoveryBehavior discoveryBehavior = new ServiceDiscoveryBehavior();
serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
// send announcements on UDP multicast transport
discoveryBehavior.AnnouncementEndpoints.Add(
new UdpAnnouncementEndpoint());
// ** DISCOVERY ** //
// add the discovery endpoint that specifies where to publish the services
serviceHost.Description.Endpoints.Add(new UdpDiscoveryEndpoint());
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
}
Then, when adding reference, you should be able to discover your services with such behaviors.

Exposing wcf service metadata

I'm following a tutorial on setting up a wcf service. I finished the changes it talks about, up to the first time it says to start the service. When navigating to the endpoint in my web browser I either get a 404 or 403.14 error. Initially the service was showing the folder structure, but I removed the attribute in the web.config file that was enabling that. I'm sure the issue is related to that file, but I'm not sure what else to change.
Link to the guide: http://www.c-sharpcorner.com/UploadFile/dhananjaycoder/four-steps-to-create-first-wcf-service-for-beginners/
Web.config file:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
<httpModules>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/>
</httpModules>
</system.web>
<system.serviceModel>
<services>
<service name="WcfCalculator.Calculator" behaviorConfiguration="Metadata">
<endpoint address="" contract="WcfCalculator.ICalculator" binding="basicHttpBinding"/>
<endpoint name="mex" address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Metadata">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="ApplicationInsightsWebTracking"/>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"
preCondition="managedHandler"/>
</modules>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<validation validateIntegratedModeConfiguration="false"/>
</system.webServer>
</configuration>
Service Contract:
using System.ServiceModel;
namespace WcfCalculator
{
[ServiceContract]
public interface ICalculator
{
[OperationContract]
double AddNumbers(double number1, double number2);
[OperationContract]
double SubstractNumbers(double number1, double number2);
[OperationContract]
double MultiplyNumbers(double number1, double number2);
[OperationContract]
double DivisionNumbers(double number1, double number2);
}
}
I think the 403.14 may be related to your folder permissions. What account is your application pool running under and the version of .NET Framework? Make sure you're app pool is targeting Framework 4.0. 403.14 - most likely you're trying to browse the root directory and directory browsing is disabled in IIS or your app pool doesn't have enough permissions. Than, try removing protocolMapping.
In VS2015 you can set .svc file as a start up document. Hitting "F5" will open that document in WCF Test Client (WcfTestClient.exe). Alternatively, you can right-click the .svc file and select "View in Browser".

List method says "No Data Received" (even though it does receive) in WCF Service Application in Visual Studio 10

I've made a WCF Service Application in Visual Studio 2010. Every method works except this one:
public List<Friend> SendFriendList(int id)
{
FyfDataContext db = new FyfDataContext();
List<Friend> friends = db.Friends.Where(P => P.PK_ID == id).ToList();
return friends;
}
It actually receives the data perfectly, but doesn't show it, when I test it in Google Chrome.
Here's the twist: Before this problem, I made the entire WCF Service App in Visual Studio 2012. And it worked perfectly there - but due to some other problems I had to go back to 2010.
Snippet of my IService.cs:
public interface IService2
{
[OperationContract]
[WebGet(UriTemplate = "/Friendlist?id={id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
List<Friend> SendFriendList(int id);
[OperationContract]
[WebGet(UriTemplate = "/Friendloc?id={id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Friendloc SendFriendLoc(int id);
}
The Friendloc method works - but like all the other methods, it returns an object, and not a list.
I suspect that the problem is something with the web.config - but I just can't find out what.
I do realize that VS12 made a 4.5 Framework, and VS10 made a 4.0.
Here's the Visual Studio 2010 Web.config:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="FyfConnectionString" connectionString="Data Source=.;AttachDbFilename=|DataDirectory|\Fyf.mdf;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name ="servicebehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restbehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name ="Fyf.Service1"
behaviorConfiguration ="servicebehavior" >
<endpoint name ="SOAPEndPoint"
contract ="Fyf.IService1"
binding ="basicHttpBinding"
address ="soap" />
<endpoint name ="RESTEndPoint"
contract ="Fyf.IService2"
binding ="webHttpBinding"
address ="rest"
behaviorConfiguration ="restbehavior"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
And here's the Web.config from Visual Studio 2012:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="FyfdbConnectionString" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Fyfdb.mdf;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name ="servicebehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restbehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name ="Fyf.Service1"
behaviorConfiguration ="servicebehavior" >
<endpoint name ="SOAPEndPoint"
contract ="Fyf.IService1"
binding ="basicHttpBinding"
address ="soap" />
<endpoint name ="RESTEndPoint"
contract ="Fyf.IService2"
binding ="webHttpBinding"
address ="rest"
behaviorConfiguration ="restbehavior"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
</service>
</services>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I've tried copying some of the elements from VS12 version to my VS10; such as aspNetCompatibilityEnabled to "true" and putting directoryBrowse in etc. But without luck.
I'm sorry if it's something extremely simple that I'm missing. This is my first WCF Service. Any help is much appreciated!
Don't quite know why this works, and the other method doesn't.
Made a DataContract called Userlist with (almost) the same attributes (just tested it with ID).
Definitely not as nice code, but it works. Still curious about the other problem though.
public List<Userlist> Friendlist(int id)
{
int i = 0;
FyfDataContext db = new FyfDataContext();
List<Friend> friends = db.Friends.Where(P => P.PK_ID == id).ToList();
List<Userlist> userlist = new List<Userlist>();
while (i < friends.Count)
{
Userlist u = new Userlist();
u.id = Convert.ToInt32(friends[i].FK_ID);
userlist.Add(u);
i++;
}
return userlist;
}

WCF endpoint not found

I'm following a tutorial in a book to implement push notifications for Windows Phone. This is the markup of the service:
<%# ServiceHost Language="C#" Debug="true" Service="Service.PushService" CodeBehind="PushService.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
As you see, a factory is added, although I don't really understand what it's for. When running the service, I get a "endpoint not found" error. When I remove the factory from the markup, the error disappears, but I get an empty page.
Any idea what could cause this error or how to fix it? If you need more code, please tell me.
Thanks
EDIT:
My web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
You are missing the endpoint configuration in your web.config.
Add this to your web.config:
<system.serviceModel>
<services>
<service name="Service.PushService">
<endpoint address="" binding="basicHttpsBinding"
contract="Service.IPushService" />
</service>
</services>
</system.serviceModel>
For those who absently implement the method in Service.svc that its definition is absent in IService causes the same exception.
This is forgotten
[OperationContract]
string CheckHMAC(string hMac);
But implemented
[WebInvoke(Method = "GET", UriTemplate = "/CheckHMAC/{hMac}")]
public string CheckHMAC(string hMac)
{//}

Categories