Exposing Metadata Exchange for use with svcutil - wcf

I am trying to take a very simple (essentially empty/function-less) service I have and generate a proxy with svcutil.exe. Here's my server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;
class Server2
{
static void Main(string[] args)
{
Console.WriteLine("Server");
Uri baseAddress = new Uri("http://localhost:1234");
var host = new ServiceHost(typeof(TheContractService), baseAddress);
//host.AddServiceEndpoint(typeof(TheContractService), new WSHttpBinding(), "ContractService");
host.Open();
Console.ReadLine();
}
}
[ServiceContract]
class TheContractService
{
[OperationContract]
void Expose()
{
Console.WriteLine("Exposed");
}
}
[DataContract]
class TheContract
{
[DataMember]
public string PublicProperty { get; set; }
[DataMember]
public string PublicField;
[DataMember]
private string PrivateProperty { get; set; }
[DataMember]
private string PrivateField;
[DataMember (Name = "BetterName")]
private string fudshjguhf;
}
Now I just need to set up my .config file to allow MEX -- here is my server config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="ContractService"
behaviorConfiguration="MexServiceBehavior">
<endpoint address="ContractService"
binding="basicHttpBinding"
contract="TheContractService"
/>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MexServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
What am I doing wrong here? When I try to run this command:
svcutil /t:code http://localhost:1234/mex /out ContractService.cs /config: ContractService.config
I get either 400 or 405 errors and the client proxy is not generated successfully. Can anyone see any issues with what I currently have? Thanks!

Your class name is TheContractService, but in your config the name attribute of the <service> element is ContractService. Make sure that the value of that attribute is the fully-qualified name (namespace, if any, plus the class name), otherwise the configuration won't be picked up.

Related

How to set up the required meta data for WCF restful service?

I am trying to get my first WCF restful service to work. But I keep getting a warning when i run it through VS2013. it says it cannot find any service metadata.
How do i set this up?
The App.config file is as follows,
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1">
<endpoint address="http://localhost:8732/service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
The IService1.cs
namespace WcfJsonRestService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
Service1.Person GetData(string id);
}
}
The Service1.cs
namespace WcfJsonRestService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
public class Service1 : IService1
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "data/{id}")]
public Person GetData(string id)
{
// lookup person with the requested id
return new Person()
{
Id = Convert.ToInt32(id),
Name = "Leo Messi"
};
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}
}

WCF Hosting with IP Address

