I am fairly new to the C# world so I don't know much. I can't even find simple step by step documentation on how to set up a simple service without using the built in templates in Visual Studios.
I would prefer to use the following class and web.conf to make my service. I do not want to use anything that is going to depend on visual studios or IIS magic like .asmx files.
I can't seem to get my server to respond to it. When i go to localhost:8152/02/service or localhost:8152/02/service/echo2, I get a 404 error.
I have the following in my web.conf file.
<system.serviceModel>
<services>
<service name ="hessian.test.HessianService" behaviorConfiguration="HttpGetMetadata">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8152/02/service"/>
</baseAddresses>
</host>
<endpoint address="/echo2" contract="hessian.test.HessianService.sayHello" binding="wsHttpBinding"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name ="HttpGetMetadata">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings />
<client />
</system.serviceModel>
This is in my .cs file
namespace hessian.test{
public class HessianService : WebService, testInterface
{
public void runVoid(int count)
{
}
public string sayHello()
{
return "Hello";
}
public string repeatMe(string s)
{
return s;
}
}
}
Any help would be appreciated.
I suggest taking a look at Getting Started with WCF. WCF operates with .svc files instead of .asmx. Here's a comparison.
In your example you'll need to create contracts like so:
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace WcfService1
{
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(UriTemplate = "sayhello")]
Stream SayHello();
}
}
Then an implementation can look like this:
using System.IO;
using System.ServiceModel.Web;
using System.Text;
namespace WcfService1
{
public class Service : IService
{
public Stream SayHello()
{
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return new MemoryStream(Encoding.UTF8.GetBytes("hello"));
}
}
}
And of course, the all important web.config, notice the serviceHostingEnvironment element, it is required if you don't want to create a .svc file, although a .svc file doesn't require IIS, you can host it anywhere.
<system.serviceModel>
<services>
<service name="WcfService1.Service">
<endpoint address="" binding="webHttpBinding" contract="WcfService1.IService"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment>
<serviceActivations>
<add factory="System.ServiceModel.Activation.ServiceHostFactory" relativeAddress="./sayhello.svc" service="WcfService1.Service"/>
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
There are quite a few things you need to get right before the service can even work:
applying ServiceContract and OperationContract to the service and operation declarations respectively
applying WebGet attribute to the operation so that it'll respond to a GET request
configuring service and behaviors so WCF can read them and handle things appropriately
WCF is powerful but it's also quite a bit to take in, which was why I suggested WebApi at first. It has a much more gentle learning curve, assuming you want to use REST as opposed to SOAP. There are also alternatives like NancyFx and ServiceStack
Related
The Problem
I am attempting to create a Rest service using WCF. I have created a WCF class in my call stack namespace called "Coronado.HUB" as shown below. When I make an http request to the service I get a 404 error.
The Source Code
using Coronado.HUB.Model;
using Coronado.HUB.Service;
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace Coronado.HUB
{
/// <summary>
/// Returns Driver By ID
/// </summary>
[ServiceContract]
public interface IDriverService
{
[OperationContract]
[WebGet]
Driver GetDriverById(Guid id);
}
/// <summary>
/// Returns Driver Object By ID
/// </summary>
public class DriverService : IDriverService
{
public Driver GetDriverById(Guid id)
{
return DriverServiceProvider.Instance.GetDriverById(id);
}
}
}
Accordingly, in my ASP.NET project, I have added the following DriverService.svc file with the following reference
<%# ServiceHost Service="Coronado.HUB.DriverService" %>
The Configuration
Finally, I added the following configuration to my web.config
<system.serviceModel>
<services>
<service name="Coronado.HUB.DriverService">
<endpoint address="" binding="webHttpBinding" contract="Coronado.HUB.IDriverService" behaviorConfiguration="RestService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/XXX/DriverService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RestService">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Bare" />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
I have been trying to resolve this issue for a day and a half and I cannot get it to work. I would be grateful if someone could show me where I have gone wrong. Thank you for your time and consideration.
-- Update --
The URL I am trying to resolve is as follows
http://localhost/XXX/DriverService.svc/GetDriverById?id=F200A17F-9E03-41EB-90FB-01B8665246BB
The problem I encountered was caused because WCF was not registered with IIS. It is my understanding, pre .Net 4.0 - this is done via the command line. In my case, I used Programs & Features. This cleared up the problem
For additional information ref: IIS 7 not recognizing svc file
I'm trying to add a WCF service to my ASP.NET MVC application. After setting it up, I get an error whenever I want to test it.
Here is my code:
BackgroundTask.svc
public class BackgroundTask : IBackgroundTask
{
public void ShutdownVm()
{
}
public void UpdateTable()
{
}
}
IBackgroundTask.cs
[ServiceContract]
public interface IBackgroundTask
{
[OperationContract]
void ShutdownVm();
[OperationContract]
void UpdateTable();
}
Web.config
<system.serviceModel>
<services>
<service behaviorConfiguration="bgtBehaviour" name="IsolutionsAzureManager.Controllers.BackgroundTask">
<endpoint address="BackgroundTask" binding="basicHttpBinding"
bindingConfiguration="" name="" contract="IsolutionsAzureManager.Controllers.IBackgroundTask" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:44304/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="bgtBehaviour">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
So, whenever I want to test my WFC service, I get this error:
Error: Cannot obtain Metadata from https://localhost:44304/Controllers/BackgroundTask.svc
Error: The HTML document does not contain Web service discovery information.
Can anyone see the mistake?
Because you are attempting to acquire the mex endpoint over Https, you'll also need to switch to mexHttpsBinding and
to enable the httpsGetEnabled setting:
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
Alternatively, obtain the endpoint via http (http://localhost:44304/Controllers/BackgroundTask.svc) and then just switch back to https once the client has built the service reference artifacts.
I have a classic WCF webservice. Few weeks ago, in order to answer to a client demand, I added Rest management to my webservice.
But, at the beginning of the week, another client said to me its system can only manage XML-RPC. So he needs to connect to my webservice via this protocol.
So I found this : Configuring XML-RPC behavior for IIS-hosted .SVC file?
First, I compiled the Microsoft.Samples.XmlRpc in order to add it to my project. Two Dll appears : Microsoft.Samples.XmlRpc & Microsoft.ServiceModel.XmlRpc
Then, I created a XmlRpcEndpointBehaviorExtension class, the same as the post above :
namespace WsZendesk
{
public class XmlRpcEndpointBehaviorExtension : BehaviorExtensionElement
{
protected override object CreateBehavior()
{
// this comes from Microsoft.Samples.XmlRpc
return new XmlRpcEndpointBehavior();
}
public override Type BehaviorType
{
get { return typeof(XmlRpcEndpointBehavior); }
}
}
}
After, I created my interface for Xml-Rpc :
namespace WsZendesk
{
[ServiceContract]
public interface IWsZendeskRpc
{
[OperationContract(Action = "wszendesk.GetUserIdFromBarcode")]
void GetUserIdFromBarcode(String sXmlIn, out String sXmlOut);
}
}
Finaly, I modified my web.config in order to allow RPC :
<system.serviceModel>
<services>
<service name="WsZendesk.WsZendesk" behaviorConfiguration="WsZendeskServiceBehavior">
<endpoint address="rest" behaviorConfiguration="restfulBehavior"
binding="webHttpBinding" bindingConfiguration="" name="RESTEndPoint"
contract="WsZendesk.IWsZendeskRest" />
<endpoint address="xmlrpc" behaviorConfiguration="xmlRpcBehavior"
binding="webHttpBinding" bindingConfiguration="" name="RPCEndPoint"
contract="WsZendesk.IWsZendeskRpc" />
<endpoint address="" behaviorConfiguration=""
binding="basicHttpBinding" bindingConfiguration="" name="SOAPEndPoint"
contract="WsZendesk.IWsZendesk" />
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="xmlRpc"
type="WsZendesk.XmlRpcEndpointBehaviorElement, WsZendesk" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp />
</behavior>
<behavior name="xmlRpcBehavior">
<xmlRpc />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="WsZendeskServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Visual Studio said he don't know the child element 'xmlRpc'. So, when I try to launch my webservice, the same error appears during the execution.
Anybody can help me to use Xml-Rpc with my existing webservice ?
For information, my project is in C# 4.
It was not this:
<add name="xmlRpc"
type="WsZendesk.XmlRpcEndpointBehaviorElement, WsZendesk" />
But this:
<add name="xmlRpc"
type="WsZendesk.XmlRpcEndpointBehaviorExtension, WsZendesk" />
I'm trying to add a WCF service to my MVC project to have a general place to put my ajax methods but when i try to call its' methods simply by browsing to the url (e.g. ../Service.svc/HelloWorld) or calling it with jquery ajax I get a 404 page instead.
If i do the same thing in a webforms project, it works without any problem. What am I doing wrong here? Is this not the best practice place to keep ajax methods? Like i said: I want a general place to keep my ajax methods that might be reused from several views so i dont want to put them in the controller of the view if possible
My code:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1:IService1
{
public string HelloWorld()
{
return "HelloWorld";
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet]
string HelloWorld();
}
My configuration:
<system.serviceModel>
<services>
<service name="WebApplication1.Service1">
<endpoint address=""
behaviorConfiguration="AJAXEndpoint"
binding="webHttpBinding"
contract="WebApplication1.IService1" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="AJAXEndpoint">
<webHttp />
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="1" />
</system.serviceModel>
You have to add a ServiceRoute in your Global.asax. You have a 404 simply because there are no routes for this request.
For example this could be
routes.Add(new ServiceRoute("ThePath", new WebServiceHostFactory(), typeof(YourService)));
+1 for asp.net Web Api : this is definitely the recommanded way of building a web api in asp.net, especially in an existing mvc project.
I have complete exhausted resources on trying to get NetNamedPipeBinding for my WCF Service working. I was able to get the NorthwindService example working found here.
For the NorthwindService example, I have the following:
namespace NorthwindServices
{
public class Customer : ICustomer
{
public string GetCustomerName(int CustomerID)
{
return CustomerID.ToString();
}
}
}
namespace NorthwindServices
{
[ServiceContract]
public interface ICustomer
{
[OperationContract]
string GetCustomerName(int CustomerID);
}
}
And the configuration for the example is the following:
<system.serviceModel>
<services>
<service name="NorthwindServices.Customer"
behaviorConfiguration="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/NorthwindServices/Customer"/>
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="CustomerService" binding="netNamedPipeBinding" contract="NorthwindServices.ICustomer"/>
<endpoint address="CustomerService/mex" binding="mexNamedPipeBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- 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>
I have an IIS Site defined for this with the details below:
So when I go to 'Add Service Reference' I can pull in the reference perfectly fine.
However, when I try to do the same in my actual application, I still cannot seem to figure it out. I am unable to pull in the reference.
The site structure is the following:
The top level site is an MVC site, and there is an "API" virtual directory below it where the service resides that I am trying to expose over NetNamedPipeBinding.
The bindings for the site are the following:
The config for the service I am trying to expose over named pipes is the following:
<system.serviceModel>
<services>
<service name="Site.API.Service.WorkItemQueueService"
behaviorConfiguration="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/WorkItemQueueService"/>
</baseAddresses>
</host>
<endpoint address="QueueService"
binding="netNamedPipeBinding"
contract="Site.API.Service.IWorkItemQueueService"/>
<endpoint address="QueueService/mex"
binding="mexNamedPipeBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="True" aspNetCompatibilityEnabled="True"/>
The service implementation is the same as the customer service above, but obviously renamed to match the configuration above.
When I try to add a service reference, or find the metadata for this, It cannot find it.
IMPORTANT - All of the pre configuration items such as starting the Net Pipe listerner and role service have been completed, hence the NorthwindServices example works.