WCF -> ASMX and Cookies - wcf

I have a web application that communicates to a WCF service through a WCF client. At the point my code is invoked, authentication cookies have been issued and I have a dependency on an ASMX service that expects those authentication cookies.
I need to pass the cookies from the web application through the WCF client to the WCF service to the ASMX service.
Any ideas? It looks like my best bet may be setting allowCookies to false, parsing out the cookie headers, attempting to re-create them on the WCF service and then attaching them to the SOAP request.
Note: I looked at this article, which seems close but not quite applicable to this question. In the linked scenario, an ASMX service is creating cookies, which must be persisted to a subsequent ASMX service by the same WCF client.

Ok, so there's two main things that need to occur:
Get the cookie from the web app context to the WCF service
Get the cookie from the WCF service to the ASMX service
NOTE: Because you didn't specify, I'm going to assume that you're using a WCF client within your WCF service to talk to the ASMX service. If this is not the case please let me know and I will revise this post accordingly.
Step #1:
I would recommend writing an IClientMessageInspector which you bind to your client endpoints using an IEndpointBehavior. In your implementation of IClientMessageInspector::BeforeSendRequest you basically read the cookie out of the current HttpContext::Request::Cookies collection and append the value as a message header. That would look a little something like this:
public void BeforeSendRequest(ref Message request, IClientChannel channel)
{
// Get the cookie from ASP.NET
string cookieValue = HttpContext.Current.Request.Cookies["MyCookieName"].Value;
// Create a header that represents the cookie
MessageHeader myCookieNameHeader = MessageHeader.CreateHeader("MyCookieHeaderName", "urn:my-custom-namespace", cookieValue);
// Add the header to the message
request.Headers.Add(myCookieNameHeader);
}
One you configure the endpoint with this message inspector every logical request will automatically flow the cookie value through as a header to your WCF service. Now, since your WCF service doesn't actually care about the header itself, it can basically ignore it. In fact, if you only did this step, you should be able to run all your code right now and not experience any difference.
Step #2:
Now we need the cookie to go from the WCF service to the ASMX service. Once again all you need to do is implement an IClientMessageInspector, except your BeforeSendMessageRequest is going to be a little different:
public void BeforeSendRequest(ref Message request, IClientChannel channel)
{
// Get the cookie value from the custom header we sent in from step #1
string cookieValue = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("MyCookieHeaderName", "urn:my-custom-namespace");
HttpRequestMessageHeaderProeperty httpRequestMessageHeaderProperty;
MessageProperties outgoingMessageProperties = OperationContext.Current.OutgoingMessageProperties;
// Get the HttpRequestMessageHeaderProperty, if it doesn't already exist we create it now
if(!outgoingMessageProperties.TryGetValue(HttpRequestMessageHeaderProperty.Name, out httpRequestMessageHeaderProperty))
{
httpRequestmessageHeaderProperty = new HttpRequestMessageHeaderProperty();
outgoingMessageProperties.Add(HttpRequestMessageHeaderProperty.Name, httpRequestmessageHeaderProperty);
}
// Set the cookie header to our cookie value (note: sample assumes no other cookies set)
httpRequestmessageHeaderProperty.Headers[HttpRequestHeader.Cookie] = cookieValue;
}
Once again you need to bind this to the endpoint for your ASMX service using an IEndpointBehavior and every logical request you make will automatically pass the cookie through.

Related

How to pass parameter and get data from wcf service

I got this error:
There was no endpoint listening at http://vkalra.in/WCF_SERVICE/RestServiceImpl.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details
InnerException-The remote server returned an error: (404) Not Found.
This is my code:
Binding binding = new BasicHttpBinding();
// Create endpointAddress of the Service
EndpointAddress endpointAddress = new EndpointAddress("http://vkalra.in/WCF_SERVICE/RestServiceImpl.svc");
ServiceReference1.Leave_Details emp = new ServiceReference1.Leave_Details();
emp.empid = items.empid;
emp.fromdate = "01-04-2019";
emp.todate = "04-06-2019";
emp.tabt = "1";
emp.jdis = "0";
try
{
ServiceReference1.RestServiceImplClient service = new ServiceReference1.RestServiceImplClient(binding, endpointAddress);
string levbal = service.Leave_Calculation(emp);
}
catch(Exception ex)
{
}
If we want to consume the WCF service created by WebHttpBinding(this type of the WCF service is also called Restful service) by adding service reference, we need to do something special. Generally speaking, if we want to call Restful service (such as the service created by Asp.net WebAPI), we could construct a http request, Get or Post with a request body, then send to the specified service address.
https://code-maze.com/different-ways-consume-restful-api-csharp/
https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
This also applies to WCF service created by WebHttpBinding.
consuming a WCF service using simple HttpClient class
But if we want to consume the WCF restful service by adding the service reference, we are supposed to maintain the consistency of binding between the client and server. we should add [WebGet]/[WebInvoke] to the auto-generated method of the service interface, which comes in the form of adding service reference, located in Reference.cs file.
One more thing we need do is add Webhttpbehavior (endpoint behavior) to the client service endpoint. This client configuration comes in the form with adding service reference, located in the System.ServiceModel section of the app.config/web.config.
The remote server returned an unexpected response: (400) Bad Request. wcf
Feel free to let me know if there is anything I can help with.

svc service that can recieve any request

