WCF 4 routing service throws handler error - web-services

I am trying to use WCF 4 routing declaratively to redirect one branch of my (REST) web services to an alternate server. I configured WCF's System.ServiceModel.Routing.RoutingService to route http://oldserver:81/FileService/ calls to http://newserver:82/FileService/, but when I try to access the redirected service, all it does is throw the error
Handler "HttpLogging" has a bad module "HttpLoggingModule" in its module list
I can enter URLs to the new service in my browser and they work fine, but URLs to the old service (to be re-routed) fail.
I have added the following routing configuration into my web service application:
<configuration>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="routingConfig">
<!-- Specify the routing table to use. -->
<routing filterTableName="routingTable1" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<!-- WCF routing table -->
<routing>
<filters>
<filter name="FileFilter1" filterType="EndpointName" filterData="FileService"/>
</filters>
<filterTables>
<filterTable name="routingTable1">
<add filterName="FileFilter1" endpointName="FileService" />
</filterTable>
</filterTables>
</routing>
<client>
<!-- Destination endpoint defining the base URL where File messages will be routed. -->
<endpoint name="FileService"
address="http://newserver:82/FileService/"
binding="webHttpBinding"
contract="*" />
</client>
<services>
<!-- WCF routing service. -->
<service name="System.ServiceModel.Routing.RoutingService" behaviorConfiguration="routingConfig" >
<host>
<baseAddresses>
<!-- The service endpoint to be redirected. -->
<add baseAddress="http://oldserver:81/FileService" />
</baseAddresses>
</host>
<!-- Define the endpoints of the service to receive messages. -->
<endpoint name="reqReplyEndpoint" binding="webHttpBinding" contract="System.ServiceModel.Routing.IRequestReplyRouter" address="" />
</service>
</services>
There is no longer a FileService service in the application, except the one that should be exposed by the routing service.
I've tried:
filter types of MatchAll, EndpointAddress, and PrefixEndpointAddress;
various forms of the old service addresses;
different names for filters, routing tables, services;
renaming contracts.
None of it gets my client to call the redirected service, much less even any indication that the routing service is operational or even configured at all.
How do I make the routing actually work? Failing that, how would I debug it so I can determine what to fix?