I have created a WCF Service which return JSON data.
here is my code:
namespace AppServices
{
[ServiceContract]
public interface Service1
{
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/GetCities", BodyStyle = WebMessageBodyStyle.WrappedRequest,
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
List<City> GetCityCode();
}
[DataContract]
public class City
{
[DataMember]
public string CityId { get; set; }
[DataMember]
public string CityName { get; set; }
[DataMember]
public string StateId { get; set; }
[DataMember]
public string Priority { get; set; }
}
}
public class ServiceAPI : Service1
{
public List<City> GetCityCode()
{
adp = new SqlDataAdapter("Select * from tblCity", offcon);
adp.Fill(ds, "City");
var city = (from DataRow dr in ds.Tables["City"].Rows
select new
{
Id = dr["intCityId"].ToString(),
Name = dr["strTitle"].ToString(),
sid = dr["intStateId"].ToString(),
priority = dr["intPriority"].ToString()
}).Select(x => new City() { CityId = x.Id, CityName = x.Name, StateId = x.sid, Priority = x.priority }).ToList();
return city;
}
}
my web.config is as follows:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehaviour" name="PatrikaAPIService.PatrikaService">
<endpoint address="" behaviorConfiguration="web" binding="webHttpBinding"
contract="PatrikaAPIService.IPatrikaService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment/>
</system.serviceModel>
</configuration>
Everything is working fine when i run this wcf on localhost as:
localhost:13186/ServiceApp.svc/GetCities
problem: when i pass my IP address as
192.168.1.16:13186/ServiceApp.svc/GetCities
it is giving an error that website is too busy...
& i want to access this wcf service in URL on other computers i mean other PCs on my Network.
I have changed my web.config as per my requirements now if anyone know what to do next to host this service with IP address.
or Host this into Microsoft 2003 Server SP2.
please help..
I'm assuming this is Cassini? If so - Cassini only responds if the host header is 'localhost' I think. Certainly you won't get it to respond by your IP.
Host it in IIS or IIS Express.
On a different note - if this is a .Net 4 project you might be interested to note that Rest services implemented this way via WCF is soon to become legacy - and be replaced by the Asp.Net Web API once it's gone to RTM (it's currently at RC stage) - I urge you to consider this newer technology if you can (it wouldn't solve this issue though).

Trying to self-host, I get error - wcf service host cannot find any service metadata .. please check if metadata is enabled

I am new to WCF and I've read answers to questions with titles similar to my error but I still cannot see what is wrong.
Following some other tutorials I decided to put my contract and my service in separate projects. Ultimately, I would like to host this in IIS but for now I just wanted to get the WCF Service Host to start (and WCF Test Client).
Here is the app.config in my service project (would this need to be in my contract project too I wonder??...):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="CBMI.TrimWCF.FileService"
behaviorConfiguration="Metadata">
<endpoint address="ws"
binding="wsHttpBinding"
contract="CBMI.TrimWCF.FileServiceContract.IFileService">
</endpoint>
<endpoint name="mex"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8081/TrimWCFfileService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Metadata">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
Here is the beginning of the FileService.cs file in my services project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.IO;
using System.Diagnostics; // needed for writing to EventLog.
using System.Text; // needed for StringBuilder
using System.ComponentModel;
using System.Web; // need to target .Net Framework 4.0 for the project (for HttpContext)
using TRIMSDK; // for TRIM 6.2. 7.1 (the "COM" SDK)
using CBMI.TrimWCF.Utilities; // separate project for misc classes
using CBMI.TrimWCF.FileServiceContract;
namespace CBMI.TrimWCF.FileService
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class FileService : IFileService
{
Database db;
string g_EventSource = "CBMI-TrimBroker";
string g_EventLog = "Application";
public FileService()
{
Finally, here is a bit of my IFileService.cs file in my contracts project:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace CBMI.TrimWCF.FileServiceContract
{
[ServiceContract(Name = "IFileService", Namespace = "http://www.cbmiweb.com/TrimWCF/2011/11")]
public interface IFileService
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
[OperationContract]
string DownloadFile(string trimURL
, string TrimRecordNumber
, string CallerPC
, string RequestorID
, out byte[] docContents
, out string returnFiletype
, out string returnFilename);
[OperationContract]
void DownloadFileCF(string trimURL
, string TrimRecordNumber
, string CallerPC = "not specified"
, string RequestorID = "not specified");
[OperationContract]
string SearchCF(string trimURL
, string CFSearchString
, string CallerPC
, string RequestorID);
[OperationContract]
string UploadFileCF(string trimURL
, byte[] incomingArray
, string fileName
, string TrimRecordTypeName
, string metaDataString);
[OperationContract]
string UpdateRecordCF(string trimURL
, string TrimRecordNumber
, string metaDataString);
}
[DataContract(Name = "WCFsample", Namespace = "http://www.cbmiweb.com/TrimWCF/2011/11 ")]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
The actual name of your service is BMI.TrimWCF.FileService.FileService (namespace BMI.TrimWCF.FileService, class name FileService). On the name attribute for the <service> tag you have only BMI.TrimWCF.FileService, so WCF can't find the configuration for your service. Please use the fully-qualified name of the service on the configuration, and WCF will then read it correctly.
I will start a service with minimum configuration and then keep adding whatever needed.
as with WCF 4 there default default binding and behavior configured by runtime.
1) service name in your config should be
<service name="BMI.TrimWCF.FileService.FileService">
2) I will change two tags (ServiceMetaData and ServiceDebug) as
3) you need not to include your app.config in your contracts project
4) Refernce your contractProjects in both service project and client project.

405 method not allowed using [webHttpBinding]

