SOAP::Lite with WCF integration error - c#

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...

Related

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!

WCF Service fails when accessing host registry

I've been working on a wrapper for an API that will let me access it via a web service. The wrapper is a WCF service that I'm using to interface between the API and an asmx.
API---WCF---Webservice
Currently, I can get the API to work with the wrapper and the wrapper to communicate with the web service. However, any calls I make that originate from the web service to the API fail. The line that causes the failure is one that accesses a registry key on the host. My guess is that this is somehow permission related, but I'm new to C# and web services so I don't know for sure.
If it is permission related, where/how can I give the client permission to access the host's registry?
WFC code:
public class IRClass
{
...
public string init()
{
string result = "THE SERVICE IS WORKING BORK BORK\n";
int handle = 1234;
double retVal = -1;
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Rand McNally\DispatchAssistant\StandAlone\Install");
\\^^^ THIS RETURNS NULL WHEN CALLED BY A CLIENT ^^^
if (key != null)
{
string sbDARouterFilePath = key.GetValue("DaRouterPath").ToString();
string sbDADataFilePath = key.GetValue("DaDataPath").ToString();
string sbRouterFilePath = key.GetValue("RoutePath").ToString();
string sbMapFilePath = key.GetValue("MapPath").ToString();
string sbAdminFilePath = key.GetValue("AdminPath").ToString();
string sbDataFilePath = key.GetValue("DataPath").ToString();
try
{
RECode = irLib.irSAInitialize(sbDARouterFilePath, sbDADataFilePath, sbRouterFilePath, sbMapFilePath, sbAdminFilePath, sbDataFilePath);
}
catch (Exception e)
{
throw new Exception("irSAInitialize call failed in IntelliRouteLib.IRApi\n + e.Message);
}
result += "Key: " + key.ToString() + " \n";
}
else
{
result += "KEY IS NULL\n"; \\THIS SHOULDN'T HAPPEN
}
...
return result;//return RECode.ToString();
}
}
WCF App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="RmWcfServiceLibrary.RMService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8733/Design_Time_Addresses/RmWcfServiceLibrary/RMService/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding" contract="RmWcfServiceLibrary.IIntRoute">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "SdrConfigExample.e2e" />
</listeners>
</source>
</sources>
</system.diagnostics>
</configuration>
WebService Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using RMWebService.RmWcf;
namespace RMWebService
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class WebService1 : System.Web.Services.WebService
{
[WebMethod]
public string Intelliroute()
{
IntRouteClient client = new IntRouteClient();
string output = client.IRinit();
client.Close();
return output;
}
}
}
Thanks

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.

UNABLE to POST data to WCF from Android

I'm trying to send data to WCF service from an Android Application but somehow the service doesn't seems to be call through the android. I received a STATUSCODE value = 500 through adnroid in LOGCAT (which means the Internal Server Error) I go through the source code 100 times but didn't figure out the Bug. and almost checked all the posts related to my problem but still didn't get any solution.
HERE IS THS CODE
Android Code:
private class sendPostData extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
HttpPost request = new HttpPost( LOGIN_SERVICE_URL + "/MyCar");
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
JSONStringer getCarInfo;
try {
getCarInfo = new JSONStringer()
.object()
.key("myCar")
.object()
.key("Name").value(edt_carName.getText().toString())
.key("Make").value(edt_carMake.getText().toString())
.key("Model").value(edt_carModel.getText().toString())
.endObject()
.endObject();
StringEntity entity = new StringEntity(getCarInfo.toString());
request.setEntity(entity);
// Send request to WCF service
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
Log.d("WebInvoke", "Saving : " + response.getStatusLine().getStatusCode());
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
txt_verif.setText("Success");
}
}
everything is working fine in android code except calling the WCF service. I Debug the code several times and received statuscode = 500
HERE is the WCF Service
Service.cs
public class Service1 : IService1
{
public void UpdateMyCar(myCar myCar) {
string strConnectionString = ConfigurationManager.ConnectionStrings["Database1"].ConnectionString;
SqlConnection conn = new SqlConnection(strConnectionString);
conn.Open();
using (SqlCommand cmd = new SqlCommand("Insert into TestingTable (Name,Make,Model) Values (#Name,#Make,#Model)", conn)) {
cmd.Parameters.AddWithValue("#Name", myCar.Name);
cmd.Parameters.AddWithValue("#Make", myCar.Make);
cmd.Parameters.AddWithValue("#Model", myCar.Model);
int queryResult = cmd.ExecuteNonQuery();
} conn.Close();
}
LogCat
WebInvoke Saving : 500
IService1.svc
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(
Method = "POST",
UriTemplate = "MyCar",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
void UpdateMyCar(myCar myCar);
}
[DataContract]
public class myCar
{
[DataMember(Name="Name")]
public string Name
{
get;
set;
}
[DataMember(Name="Model")]
public string Model
{
get;
set;
}
[DataMember(Name="Make")]
public string Make
{
get;
set;
}
Web.Config
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<compilation debug="true" targetFramework="4.0">
</compilation>
<authentication mode="Windows"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/></system.web>
<system.serviceModel>
<services>
<service name="CarSercive.Service1" behaviorConfiguration="CarSercive.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="" binding="webHttpBinding" contract="CarSercive.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CarSercive.Service1Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
this service is also publish on IIS. and I also checked that service with google chrome extension SIMPLE REST CLIENT and received an internal server error
The problem is your host name doesn't match what you are using from the phone.
You can turn off address filter to fix this temporarily:
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
public class Service1 : IService1
{
....
}
But you should fix the hostname when you release to production
Create a domain in your machine with proper port number and make sure you are able to call the service using the Google's Rest client.If it works,then you won't find any issue if you call the same using your android phone.
Following article will help to setup virtual directory with proper port number.[http://www.hosting.com/support/iis7/create-new-sites-in-iis-7/]
Note you can't call localhost directly from your mobile.atleast try to call the service with ipaddress.[http://localhost/service/mycar] =>[http://DemoService/service/mycar]
The following code will help you to debug your code a little bit deep.
catch (Exception ex)
{
WebException webexception = (WebException)ex;
var responseresult = webexception.Response as HttpWebResponse;
//Code to debug Http Response
var responseStream = webexception.Response.GetResponseStream();
string fault_message = string.Empty;
int lastNum = 0;
do
{
lastNum = responseStream.ReadByte();
fault_message += (char)lastNum;
} while (lastNum != -1);
responseStream.Close();
}
Never mind, I have made several changes in web.config file and got the solution. <endpointBehaviors> tag was missing in my case and several other things. here is the updated code of web.config file.
[UPDATED web.config file]
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings>
<add name="DB" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Munyb\Documents\Visual Studio 2010\Projects\CarSercive\CarSercive\App_Data\Database1.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0">
</compilation>
<authentication mode="Windows"/>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/></system.web>
<system.serviceModel>
<services>
<service name="CarSercive.Service1" behaviorConfiguration="RESTfulServ">
<!-- Service Endpoints -->
<endpoint address="" binding="webHttpBinding" contract="CarSercive.IService1" behaviorConfiguration="web"></endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="RESTfulServ">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
</serviceHostingEnvironment>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>
</system.webServer>
</configuration>

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