The general problem I see is that you are trying to route REST calls with Routing Service, which is not supported. MSDN reference:
https://msdn.microsoft.com/en-us/library/ee517423.aspx
The Routing Service does not currently support routing of WCF REST
services. To route REST calls, consider using System.Web.Routing or
Application Request Routing
(http://go.microsoft.com/fwlink/?LinkId=164589).
Blockquote

Related

How to configure one URL Rewrite/proxy rules on IIS?

Architecture:
User --> ARR Server --> LB --> 2 Web Server serving 2 different sites
Web Server1 serving -> https://xxxx-green-xxxx-xxxx.net/xxx/xxx?xx=xxxx where green keyword comes in any place in domain name
Web Server2 serving -> https://xxxx-yellow-xxxx-xxxx.net/xxx/xxx?xx=xxxx where yellow keyword comes in any place in domain name
Requirement:
Request format: https://xxxx-green-xxxx-xxxx.net/xxx/xxx?xx=xxxx or yellow URL
In ARR we need to filter the URL with green and yellow keyword in URL and send it to respective Web Server IP.
But all my requests are landing to home page only. and even i am confused that whether changing the host will work but i need to give IP which is different for each web server in LB
We have set this Rule and getting below results:
<rule name="Green" enabled="true" stopProcessing="true">
<match url="(.*xxx.net)(/.*)" />
<conditions logicalGrouping="MatchAll"
trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="green" />
</conditions>
<action type="Rewrite" url="https://xx.xxx.xx.xx/{R:2}"
appendQueryString="true" />
</rule>
Where R:2 is --> xxx/xxx?xx=xxxx
As per your question.
You need to write Custom rewrite rule for that.
So first refer this link
Into link you can handle your requirement and rewrite to other other web server.
So please follow all the step and write you logic into
Rewrite(string value) method.
Into this method you need to pass your server url from IIS rules and check via condition like below.
public string Rewrite(string value)
{
if(value.Contains("green"))
{
return // your rewrite URL here
}
else if(value.Contains("yellow"))
{
return // your rewrite URL here
}
return value;
}
So it's working as per your requirement.

WCF webservice fails after "extracting interface"

I am new to WebServices, and have a simple question.
I wrote a "Hello World" Service with Visual Studio 2017:
ServiceAjax.svc.cs:
namespace WebServiceTest
{
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ServiceAjax
{
[OperationContract]
[WebGet]
public string DoWork()
{
return "Hallo World";
}
}
}
the ServiceAjax.svc reads as this:
<%# ServiceHost Language="C#" Debug="true" Service="WebServiceTest.ServiceAjax" CodeBehind="ServiceAjax.svc.cs" %>
Running this works fine.
Now i read it's the way to go to declare an Interface for the Service.
Nearly every example does this ..., so i tried:
ServiceAjax.svc.cs:
namespace WebServiceTest
{
[ServiceContract]
public interface IServiceAjax
{
[OperationContract]
[WebGet]
string DoWork();
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ServiceAjax: IServiceAjax
{
public string DoWork()
{
return "Hallo World";
}
}
}
Running this i get an error:
It's german, so my translation might be not excatly as the english message:
"From http://localhost:58513/ServiceAjax.svc no metadata could be loaded ..."
I Little bit below he tells me:
WebServiceTest.ServiceAjax wos not found in the List of contracts implemented by ServiceAjax
So, it must be a dump foult, cause i cant explain why extracting an Interface blows the Service, i sure missed something simple.
But i cant find a difference to the "simple WCF Web HTTP Service" samples in the net.
Ideas?
Update: I added this to an existing ASPX-Project, not a "clean" wcf Project ....
I found the answer myself (after earning the Tumbleweed badge ...)
There was one line missing in the WebConfig
<endpoint address="mex"
binding="mexHttpBinding"
name="mex"
contract="IMetadataExchange" />
I had tried with different "Factorys" in the SVC-Markup, which did not work.
Perhaps havent found the right one ...
i.e.
<%#ServiceHost language=c# Debug="true" Service="WebServiceTest.ServiceAjax"
Factory=System.ServiceModel.Activation.WebScriptServiceHostFactory%>
Adding the Config manually and adding to it did the trick after all.
I followed the steps in
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-configuration-to-add-an-aspnet-ajax-endpoint
This lead to the "cant load metadata" Problem which i could fix with the line on Top (mex endpoint).
Why mircosoft [sic] did not point that out, i dont know ...
And why this starts beeing needed when using an interface i dont know neither.
But I stumbled about more occasions, when he needed that, i.e, AJAX Scripting Manger, which needs the Namespace-Argument in the Servicedeclaration too:
[ServiceContract(Namespace = "AJAXService")]
Below what i added to web.config (allready included Lines where dropped 4 shortage
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="myServiceTypeBehaviors" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="myDataAspNetAjaxBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="myServiceTypeBehaviors"
name="WebServiceTest.ServiceAjax">
<endpoint address=""
behaviorConfiguration="myDataAspNetAjaxBehavior"
binding="webHttpBinding"
name="ZESData"
contract="WebServiceTest.IZESData" />
<endpoint address="mex"
binding="mexHttpBinding"
name="mex"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>

Missing SOAPAction header when invoking WS with Camel-CXF

We are trying to a invoke Soap service using Camel-Cxf/Fuse and using Payload dataformat. Some times client is rejecting request saying SOAPAction is missing and this is intermittent. Is there a way for us to set SOAPAction specifically during service invocation? In what cases we fail to send SOAPAction? Here is the configuration we are using for invocation.
<!-- CXF configuration pointing to WSDL URL and service Name -->
<cxf:cxfEndpoint id="abcSOAPCPOutbound"
wsdlURL="wsdl/FooService.wsdl"
endpointName="cNS:FooServiceSoap"
serviceName="cNS:FooService"
address="http://example.com/processRequest.asmx"
xmlns:cNS="http://www.example.com"
loggingFeatureEnabled="false">
<cxf:inInterceptors>
<ref bean="GZIPInInterceptor"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="iuABCSOAPOutboundInterceptor"/>
</cxf:outInterceptors>
</cxf:cxfEndpoint>
<!-- Came route for invoking service with operationName header set -->
<route id="iuFooOutboundRoute">
<from uri="direct-vm:iuOutboundtoFoo"/>
<setHeader headerName="operationName" >
<constant>FooSync</constant>
</setHeader>
<convertBodyTo type="String"/>
<!-- Send to Colibrium -->
<to uri="cxf:bean:abcSOAPCPOutbound?dataFormat=PAYLOAD"/>
<process ref="extractHTTPStatusCode"/>
</route>
Does it cause any problem if we set camel header as SOAPAction before invoking service?
Yes,
The same way as you do operationName:
<setHeader headerName="SOAPAction">
<constant>DummyOperation</constant>
</setHeader>
You can refer here - http://www.javaworld.com/article/2078883/open-source-tools/java-tip-write-an-soa-integration-layer-with-apache-camel.html?page=4

Setting up Mock Endpoints in Apache Camel with log:*

I have several routes that end with a log uri such as
<route>
<from uri="someUri" />
<to uri="someProcessor" />
<to uri="log:SOME_LOG?level=INFO" />
</route>
I am using CamelSpringJUnit4ClassRunner to run my unit tests.
I want to be able to mock my log endpoints as MockEndpoint objects. I have tried to use
#MockEndpoints("log:*")
along with
end = MockEndpoint.resolve(camelContext, "log:SOME_LOG?level=INFO");
but that generates a ClassCastException cannot cast InterceptSendToEndpoint to MockEndpoint.
and also tried
#EndpointInject(uri="log:SOME_LOG?level=INFO")
MockEndpoint end;
but that also generates an IllegalArgumentException.
Invalid type: org.apache.camel.component.mock.MockEndpoint which cannot be
injected via #EndpointInject/#Produce for: Endpoint[log:SOME_LOG?level=INFO]
A workaround I've found is by prepending my log uri with "mock:" and using
#EndpointInject(uri="mock:log:SOME_LOG?level=INFO) and defining my route in xml with
<route>
<from uri="someUri" />
<to uri="someProcessor" />
<to uri="mock:log:SOME_LOG?level=INFO" />
</route>
However I would like to get this to work by mocking my log: uris and not having to modify my route definitions in camel.xml.
Is there something that I'm missing?
When you use #MockEndpoints("log:*"), the camel just create the mock endpoint for you, the mock endpoint uri should be mock:log:THE_REMAINED. You should be able to get the mock endpoint with below code:
end = MockEndpoint.resolve(camelContext, "mock:log:SOME_LOG?level=INFO");

Adding authorization to a third-party web service

I have several third-party web services of which I only have their WSDL's. Currently they are only accessible in my internal network. I would like to expose those web services to the internet but, since they read/write sensitive information, I would need some sort of authentication mechanism in order to assure that only certain users are able to invoke them.
The idea is to expose exactly the same interface (same operations with the same parameters) but intercepting each invocation to check the security and then invoking the original web service if the authentication is valid or returning an exception or error message otherwise. I've been trying to use Mule ESB for the task abut I can't quite get there
Is this possible with mule? If not, how would i go about doing this? Can anyone point me in the right direction?
Thanks in advance.
Here is an example of a web service proxy adding WS-Security to an unsecure target web service:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:mule-ss="http://www.mulesoft.org/schema/mule/spring-security"
xmlns:ss="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.2/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/3.2/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/3.2/mule-cxf.xsd
http://www.mulesoft.org/schema/mule/spring-security http://www.mulesoft.org/schema/mule/spring-security/3.2/mule-spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<mule-ss:security-manager>
<mule-ss:delegate-security-provider
name="memory-provider" delegate-ref="authenticationManager" />
</mule-ss:security-manager>
<spring:beans>
<ss:authentication-manager alias="authenticationManager">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="user" password="pass" authorities="ROLE_USER" />
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
<cxf:security-manager-callback id="serverCallback" />
</spring:beans>
<flow name="secureStockQuoteWsProxy">
<http:inbound-endpoint address="http://localhost:8080/sec-ws/stockquote"
exchange-pattern="request-response">
<cxf:proxy-service>
<cxf:inInterceptors>
<spring:bean
class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
<spring:bean
class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<spring:constructor-arg>
<spring:map>
<spring:entry key="action" value="UsernameToken" />
<spring:entry key="passwordCallbackRef"
value-ref="serverCallback" />
</spring:map>
</spring:constructor-arg>
</spring:bean>
</cxf:inInterceptors>
</cxf:proxy-service>
</http:inbound-endpoint>
<http:outbound-endpoint address="http://www.webservicex.net/stockquote.asmx"
exchange-pattern="request-response">
<cxf:proxy-client enableMuleSoapHeaders="false"
soapVersion="1.2" />
</http:outbound-endpoint>
</flow>
http://www.webservicex.net/stockquote.asmx?wsdl gives the same result. So you could test it there. Maybe the problem lies with .net services.
Anyway, for now I made a successful proxy with the webservice pattern. Now I am still working on transforming a response. Not with much success because Mule keeps giving me a ReleasingInputStream as response.