Adding WCF service reference in ASP.NET MVC app fails - c#

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.

Related

Creating a wcf web service and returning the xml response in android

I am an android developer. I want to create an android application which fetches the xml response from a WCF web service using soap. I have created a WCF web service, in which it fetches the XML document and return the content of that document. Here I dont know how to consume that content in android. Moreover, I am new to WCF and I am confused whether I am doing it right or wrong. Any help would be appreciated.
IService.cs
namespace WcfXML
{
[ServiceContract (Namespace="http://tempuri.org/")]
public interface IService1
{
[OperationContract, XmlSerializerFormat]
XmlElement GetData();
}
}
Service1.svc
namespace WcfXML
{
public class Service1 : IService1
{
public XmlElement GetData()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"D:\defaultGraphProperties.xml");
return xmlDoc.DocumentElement;
}
}
}
After creating this, when I run(F5), I am not able to invoke the method. How can I consume this web services in android? Please Help!!!!
You need to add configuration for webHttpBinding in web.config under the <Bindings>.
Then add the below code in web.config under the <System.serviceModel>
<services>
<service name="Test_WcfService.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBindingConfiguration" behaviorConfiguration="web" contract="Test_WcfService.IService1"></endpoint>
<endpoint address="Service1.svc" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingConfiguration" contract="Test_WcfService.IService1"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingConfiguration" maxReceivedMessageSize="2147483647" />
</webHttpBinding>
<basicHttpBinding>
<binding name="basicHttpBindingConfiguration" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- 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>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
After doing this changes in web.config you will be able to consume the wcf service from Browser.
Replace the Test_WcfService.Service1 and Test_WcfService.IService1 with your WCF Service name and interface.
To consume the WCF Service , you will have to do a Soap Request from Android.
Also if possible share your demo wcf service i will make the necessary configuaration changes at my end.

WCF + Xml-Rpc don't work

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

Ajax enabled WCF in MVC returns 404

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.

WCF NetNamedPipeBinding Service NorthwindService example vs MyService

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.

Combining WCF SOAP and REST

The REST project works fine, this can be accessed through this address:
http://localhost:8525/Device/Login?deviceID=testid&password=a&serialNum=testserial
I also have WCF SOAP project in my REST project, these two projects are separated in different folders, "SOAP" and "REST".
My problem is that, after I put this code:
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("Device", new WebServiceHostFactory(), typeof(Rest.DeviceComponent)));
}
I can't access now the SOAP service which I was able to access before through this address:
http://localhost:8525/DeviceComponent.svc (using WCFTest Client)
Here is the WebConfig
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<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="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
<handlers>
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd"/>
</handlers>
</system.webServer>
</configuration>
And inside Global.asax.cs
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("Device", new WebServiceHostFactory(), typeof(Rest.DeviceComponent)));
}
SOAP sample contract
namespace TSDEVICE.SoapSVC.Interface
{
[ServiceContract]
public interface IDeviceComponent
{
[OperationContract]
Session Login(string deviceID, string password, string serialNum, string ip);
[OperationContract]
bool Logout(DeviceSession session);
[OperationContract]
bool IsLatestVersion(DeviceSession session, int version);
[OperationContract]
byte[] DownloadLatest(DeviceSession details);
[OperationContract]
DateTime GetServerTime(DeviceSession session, long branchID);
[OperationContract]
bool AddDevice(UserSession session, Device deviceitem);
[OperationContract]
bool RemoveDevice(UserSession session, long deviceID);
}
}
And the REST part:
namespace TSDEVICE.Rest
{
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class DeviceComponent
{
[WebInvoke(UriTemplate = "Login?deviceID={deviceID}&password={password}&serialNum={serialNum}", Method = "POST")]
[OperationContract]
public TMODELDEVICE.Entities.Session Login(string deviceID, string password, string serialNum)
{
string ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
TMODELDEVICE.Logic.DeviceComponent restDC = new TMODELDEVICE.Logic.DeviceComponent();
return restDC.Login(deviceID, password, serialNum, ip);
}
public string Sample()
{
return "Hello";
}
}
}
I have to access SOAP and REST, how can I do that? Thanks a lot!
EDIT
When I try to "Set as Start page" the .svc file, I get this error:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
EDIT 2
Now I found out the real problem.
When ASP.NET compatibility mode in the web.config == true, SOAP fail to work, while REST requires it. What should I do with this? Thanks
I have a REST project that as both REST and SOAP service being exposed. Now I placed an .svc file for the SOAP service to be accessed by some clients.
The below screenshot gives the folder structure of my project, the route configuration in global.asax, Output accessing the Rest Service and accessing the .svc file (SOAP service)
UPDATE:
Please find my web.Config (My application is hosted on IIS):
Please find my class that implements my interface ISampleService:
While I appreciate the solutions listed above - I have a found it is far easier to manage/deploy if you don't over think the problem and follow a KISS principle.
Service Contract: IService.cs
namespace DontTazeMe.Bro
{
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet]
List<GeoMapData> GetToTheChopper();
}
}
Implementation: Service.cs
namespace DontTazeMe.Bro
{
public class WSDLService : IService
{
public List<GeoMapData> GetToTheChopper()
{
return ItsNotEasyBeingChessy.Instance.GetToTheChopperGeoData();
}
}
public class RESTService : WSDLService
{
// Let's move along folks, nothing to see here...
// Seriously though - there is no need to duplicate the effort made in
// the WSDLService class as it can be inherited and by proxy implementing
// the appropriate contract
}
}
Configuration
<system.serviceModel>
<services>
<!-- SOAP Service -->
<service name="DontTazeMe.Bro.WSDLService">
<endpoint address="" binding="basicHttpBinding" contract="DontTazeMe.Bro.IService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/DontTazeMe.Bro/Service/" />
</baseAddresses>
</host>
</service>
<service name="DontTazeMe.Bro.RESTService">
<endpoint address="" binding="webHttpBinding" contract="DontTazeMe.Bro.IService" behaviorConfiguration="Restful" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/DontTazeMe.Bro/Rest/Service/" />
</baseAddresses>
</host>
</service>
<behaviors>
<endpointBehaviors>
<behavior name="Restful">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
This method works just fine without getting carried away with configuration

Categories