multi service contract in one endpoint c# wcf - c#

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.

Related

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".

Web Service Rest Error http 400

I have a WebService that I use only for data.
Using the service:
[WebGet(UriTemplate = "maq/?v={v}",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
List<VoltaPDA> GetAllta(int v);
it works perfectly;
using this function in the same webService:
[WebGet(UriTemplate = "ped/?T={ti}&V={Vo}",
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
List<Pedido> GetSub(string ti,string Vo);
I get the error HTTP 400 The curious that the test through a browser directly both work, when I use them on my Windows Mobile 6.5 application the second function returns HTTP 400 error.;
Can you imagine what it might be?
Both access the same databaseSql Server 2012 , and the WebService hosted in IIS 8.5
webConfig:
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="BD_S_V10ConnectionString" connectionString="Data Source=NUNO-PC;Initial Catalog=BD_S_V10;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<globalization culture="pt-PT" uiCulture="pt-PT" />
</system.web>
<system.serviceModel>
<!-- REST -->
<services>
<service name="WcfServicePedido_v7.ServicePedido">
<endpoint name="RestEndPoint" contract="WcfServicePedido_v7.IServicePedido" binding="webHttpBinding" address="" behaviorConfiguration="restBehavior"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="restBehavior">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
<!-- REST -->
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false 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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment 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>
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="Traces.svclog" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId"/>
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
It is common that the Default 400 response is returned for Mime-Type mismatches and malformed requests (body and sometime URLs) from the client.
In this case, I would recommend checking the Content-Type header sent from the mobile application in the second request to make sure its something like text/xml.

ServiceAuthorizationManager not called

I have a very simple ServiceAuthorizationManager (perhaps the simplest) and have followed various tutorials on the web but for some reason none of my breakpoints are hit and this leads to me thinking that its not being called.
Created a WCF Service Application named it WcfTest
Kept the default classes Service1.svc, IService.cs but changed method to return a string
Added a new class that inherits from ServiceAuthorizationManager
Overridden the method CheckAccessCore()
Adjusted web.config so that it uses this manager class
Run the WCF Service Application
Assembly is called WcfTest
All classes live in root of the project no folders or anything
Invoke the method and at this point I am expecting my ServiceAuthorizationManager to be called or am I wrong here? I thought the whole purpose of it was to hit the custom ServiceAuthorizationManager on every request received?
Thanks in advance, Onam.
Any more info required let me know, will be watching this like a hawk as I am very confused when this should apparently be very simple.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "/getIt",ResponseFormat=WebMessageFormat.Json)]
string GetIt();
}
public class Service1 : IService1
{
public string GetIt()
{
return "boo!";
}
}
public class MyServiceMan : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
try
{
//Some stuff here breakpoint set on above line not hit
return false;
}
catch (Exception e)
{
return false;
}
}
}
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfTest.Service1">
<endpoint address=""
contract="WcfTest.IService1"
binding="webHttpBinding">
</endpoint>
</service>
</services>
<behaviors>
<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"/>
<serviceAuthorization serviceAuthorizationManagerType="WcfTest.MyServiceMan,WcfTest" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Are you missing endpoint behavior?
behaviorConfiguration="WebHttpEndpointBehavior"
<endpointBehaviors>
<behavior name="WebHttpEndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
I had the same problem. I resolved it by setting breakpoint in my CustomAuthorizationManager CheckAccessCore method and start debugging my WCF project in Visual Studio. Then I run from my desktop WCF Client App and execute some method and it's done.

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

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.

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