How can I discover current endpoints of my c# application programmatically? - c#

How can I code a c# sample for reading my Client endpoint configurations:
<client>
<endpoint address="http://mycoolserver/FinancialService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IFinancialService"
contract="IFinancialService" name="WSHttpBinding_IFinancialService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="http://mycoolserver/HumanResourcesService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHumanResourceService"
contract="IHumanResourceService" name="WSHttpBinding_IHumanResourceService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
And the goal is to obtain an array of endpoints address:
List<string> addresses = GetMyCurrentEndpoints();
As result we would have:
[0] http://mycoolserver/FinancialService.svc
[1] http://mycoolserver/HumanResourcesService.svc

This is my first answer ever. Be gentle :)
private List<string> GetMyCurrentEndpoints()
{
var endpointList = new List<string>();
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);
foreach (ChannelEndpointElement endpoint in serviceModel.Client.Endpoints)
{
endpointList.Add(endpoint.Address.ToString());
}
return endpointList;
}

// Automagically find all client endpoints defined in app.config
ClientSection clientSection =
ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection;
ChannelEndpointElementCollection endpointCollection =
clientSection.ElementInformation.Properties[string.Empty].Value as ChannelEndpointElementCollection;
List<string> endpointNames = new List<string>();
foreach (ChannelEndpointElement endpointElement in endpointCollection)
{
endpointNames.Add(endpointElement.Name);
}
// use endpointNames somehow ...
(Taken from http://mostlytech.blogspot.com/2007/11/programmatically-enumerate-wcf.html)

Related

How to switch different enpoint for a soap client

I have code that use soap client.
using (webTest.TestSoapClient sc = new webPrint.TestSoapClient())
{
sc.Print();
}
I have the following in web.config
<client>
<endpoint address="http://localhost/webservice/test.asmx"
binding="basicHttpBinding" bindingConfiguration="TestSoap"
contract="webTest.TestSoap" name="TestSoap" />
</client>
Now I want to add more endpoints to the web.config. like
<endpoint address="http://example.com/webservice/test.asmx"
binding="basicHttpBinding" bindingConfiguration="TestSoap"
contract="webTest.TestSoap" name="TestSoap1" />
<endpoint address="http://123.com/webservice/test.asmx"
binding="basicHttpBinding" bindingConfiguration="TestSoap"
contract="webTest.TestSoap" name="TestSoap2" />
</client>
Can I create the soap client in code using different endpoint like follows:
using (webTest.TestSoapClient sc = new webPrint.TestSoapClient("TestSoap1"))
{
sc.Print();
}
using (webTest.TestSoapClient sc = new webPrint.TestSoapClient("TestSoap2"))
{
sc.Print();
}
using (webTest.TestSoapClient sc = new webPrint.TestSoapClient("TestSoap3"))
{
sc.Print();
}
Is that feasible, and how can I do it?

WCF service streaming images

I'd like to make WCF service which can put image into stream.
I have next in config:
<service name="Images" behaviorConfiguration="ImagesBehavior">
<endpoint address="http://localhost:5523/Images.svc"
binding="basicHttpBinding" contract="Images" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:5523/Images" />
</baseAddresses>
</host>
</service>
<behavior name="ImagesBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
And code:
[OperationContract]
[WebGet(UriTemplate = "GetImage/{imageID}",
BodyStyle = WebMessageBodyStyle.Bare)]
public Stream GetImage(string imageID)
{
try
{
if (WebOperationContext.Current != null)
WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
var ms = new MemoryStream(myImage);
return ms;
}
catch (Exception e)
{
if (WebOperationContext.Current != null)
WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
Console.WriteLine("GetImage ERROR:" + e.Message + "\r\n" + e.StackTrace);
byte[] errorBytes = Encoding.UTF8.GetBytes("ERROR");
return new MemoryStream(errorBytes);
}
}
But when I'm trying this via browser like
http://localhost:5523/Images.svc/GetImage/imagecodeblabla
I've got
400 Bad Request
And when
http://localhost:5523/Images/GetImage/imagecodeblabla
405 Method Not Allowed
What's wrong?
Is your service SOAP or REST? It appears that you're using REST syntax (WebGetAttribute) but your binding is BasicHttpBinding (SOAP).
Try using WebHttpBinding instead and see how that goes!

Simple REST WCF Service Example Code - Endpoint not found

I was trying an example partially from Chapter 5 - RESTful .Net, but couldn't make it work for some reason (receiving 404-Not found).
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
[ServiceContract]
public class RestService
{
[OperationContract]
[WebGet(UriTemplate = "Hosting")]
public void Hosting()
{
Console.WriteLine("RestService::Hosting()");
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;
}
static void Main(string[] args)
{
var host = new ServiceHost(typeof(RestService));
var endpoint = host.AddServiceEndpoint(typeof(RestService), new WebHttpBinding(), "http://localhost:8080/Hosting");
endpoint.Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.ReadKey();
}
}
It works (returns status-code OK) if I use WebServiceHost as follows
static void Main(string[] args)
{
var host = new WebServiceHost(typeof(RestService), new Uri("http://localhost:8080"));
host.Open();
Console.ReadKey();
}
So the question is how to make it work with ServiceHost (without any configuration file etc. if possible) ?
WebServiceHost creates an EndPoint for you, nothing wrong if you continue using it. Refer this link for more details...
But you can also add below configuration to your service configuration to use ServiceHost, I have given an example, you can change it to reflect your service classes.
<system.serviceModel>
<services>
<service name="YourService.DateTimeService" behaviorConfiguration="customBehavior">
<endpoint address="Basic" binding="basicHttpBinding" contract="DifferentBindings.IDateTime">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="Web" binding="webHttpBinding" contract="DifferentBindings.IDateTime" behaviorConfiguration="webHttpBehavior">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/DifferentBindings/DateTimeService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false 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>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
So I was curious how complex this will be with WCF. Tried it out. It's streight forward.
I used this tutorial to create a simple service that has a doWork method that expects a string and returns a greeting.
Greeting:
[DataContract]
public class Greeting
{
[DataMember]
public string Str { get; set; }
}
Svc Contract:
[OperationContract]
[WebInvoke(Method = "ResponseFormat = WebMessageFormat.BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "sayHello/{name}/")]
Greeting DoWork(string name);
Svc Impl:
public class GreetingService : IGreetingService
{
public Greeting DoWork(string name)
{
return new Greeting {Str = string.Format("Hello {0}", name)};
}
}
Then you can first test it by:
Right click on the svc file in visual studio > view in browser
add 'sayHello/test' to the url
see the greeting in the browser
A consumer for this can be implemented in AngularJS using either the $http oder the $resource service
<!DOCTYPE html>
<html ng-app="restTest">
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular-resource.min.js"></script>
<script language="javascript">
// set up the app
var app = angular.module('restTest', ['ngResource']);
// create a controller
app.controller('RestTestCtrl', function ($scope, $http, $resource) {
// initial greeting
$scope.greeting = "Not greeted yet";
// say hello, consuming the svc using $http
$scope.sayHelloHttp = function () {
var url = "http://localhost:7507/GreetingService.svc/sayHello/" + $scope.inName + "/";
$http.get(url).
success(function(data) {
$scope.greeting = data.Str;
});
}
// say hello, consuming the svc using $resource
$scope.sayHelloRest = function () {
var GreetingSvc = $resource("http://localhost:7507/GreetingService.svc/sayHello/:name");
GreetingSvc.get({ name: $scope.inName }, function(data) {
$scope.greeting = data.Str;
});
}
});
</script>
</head>
<body ng-controller="RestTestCtrl">
<!-- bind the value of this input to the scope -->
<input type="text" ng-model="inName"/>
<button ng-click="sayHelloHttp()">$http</button>
<button ng-click="sayHelloRest()">$resource</button>
<!-- bind the greeting property -->
<div>{{greeting}}</div>
</body>
</html>
I guess everything above can be expressed more advance but it should give you a basic and working example to get started.

SOAP::Lite with WCF integration error

I'm having very simple c# application which running WCF service as follows:
[ServiceContract]
public interface IMessageRepository
{
event EventHandler<string> OnNewMessage;
[OperationContract]
void RegisterClient();
[OperationContract]
void SendMessage(string message);
void ClearClients();
}
App.config
<system.serviceModel>
<services>
<service name="CatcherService.Services.MessageRepository">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8740/MessageRepository/" />
</baseAddresses>
</host>
<endpoint address=""
binding="basicHttpBinding"
contract="CatcherService.Infrastructure.IMessageRepository"
>
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"
/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpGetUrl="http://localhost:8740/MessageRepository/"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
since i don't really understand PERL i took a client example from web and customized it a bit:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use SOAP::Lite +trace => [ transport => sub {
my ($in) = #_;
if ( ref($in) eq "HTTP::Request") {
print( "**** REQUEST ****\n" . $in->content() . "\n**** END REQUEST ****\n" );
}
elsif ( ref($in) eq "HTTP::Response") {
print( "**** RESPONSE ****\n" . $in->content() . "\n**** END RESPONSE ****\n" );
}
} ];
my $port = 8740;
my $server = "http://localhost:$port";
my $namespace = 'http://tempuri.org/';
# Setup Network Connection
my $service = SOAP::Lite
->ns( $namespace, 'my' )
->proxy( $server )
->on_action( sub {
my $action = sprintf( 'IMessageRepository/%s', #_ );
print( "action: '$action'\n" );
return $action;
} );
print( Dumper( $service ) );
eval {
print( "making request\n" );
my $response = $service->SendMessage("A message from perl client");
print( "got response:\n$response\n" );
};
if ( $# ) {
print( "failed:\n**************************\n$#\n*****************************\n" );
}
i'm getting the following error message when running:
action: 'IMessageRepository/http://tempuri.org/'
**** REQUEST ****
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:my="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soap:Body><my:SendMessage><c-gensym3 xsi:type="xsd:string">A message from perl client</c-gensym3></my:SendMessage></soap:Body></soap:Envelope>
**** END REQUEST ****
**** RESPONSE ****
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Not Found</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Not Found</h2>
<hr><p>HTTP Error 404. The requested resource is not found.</p>
</BODY></HTML>
**** END RESPONSE ****
what am i missing ?
the perl should call SendMessage("some text") method which in the c# server...

Cannot open host WCF REST Services

I am trying to implement some WCF and REST services to upload a file on my server, and I have found some code which I am trying to implement, but no success yet.
My code
class Program
{
static void Main(string[] args)
{
string address = "http://localhost/UploadService/UploadService.svc/UploadFile/theFile.txt";
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);
req.Method = "POST";
req.ContentType = "text/plain";
Stream reqStream = req.GetRequestStream();
string fileContents = "the quick brown fox jumped over the lazy dog.";
byte[] bodyContents = Encoding.UTF8.GetBytes(fileContents);
reqStream.Write(bodyContents, 0, bodyContents.Length);
reqStream.Close();
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
}
}
public class UploadService : IUploadService
{
#region IUploadService Members
public void UploadFile(string fileName, Stream fileContent)
{
using (StreamReader fileContentReader = new StreamReader(fileContent))
{
string content = fileContentReader.ReadToEnd();
File.WriteAllText(Path.Combine(#"c:\temp", fileName), content);
}
}
#endregion
}
[ServiceContract]
public interface IUploadService
{
[OperationContract]
[WebInvoke(UriTemplate = "UploadFile/{fileName}")]
void UploadFile(string fileName, Stream fileContent);
}
Web.Config
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehavior" name="UploadService">
<endpoint address="" binding="webHttpBinding" contract="IUploadService" behaviorConfiguration="RestBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RestBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
At the moment, in the response resp = (HttpWebResponse)req.GetResponse(); I am getting:
The remote server returned an error: (400) Bad Request.
What should I do to fix this?
You are making a service request from the same process that is hosting the service. I think they should be separate, e.g. your service host in a console app and your test in another.

Categories

Resources