WCF Array Always Acting as DataSet - c#

I am building a simple self-hosting WCF service that will host a mapping service for multiple products.
Here is my Interface:
namespace Eps.Messaging.Mapper.MapperServiceLibrary
{
[ServiceContract]
public interface IMapperService
{
[OperationContract]
public MapperOutput Map(String MapperFilename, String Input, GlobalArgument[] InputArguments);
[OperationContract]
public List<string> GetAvailableMaps();
}
[DataContract]
public class SymphoniaGlobalArgument
{
[DataMember]
public String Name { get; set; }
[DataMember]
public String Value { get; set; }
}
}
I simply am inheriting IMapperService and implementing them as needed in the service side.
Here is the config for the binding:
<services>
<service name="Eps.Messaging.Mapper.MapperServiceLibrary.MapperService">
<endpoint address="" binding="wsHttpBinding" contract="Eps.Messaging.Mapper.MapperServiceLibrary.MapperService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8755/Design_Time_Addresses/Eps.Messaging.Mapper.MapperServiceLibrary/MapperService/" />
</baseAddresses>
</host>
</service>
</services>
On the client side I am creating a service reference in Visual Studio and pointing to this location. Upon creating an instance of the service I do this:
MapperServiceClient Test = new MapperServiceClient();
Test.Map("Test.map", "Blah", BAD_HERE);
Where it says BAD_HERE it is looking for System.Data.DataSet instead of an array.
What am I doing wrong? Or is this correct and I need to do some fancy casting to get it to accept an array?

There's a setting on the Configure Service Reference dialog box that allows you to configure how collection types are dealt with. Modify the value in the Collection type combo box to an appropriate type (eg array).

Related

Can't access WCF service after versioning service contracts

I'm having trouble figuring out an issue with a WCF service that has appeared after I have implemented a "v2" contract to it to extend functionality. Everything builds fine but when I try to access the service in the browser I just get told that it cannot connect. When I try to add it as a service reference I get a similar message regarding connection issues. However, when I remove the extended contract's endpoint from the config file, and leave the previous "v1" version intact, it works fine.
Here is the "v1" contract:
namespace Company.Services.Ticketing.Retail.Contracts
{
[ServiceContract(Name = "OutletReportingContract_v1", Namespace = "https://enterprise.company.ie/Services/Retail")]
public interface IOutletReportingContract_v1
{
/* methods */
}
}
And here is the "v2" contract:
namespace Company.Services.Ticketing.Retail.Contracts
{
[ServiceContract(Name = "OutletReportingContract_v2", Namespace = "https://enterprise.company.ie/Services/Retail")]
public interface IOutletReportingContract_v2 : IOutletReportingContract_v1
{
/* methods */
}
}
Here are the endpoints in the Web.config:
<service name="Company.Services.Ticketing.Retail.OutletService" behaviorConfiguration="Public">
<endpoint address="1" binding="wsHttpBinding" bindingConfiguration="Standard" name="OutletReportingContract_v1"
contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v1" />
<endpoint address="2" binding="wsHttpBinding" bindingConfiguration="Standard" name="OutletReportingContract_v2"
contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v2" />
<endpoint address="mex" binding="mexHttpsBinding" name="IMetadataExchange" contract="IMetadataExchange" />
</service>
And here is the error message that appears in the event viewer:
WebHost failed to process a request.
Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/28075619
Exception: System.Web.HttpException (0x80004005): There was no channel actively listening at 'https://phil-pc.company.local/Services/Retail/OutletService.svc/_vti_bin/ListData.svc/$metadata'. This is often caused by an incorrect address URI. Ensure that the address to which the message is sent matches an address on which a service is listening. ---> System.ServiceModel.EndpointNotFoundException: There was no channel actively listening at 'https://phil-pc.company.local/Services/Retail/OutletService.svc/_vti_bin/ListData.svc/$metadata'. This is often caused by an incorrect address URI. Ensure that the address to which the message is sent matches an address on which a service is listening.
at System.ServiceModel.Activation.HostedHttpTransportManager.HttpContextReceived(HostedHttpRequestAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.HandleRequest()
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.BeginRequest()
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result)
Process Name: w3wp
Process ID: 8148
A bit stumped now and would appreciate any help :)
You need to separate your services declaration in web.config.
Assuming your implementation classes are named OutletService_v1 & OutletService_v2 you should end up with something like that:
<services>
<service name="Company.Services.Ticketing.Retail.OutletService_v1" behaviorConfiguration="Public">
<endpoint binding="wsHttpBinding" bindingConfiguration="Standard" contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v1" />
<endpoint address="mex" binding="mexHttpsBinding" name="IMetadataExchange" contract="IMetadataExchange" />
</service>
<service name="Company.Services.Ticketing.Retail.OutletService_v2" behaviorConfiguration="Public">
<endpoint binding="wsHttpBinding" bindingConfiguration="Standard" contract="Company.Services.Ticketing.Retail.Contracts.IOutletReportingContract_v2" />
<endpoint address="mex" binding="mexHttpsBinding" name="IMetadataExchange" contract="IMetadataExchange" />
</service>
</services>