I'm getting problems with jquery call wcf. I've already search and found some solutions but it still raise me an error "405 method not allowed". Below is may code
-Interface
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.ServiceModel;
namespace WcfServiceLibrary
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IContactService" in both code and config file together.
[ServiceContract]
public interface IContactService
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Contact GetContactInfo();
}
}
My service
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.ServiceModel;
namespace WcfServiceLibrary
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ContactService" in both code and config file together.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ContactService : IContactService
{
public Contact GetContactInfo()
{
ContactBL contactBL = new ContactBL();
return contactBL.GetContact();
}
}
}
My object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime;
using System.Runtime.Serialization;
namespace WcfServiceLibrary
{
[DataContract]
public class Contact
{
[DataMember]
public int Id {get;set;}
[DataMember]
public string Fullname {get; set;}
[DataMember]
public string email { get; set; }
}
}
BL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WcfServiceLibrary
{
class ContactBL
{
public ContactBL() { }
public Contact GetContact()
{
return new Contact {email="thang.nguyen#saas.com.vn", Fullname="NVTThang",Id=2 };
}
}
}
And also my WCF configuration:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="myBehavior" name="WcfServiceLibrary.ContactService">
<endpoint address="ajaxEp" behaviorConfiguration="epAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="webBinding" name="epWebHttp"
contract="WcfServiceLibrary.IContactService" />
<endpoint address="mex" binding="mexHttpBinding" name="epMex"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="epAjaxBehavior">
<webHttp />
<enableWebScript/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="myBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="http://localhost"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
The I deploy my wcf on IIS 7.5 then I created a web client using jquery ajax call to my service.
$.ajax({
type: "GET",
url: "http://localhost/WcfTestService/Service.svc/ajaxEp/GetContactInfo",
data: '',
contentType: "application/json;charset=utf-8",
dataType: "json",
processdata: true,
success: function (msg) {
alert(msg);
//ServiceSucceeded(msg);
},
error: ServiceFailed
});
function ServiceFailed(err){
alert(err.responseText);
return;
}
when I call my service it always raises me "405 Method Not Allowed" and I've tried aspnet_regiis -i and ServiceModelReg -i but it didn't effect. Please suggest me any solutions.
Thanks in advance!
I can see a few problems in your service:
For "GET" requests, you should use WebGet, instead of WebInvoke, on your contract:
[ServiceContract]
public interface IContactService
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Contact GetContactInfo();
}
In your endpoint behavior you have 2 behaviors for scripting: webHttp and enableWebScript. You only need the former. The latter is for integration with ASP.NET AJAX specifically.
<endpointBehaviors>
<behavior name="epAjaxBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
This probably isn't causing any issues, but in the $.ajax call, you don't need to specify a content-type, since it's a GET request (so there's no content). Also, since you aren't passing any parameter, you also don't need the data parameter.
$.ajax({
type: "GET",
url: "http://localhost/WcfTestService/Service.svc/ajaxEp/GetContactInfo",
dataType: "json",
success: function (msg) {
alert(msg);
//ServiceSucceeded(msg);
},
error: ServiceFailed
});
Try this in your service:
[ScriptMethod]
public Contact GetContact(...)

WCF endpoint exception

I am just trying with various WCF(in .Net 3.0) scenarios.
I am using self hosting.
I am getting an exception as "Service 'MyServiceLibrary.NameDecorator' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element."
I have a config file as follows (which has an endpoint)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Lijo.Samples.NameDecorator"
behaviorConfiguration="WeatherServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8010/ServiceModelSamples/FreeServiceWorld"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
contract="Lijo.Samples.IElementaryService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WeatherServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And a Host as
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Runtime.Serialization;
namespace MySelfHostConsoleApp
{
class Program
{
static void Main(string[] args)
{
System.ServiceModel.ServiceHost myHost = new ServiceHost(typeof(MyServiceLibrary.NameDecorator));
myHost.Open();
Console.ReadLine();
}
}
}
My Service is as follows
using System.ServiceModel;
using System.Runtime.Serialization;
namespace MyServiceLibrary
{
[ServiceContract(Namespace = "http://Lijo.Samples")]
public interface IElementaryService
{
[OperationContract]
CompanyLogo GetLogo();
}
public class NameDecorator : IElementaryService
{
public CompanyLogo GetLogo()
{
CircleType cirlce = new CircleType();
CompanyLogo logo = new CompanyLogo(cirlce);
return logo;
}
}
[DataContract]
public abstract class IShape
{
public abstract string SelfExplain();
}
[DataContract(Name = "Circle")]
public class CircleType : IShape
{
public override string SelfExplain()
{
return "I am a Circle";
}
}
[DataContract(Name = "Triangle")]
public class TriangleType : IShape
{
public override string SelfExplain()
{
return "I am a Triangle";
}
}
[DataContract]
[KnownType(typeof(CircleType))]
[KnownType(typeof(TriangleType))]
public class CompanyLogo
{
private IShape m_shapeOfLogo;
[DataMember]
public IShape ShapeOfLogo
{
get
{
return m_shapeOfLogo;
}
set
{
m_shapeOfLogo = value;
}
}
public CompanyLogo(IShape shape)
{
m_shapeOfLogo = shape;
}
}
}
Could you please help me to understand what I am missing here?
Thanks
Lijo
You're self-hosting in a console app - how is your config set up??
Does your MySelfHostConsoleApp project have an app.config file?
Do you have the MySelfHostConsoleApp.exe.config in the same directory as the MySelfHostConsoleApp.exe file?
The error message just really means the config cannot be found and thus cannot be interpreted and used.
UPDATE: the other option is that WCF cannot interpret the config if it's present.
Check this out:
in your .NET code, your service class that implements the service is called MyServiceLibrary.NameDecorator
however, in your config, you call your service:
<service name="Lijo.Samples.NameDecorator"
That's not going to work! You're mixing up the .NET namespaces and the service namespaces here - and the name you need to put in your service-side config is the .NET fully qualified type name (including the .NET namespace - not the service namespace!).
Your service host will look for an entry <service name="MyServiceLibrary.NameDecorator"> based on your code - but it won't find it.
So you need to make sure to sync those two things up - the fully qualified service class name (including namespace and all) MUST match the name="...." attribute in your <service> tag in your config.