Hello BizTalk and WCF experts
I need your help todo a implementation for this scenario:
I have created a BizTalk application without schemas, orchestrations but just with a send port pipeline that look at the soap action on the request message and send the request to the correct destination service.
I have also created a in-process WCF-Custom receive port that my send port subscribe and I have defined following in-process custom URL "http://localhost:8080/bts/services/serviceRoute.svc".
Instead of calling the above metioned URL i want an IIS service endpoint that receive all the request and send it to ny custom url.
So i want a IIS svc endpoint without specific schema but a service endpoint that can receive any request no matter operationsname and send the request to my BizTalk receive port (my WCF-Custom receive port).
Can anyone tell me how I can define/create a IIS service endpoint for this scenario or any other way I can solve this issue.?
Thanks for your help..
Very important point: BizTalk already does this. You don't need the extra IIS service.
BizTalk Receive Locations are not Schema bound. They will happily accept any message type. The only validation happens if you implement it.
So, I would start with a plain WCF-WebHttp endpoint hosted In-Process or IIS or WCF-BasicHttp/basicHttpBinding to have the Action automatically Promoted (IIRC, been a while ;).
You can configure the URL, security and what not any way you need in IIS.
Create a service with a method that receives a System.ServiceModel.Channels.Message class, like this interface:
[ServiceContract(Namespace = "http://yournamespace")]
public interface IRouter
{
[OperationContract(Action = "*", ReplyAction = "*", Name = "*")]
[WebGet]
Message RouteMessage(Message incomingRequest);
}
This will receive any message, including non-soap messages, so you can create your routing logic.
Message class has some useful members, like Headers property and CreateMessage method, that you can use to create a copy of original message and redirect to its destination, or simply extract the data for logging.
EDIT: adding some information (some doubts in comments)
Using the code above, you can simply redirect the incomming message to another endpoint, like this:
/* "endpointConfigurationName" is the name of a client endpoint, that is in Web.config, like this for instance:
<endpoint name="endpointConfigurationName" binding="basicHttpBinding" bindingConfiguration="someBindingConfiguration" behaviorConfiguration="someBehaviorConfiguration" contract="IRouter" />
notice that there is not an address defined, you can define in code */
using (var factory = new ChannelFactory<IRouter>("endpointConfigurationName", new EndpointAddress("http://destinationEndpoint")))
{
// create a channel to send the resquest
IRouter router = factory.CreateChannel();
// get the response
var reply = router.ProcessarMensagem(incomingRequest);
}
This is a very simple example, but contains the base logic.

WCF Client, AllowCookies and clearing any current cookie?

I have a WPF client that is using WCF to call into a service hosted in IIS. My WCF client has AllowCookies='true' so that the forms authentication cookie that IIS is using is passed back and forth with each WCF call automatically. This all works just fine.
But I need the ability to clear out any forms authentication cookie my WCF client is caching so that my next request is not authenticated. Is there any way to do this?
On wcf client, you would have access to
HttpContext.Current.Request
Now this Request object contains cookies. You could loop over the cookie collection and remove the one you need.
foreach(var cookie in request.Cookies) { // }
An excellent article at code project which explains cookie management on WCF client
UPDATE
HttpContext is only available at server side, so my previous answer was incorrect as pointed by Phil.
The correct way to do it would be rather clumsy as you have get hold of HttpRequest itself
MyWebServiceClient client = new MyWebServiceClient();
using ( new OperationContextScope( client.InnerChannel ) )
{
HttpRequestMessageProperty request = new HttpRequestMessageProperty();
//get the instance of your AuthCookie and make it blank
request.Headers["AuthCookie"] = "";
OperationContext.Current.OutgoingMessageProperties[
HttpRequestMessageProperty.Name] = request;
client.InvokeSomeMethod();
}
Found this example here

How to perform GET web requests to WCF Service Without WCF Client?

I want to send a GET web Request to a WCF service:
for example to:
http://TheirServerIP:PortNumber/TheirService/TheirServiceName.svc?op=theirWCFmethod
i want to write a C# code in my page (web aplication) that send HTTP GET request to their service (without WCF Client)
can i do that ?
To create a WCF service that responds to HTTP GET or HTTP POST requests
http://msdn.microsoft.com/en-us/library/bb628610.aspx
Well, in that case, you need to create a WCF REST service, one that can be called from any language using any HTTP stack and no need for any WCF specifics.
Check out the WCF REST developer center for lots of great info on WCF REST services.
Basically, what it boils down to is
using the WebHttpBinding on your server side
defining a URL pattern to handle requests and their parameters
For the client part of this, use the answer Ladislav provided - just new up a HttpRequest object and make a HTTP GET request to a valid URL - that's all there is, really.
The basic approach to call HTTP resource is:
var request = HttpWebRequest.Create("YourURL");
request.Method = "GET";
var response = request.GetResponse();
...

WCF how to pass token for authentication?

I have a WCF service which would like to support basicHttpBinding and webHttpBinding. When the client successfully login, server will generate a token for client to pass to server on all the request make later. Question is how the client can pass the token to server? I don't want to add an extra parameter on every web method to hold the token.
Typically, the best way to do something like this is passing such "meta-information" in a WCF header. You can easily create a message inspector to extend WCF (it's really not that scary and hard to do!) which would inject the token into every outgoing request from the client, and retrieve it from the header and validate it on the server side.
There are a number of pretty good blog post out there showing you how to create a message inspector:
Richard Hallgren's WCF postings
Writing a WCF message inspector
Automatic Culture Flowing with WCF by using Custom Behaviour
Check out the two relevant interfaces to implement:
IClientMessageInspector on the client side, which has a BeforeSendRequest and AfterReceiveReply message to implement
IDispatchMessageInspector on the server side, which has a AfterReceiveRequest and BeforeSendReply method to implement