Error adding wcf service to WCF Test Client - Service metadata cannot be accessible

I created a WCF Service and would like to test the one method I added using the WCF Test Client. When I originally created the method, it returned a DataTable. When I used the WCF Test Client to add the service, the service was added using the original app.config file. The method returning the DataTable showed an 'X' because I learned that you can't return this data type. So I created a class that contains the DataTable. The DataContract, Subject, is returned by the method. The code is below:
[ServiceContract]
public interface IPaging
{
[OperationContract]
Subject GetSubjectList(string strUserID);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
public class Subject
{
DataTable dtSubjectData = new DataTable();
[DataMember]
public DataTable SubjectTable
{
get;
set;
}
}
The method details:
namespace PagingService
{
public class Paging : IPaging
{
Subject cSubject = new Subject();
public Subject GetSubjectList(string strUserID)
{
....
}
}
}
Now, when I try to add the service to the WCF Test Client, I get the error:
'Service metadata cannot be accessible.'
This is my app.config file:
<system.serviceModel>
<services>
<service name="PagingService.Paging" behaviorConfiguration="SimpleServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="PagingService.IPaging">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/PagingService/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SimpleServiceBehavior">
<serviceMetadata httpGetEnabled="True" />
<!-- 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>
It seems to me that it is not with the app.config file because the original entries worked when the method returned a DataTable. But now the return type is now 'Subject', it is not updated somewhere.
When you change the method signature, is there some other place that needs to be changed that I am missing?
Thanks.
Why don't you just serialize the DataTable and send it back as an XML string? On the client end you could create a DataTable on the client end by usinging DataTable.ReadXML.

Cannot access WCF url hosted as a windows service

I have created a WCFLibrary which has :
[OperationContract]
string TestCall();
And my app.config has this :
<endpoint address="" binding="wsHttpBinding" contract="TestWCF.ITestService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/TestWCF/TestService/" />
</baseAddresses>
</host>
My Windowsservice has this :
protected override void OnStart(string[] args)
{
host = new ServiceHost(typeof(TestWCF.TestService));
}
Have compiled exe and installed it as a service everything is fine till this point.
Now I wanted to check this url from browser :
*http://localhost:8732/Design_Time_Addresses/TestWCF/TestService*
but due to some reasons I cant make a call to my WCF hosted in Windows Service, What might be went wrong am I missing anything ?
protected override void OnStart(string[] args)
{
host = new ServiceHost(typeof(TestWCF.TestService));
host.Open(); // :-)
}

Publishing 2 interface endpoints with common public methods - operation references a message element...that has already been exported

Been trying to add a non secure endpoint to my self hosted service, so basically I have one interface that uses sessions and another one that doesn't. They are both implemented by the same class. Here's part of my server config file:
<service name="PT.DataServices.WCFService.PTDataServices" behaviorConfiguration="dataServiceBehavior">
<endpoint address="PTDataServices" binding="wsHttpBinding" contract="PT.DataServices.WCFService.IPTDataServices" bindingConfiguration="wsHttpBinding1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="PTDataServicesNoSessions" binding="wsHttpBinding" contract="PT.DataServices.WCFService.IPTDataServicesNoSessions" bindingConfiguration="wsHttpBinding2">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://*/PT6/DataServices/"/>
</baseAddresses>
</host>
</service>
Interface without sessions:
[ServiceContract(
SessionMode = SessionMode.NotAllowed
)]
public interface IPTDataServicesNoSessions
{
[OperationContract]
string GetData(int value);
}
Interface with sessions:
[ServiceContract(
SessionMode=SessionMode.Required
)]
public interface IPTDataServices
{
[OperationContract(IsInitiating = true, IsTerminating = false)]
DcUser InitSession(string userCode, string passwordEncrypted, string connectionString);
[OperationContract(IsInitiating = false, IsTerminating = true)]
int EndSession();
[OperationContract(IsInitiating = false, IsTerminating = false)]
string GetData(int value);
}
Putting :http://localhost/PT6/DataServices/ in a browser returns :
The PT.DataServices.WCFService.IPTDataServicesNoSessions.GetData
operation references a message element [http://tempuri.org/:GetData]
that has already been exported from the
PT.DataServices.WCFService.IPTDataServices.GetData operation.
I don't want to change all clients to use different method names depending on the endpoint that is dynamically being used... how can I tell WCF that it's OK to have the same methods on each of the 2 interfaces?
Figured it out myself. I needed to add the namespace attribute to my interfaces:
[ServiceContract(
SessionMode=SessionMode.Required,
Namespace = "PTDataServices/WithSession"
)]
and
[ServiceContract(
SessionMode = SessionMode.NotAllowed,
Namespace = "PTDataServices/NoSessions"
)]
This allowed for WCF to avoid method name collisions in the WSDL for the methods that have the same name in both interfaces.

Expose webHttpBinding endpoint in a WCF service

I created a WCF service and exposed three endpoints which are basicHttpBinding, wsHttpBinding and webHttpBinding. This is a test service for my experiments with WCF. But, whenever I add service reference using the .svc file, I only get two (basic and ws) endpoints. There doesn't seem to be a third (webHttpBidning) endpoint being exposed for some reason.
To reproduce this issue, create a WCF application project, delete the Service1 service, add new item > WCF service named TestService, and change the config file to the following :
<system.serviceModel>
<services>
<service name="WcfTestService.TestService" behaviorConfiguration="TestServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost/WcfTestService/TestService.svc"/>
</baseAddresses>
</host>
<endpoint address="basic"
binding="basicHttpBinding"
contract="WcfTestService.ITestService" />
<endpoint address="ws"
binding="wsHttpBinding"
contract="WcfTestService.ITestService" />
<endpoint address="web"
binding="webHttpBinding"
contract="WcfTestService.ITestService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="TestServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
Here is the code for ITestService.cs:
[ServiceContract]
public interface ITestService
{
[OperationContract]
[WebInvoke]
Boolean ValidateUser(User user);
}
[DataContract]
public class User
{
[DataMember(Name = "Name")]
public String UserName { get; set; }
[DataMember]
public String Password { get; set; }
}
and for TestService.svc
public class TestService : ITestService
{
public bool ValidateUser(User user)
{
if (user.UserName == "User" && user.Password == "123")
{
return true;
}
return false;
}
}
I tried different combination of WebInvoke parameters and WebGet parameters, but failed.
Can anyone tell me why the third endpoint is not showing up in the WSDL file?
#decyclone: I have successfully exposed webHttpBindings without any issue. But I found some interesting thing when it get exposed and when it not!
I can see web binding getting exposed in Wcf Test Client.
Here are my configurations
<services>
<service behaviorConfiguration="TestWeb.Service2Behavior" name="TestWeb.Service2">
<endpoint address="" binding="wsHttpBinding" contract="TestWeb.Service2">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="web" binding="webHttpBinding" contract="TestWeb.Service2">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
Point to note here is, its working fine using VS2008 with Framework 3.5, VS2010 with Framework 3.5, when I use VS2010 and Framework 4.0 then I can't see WebHttpBinding getting exposed in WCF Test Client, however I can use that binidng to do http post in all cases.
I assume that in Framework 4.0 its not visible by default, even I try enable endpointDiscovery but still no luck!
I have covered this behaviour in my post
Your "web" endpoint will be exposed as a JSON endpoint. It is not compatible with WSDL.
WebHttpBinding is in System.ServiceModel.Web. If you are using vs2010, go to properties of your project, check target framework. By default it points to .Net Framework 4 Client Profile. It should point to .Net Framework 4, then you can find the System.ServiceModel.Web when you will go to Add reference
#decyclone: One way that a javascript client can learn the available methods on a webHttpBinding is to download a WCF javascript proxy with HTML script tags pointing to your endpoint followed by "/js": <script src="http://localhost/WcfTestService/TestService.svc/web/js"></script>

Categories

Resources