As far as I can tell I have mimicked the accepted solutions of this post and this post. Unless I'm blind (and I hope I am at this point), I have a spotless app.config for my very simple WCF service:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RESTBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="Vert.Host.VertService.RSVPService">
<endpoint
address="/RSVP"
binding="webHttpBinding"
contract="Vert.Host.VertService.IRSVP"
behaviorConfiguration="RESTBehavior" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/Vert" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Here's the corresponding Service Contract and Implementation:
namespace Vert.Host.VertService
{
[ServiceContract]
public interface IRSVP
{
[OperationContract]
bool Attending();
[OperationContract]
bool NotAttending();
}
public class RSVPService : IRSVP
{
public bool Attending()
return true;
public bool NotAttending()
return true;
}
}
I'm hosting everything via a console app:
class Program
{
public static void Main()
{
// Create a ServiceHost
using (ServiceHost serviceHost = new ServiceHost(typeof(RSVPService)))
{
serviceHost.Open();
// The service can now be accessed.
Console.ReadLine();
}
}
}
All I want to do is stand this tiny service up, but I can't hit this endpoint with http://localhost:8080/Vert/RSVP/Attending. I still get 405 Method not allowed as a response.I'm using Visual Studio Community 2015, IIS10, targeting .NET 4.6
Things I've tried from suggestions:
I've given my service an explicitly-named behavior. No luck.
What am I missing?
Honestly not sure if this will make the difference, but mine has a link to service behaviour. Give your service behaviour a name:
<serviceBehaviors>
<behavior name="ServiceBehavior">
Then link it to your service:
<service name="Vert.Host.VertService.RSVPService" behaviorConfiguration="ServiceBehavior">
Be sure to decorate the service methods with the [WebGet] attribute (reference System.ServiceModel.Web.dll)
I.e. changing the service from
public class RSVPService : IRSVP
{
public bool Attending()
return true;
public bool NotAttending()
return true;
}
to
public class RSVPService : IRSVP
{
[WebGet]
public bool Attending()
return true;
[WebGet]
public bool NotAttending()
return true;
}
Solves the issue.
Related
Hey fellow developers and software-engineers,
I've recently run into a problem which doesn't let me access my WCF Services with a 404 (using ChannelFactory).
Here are the details:
multiple Webservers hosting the same WS (WCF.Net4/IIS8.5)
Server web.config of each WS:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true"/>
</webHttpBinding>
<basicHttpBinding>
<binding name="" maxReceivedMessageSize="26144"/>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="enableScriptBehaviour">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="IISManagerWS.WS">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="enableScriptBehaviour" contract="ContractDll.IWS"/>
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="True" />
</system.serviceModel>
</configuration>
Important Note for the WS: I've used a ClassLibrary for the Service Contract so I could work with the ChannelFactory in the client.
Why I am using a ChannelFactory? It simply seemed the easiest way to consume multiple WS which are all the same. Because the number
of these Webservices can become more I'd wanted it to be dynamically via code.
Interface of the Contract Dll:
namespace ContractDll
{
[ServiceContract]
public interface IWS
{
[WebGet()]
[OperationContract]
WebSite[] getLocalSiteInventory();
}
[DataContract]
public class WebSite
{
[DataMember]
public String Name { get; set; }
[DataMember]
public String AppPool { get; set; }
[DataMember]
public String Authentication { get; set; }
[DataMember]
public String Path { get; set; }
[DataMember]
public String Server { get; set; }
[DataMember]
public Boolean HasSSL { get; set; }
}
}
On the Client Side I've got an empty app.config except for the connectionstring, so nothing special here.
The whole lot of magic should happen in the code behind:
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress(ServiceURL);
ChannelFactory<IWS> factory = new ChannelFactory<IWS>(binding, address);
IWS channel = factory.CreateChannel(address);
WebSite[] sites = channel.getLocalSiteInventory();
But just when the call of my WS-Method gets going I happen to get an exception:
There was no endpoint listening at 'http://dev-02.apps.rd.local/IISManagerWS/ws.svc' that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
And the inner Exception goes:
(404) Not found.
If I access the WS via URL:
I've tried alot of research but even if there are lot of topics that look the same I had no success in solving this error.
Found the Solution myself while reading about designing RESTful Webservices.
WebChannelFactory<IWS> cf = new WebChannelFactory<IWS>(new Uri(ServiceURL));
IWS channel = cf.CreateChannel();
WebSite[] sites = channel.getLocalSiteInventory();
I am newbie in creating WCF web service. I am using VS2012 with target framework 4.5. I have added a WCF Service file in my project.
In "IService.cs" I have written the following code
namespace _3TWebServ
{
// 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 IService1
{
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped,
RequestFormat = WebMessageFormat.Json,
UriTemplate = "Calculate")]
String Calculate(Inputs ip1);
}
[DataContract]
public class Inputs
{
[DataMember(Name = "Coil_type")]
public string Coil_type { get; set;}
[DataMember(Name = "Finned_length")]
public string Finned_length { get; set;}
}
}
and in "Service.svc.cs"
namespace _3TWebServ
{
public class Service1 : IService1
{
[DataMember]
public string input;
public String Calculate(Inputs ip1)
{
String str = ip1.Coil_type + ip1.Finned_length;
return str;
}
}
}
But the problem comes when I run my service its not showing my method Calulate, When I pass my URL as Following
localhost:2121/Service1.svc/Calculate it shows "method not allowed" error.
I have done some Googling and enabled my IIS manager Directory Browsing. My config file is following
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="_3TWebServ.IService1" name="_3TWebServ.Service1">
<endpoint address="" behaviorConfiguration="Rest" binding="webHttpBinding" contract="_3TWebServ.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!--endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="_3TWebServ.IService1">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="Rest">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
I can see a few possible issues.
Your Calculate method is set for a HTTP POST request. You should make a HTTP POST request to get proper response.
Your request format is JSON (RequestFormat attribute property value), so make sure your request body contains the parameters in JSON format ({ "Coil_type" : "type", "Finned_length": 12 }).
Why do you have the [DataMember] public string input on the service implementation? Service implementations should generally carry operation contracts.
When I host my wcf service via webiste iis7, the method AfterReceiveRequest does not get called.
Please help..
Thanks
public class CultureMessageInspector : IClientMessageInspector, IDispatchMessageInspector
{
private const string HeaderKey = "culture";
#region IDispatchMessageInspector Members
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
int headerIndex = request.Headers.FindHeader(HeaderKey, string.Empty);
if (headerIndex != -1)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(request.Headers.GetHeader<String>(headerIndex));
}
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
#endregion
#region IClientMessageInspector Members
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
request.Headers.Add(MessageHeader.CreateHeader(HeaderKey, string.Empty, Thread.CurrentThread.CurrentCulture.Name));
return null;
}
#endregion
}
My Behavior Extension class, Service.svc, and config settings are as follows:
<system.serviceModel>
<services>
<service name="C:\Visual Studio 2010\WebSites\WCFService8">
<endpoint binding="netTcpBinding" bindingConfiguration="" behaviorConfiguration="Default" contract="CultureServer.IHelloWorld" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="Default">
<CultureExtension/>
</behavior>
</endpointBehaviors>
<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"/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="CultureExtension" type="Extension.CultureBehaviorExtension, Extension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
public class CultureBehaviorExtension : BehaviorExtensionElement
{
// BehaviorExtensionElement members
public override Type BehaviorType
{
get { return typeof(CultureBehaviour); }
}
protected override object CreateBehavior()
{
return new CultureBehaviour();
}
}
<%# ServiceHost Language="C#" Debug="true" Service="CultureServer.Server"%>
<services>
<service name="C:\Visual Studio 2010\WebSites\WCFService8">
<endpoint binding="netTcpBinding" bindingConfiguration="" behaviorConfiguration="Default" contract="CultureServer.IHelloWorld" />
</service>
</services>
The name attribute for the <service> tag is wrong. It should have the class name, not a path. Try replacing it with the code below.
<services>
<service name="CultureServer.Server">
<endpoint binding="netTcpBinding" bindingConfiguration="" behaviorConfiguration="Default" contract="CultureServer.IHelloWorld" />
</service>
</services>
Im trying to combine SOAP and REST under one roof with some modification. But I dont know whether its possbile. My code is below, it used to work when REST only but since I tried to add the extra web service as SOAP (using configuration) it doesnt work. Not sure how to configure it...
I have the interfaces:
[ServiceContract]
public interface IVLSContentServiceREST
{
[OperationContract]
[WebGet]
string EchoWithGet(string s);
[OperationContract]
[WebInvoke]
string EchoWithPost(string s);
}
[ServiceContract]
public interface IVLSContentServiceSOAP
{
[OperationContract]
[WebGet]
string EchoWithGet(string s);
[OperationContract]
[WebInvoke]
string EchoWithPost(string s);
}
Then I have a file called VLSContentService.svc with this:
<%# ServiceHost Language="C#" Debug="true" Service="VLSContentService" CodeBehind="VLSContentService.svc.cs" %>
And the cs(codebehind) file:
public class VLSContentService : IVLSContentServiceSOAP, IVLSContentServiceREST
{
string IVLSContentServiceSOAP.EchoWithGet(string s)
{
return "You said " + s;
}
string IVLSContentServiceSOAP.EchoWithPost(string s)
{
return "You said " + s;
}
string IVLSContentServiceREST.EchoWithGet(string s)
{
return "You said " + s;
}
string IVLSContentServiceREST.EchoWithPost(string s)
{
return "You said " + s;
}
}
And the configuration:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<!---Add the service-->
<services>
<service behaviorConfiguration="VLSContentServiceBehaviour" name="VLSContentService">
<endpoint address="rest" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentServiceREST"/>
<endpoint address="soap" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="basicHttpBinding" contract="IVLSContentServiceSOAP"/>
</service>
</services>
<!---Add the behaviours-->
<behaviors>
<serviceBehaviors>
<behavior name="VLSContentServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<!---Add the behaviours-->
<endpointBehaviors>
<behavior name="VLSContentServiceEndpointBehaviour">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
You don't need two versions of the contract - just host the same contract at two endpoints using different bindings
<services>
<service behaviorConfiguration="VLSContentServiceBehaviour" name="VLSContentService">
<endpoint address="rest" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="webHttpBinding" contract="IVLSContentService"/>
<endpoint address="soap" behaviorConfiguration="VLSContentServiceEndpointBehaviour" binding="basicHttpBinding" contract="IVLSContentService"/>
</service>
</services>
I am attempting to create and host a simple RESTful WCF Service. The service works perfectly except for 1 situation. I attempt to perform a POST to insert a new object into my static List using the JSON request of:
{"sampleItem":{"Id":1,"StartValue":2,"EndValue":3}}
If I then change the request to be:
{"sampleItemBlah":{"Id":1,"StartValue":2,"EndValue":3}}
I get a 500 response and all future POST's return a 500 error until I recycle my IIS App Pool and then it starts to work again.
It doesn't appear that the service is in a faulted state because I can still perform GET's and get data back. I turned on trace debugging and I do not see any errors in my log file.
Does anyone have any ideas?
Here is my Service Contract:
[ServiceContract]
public interface IWcfRestService
{
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
SampleItem Insert(SampleItem sampleItem);
}
[DataContract]
public class SampleItem
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int StartValue { get; set; }
[DataMember]
public int EndValue { get; set; }
}
And here is my implementation:
public class WcfRestService : IWcfRestService
{
private static readonly List<SampleItem> Items = new List<SampleItem>();
public SampleItem Insert(SampleItem sampleItem)
{
return BaseInsert(sampleItem);
}
private static SampleItem BaseInsert(SampleItem sampleItem)
{
if (Items.Exists(x => x.Id == sampleItem.Id))
Items.RemoveAll(x => x.Id == sampleItem.Id);
Items.Add(sampleItem);
return sampleItem;
}
}
And finally here is my ServiceModel section of my Web.config:
<services>
<service behaviorConfiguration="Services.ServiceBehavior"
name="WcfRestServiceApp.WcfRestService">
<endpoint address=""
behaviorConfiguration="RESTBehavior"
binding="webHttpBinding"
contract="WcfRestServiceApp.IWcfRestService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="RESTBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Services.ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Any and all help is greatly appreciated.
It turned out that the problem was with using the tag:
BodyStyle = WebMessageBodyStyle.Wrapped
When I removed it, the requirement to have:
{"sampleItem":{"Id":1,"StartValue":2,"EndValue":3}}
turned into:
{"Id":1,"StartValue":2,"EndValue":3}
This forced the cast to the correct object type and if the field wasn't present, it set the value to null or the type's default empty value.